bzoj3082: Graph2 离线+线段树

Posted f321dd

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj3082: Graph2 离线+线段树相关的知识,希望对你有一定的参考价值。

经典问题。强制在线的话非常复杂。

考虑离线。

每条边的存在时间是一个区间,因此按时间建立一颗线段树,将每条边插入,拆成log条边。然后dfs线段树,每次并查集合并当前节点的所有边,到叶子节点时回答询问,回溯时撤销并查集的修改。

带撤销的并查集不能路径压缩,要按秩合并。

#include<bits/stdc++.h>
#define N 200005
#define M (l+r>>1)
#define P (k<<1)
#define S (k<<1|1)
#define L l,M,P
#define R M+1,r,S
#define Z int l=1,int r=q,int k=1
#define u first
#define v second
using namespace std;
struct io_t{
	operator int(){
		int x;
		scanf("%d",&x);
		return x;
	}
}it;
int n=it,m=it,s[N],t[N];
int p[N],u[N],v[N],j,q;
char d[N];
typedef pair<int,int> vec;
vec f[N],e[N];
vector<vec> a[1<<18];
int find(int i){
	return p[i]==i
	?i:find(p[i]);
}
void add(vec v,int s,int t,Z){
	if(s<=l&&r<=t)
		a[k].push_back(v);
	else{
		if(s<=M)
			add(v,s,t,L);
		if(t>M)
			add(v,s,t,R);
	}
}
void dfs(Z){
	for(int j=0;j!=a[k].size();++j){
		vec* i=&a[k][j];
		i->u=find(i->u);
		i->v=find(i->v);
		if(i->u^i->v){
			if(u[i->u]<u[i->v])
				swap(i->u,i->v);
			p[i->v]=i->u;
			u[i->u]+=u[i->v];
		}
	}
	if(l==r)
		d[l]^81?0:v[l]
		=find(f[l].u)
		^find(f[l].v);
	else{
		dfs(L);dfs(R);
	}
	for(int j=a[k].size()-1;~j;--j){
		vec* i=&a[k][j];
		if(i->u^i->v){
			p[i->v]=i->v;
			u[i->u]-=u[i->v];
		}
	}
}
int main(){
	for(int i=1;i<=n;++i)
		u[p[i]=i]=1;
	for(int i=1;i<=m;++i)
		e[i]=vec(it,it);
	q=it;
	for(int i=1;i<=q;++i){
		scanf(" %c%d",d+i,&j);
		if(d[i]==68)
			t[j]?0:t[j]=i;
		if(d[i]==81)
			f[i]=vec(j,it);
		if(d[i]==73&&++m){
			s[m]=i;
			e[m]=vec(j,it);
		}
	}
	for(int i=1;i<=m;++i)
		add(e[i],
		s[i],t[i]?t[i]:q);
	dfs();
	for(int i=1;i<=q;++i)
		if(d[i]==81)
			puts(v[i]?"No":"Yes");
}

  

以上是关于bzoj3082: Graph2 离线+线段树的主要内容,如果未能解决你的问题,请参考以下文章

BZOJ 3626: [LNOI2014]LCA 树链剖分 线段树 离线

BZOJ1969[Ahoi2005]LANE 航线规划 离线+树链剖分+线段树

BZOJ3626[LNOI2014]LCA 离线+树链剖分+线段树

bzoj1959[Ahoi2005]LANE 航线规划 离线处理+树链剖分+线段树

BZOJ2333 [SCOI2011]棘手的操作 离线 + 线段树

bzoj3545 && bzoj3551 Peaks(离线版&&在线版)