BZOJ3237:[AHOI2013]连通图(线段树分治,并查集)

时间:2022-01-07 21:32:48

Description

BZOJ3237:[AHOI2013]连通图(线段树分治,并查集)

Input

BZOJ3237:[AHOI2013]连通图(线段树分治,并查集)

Output

BZOJ3237:[AHOI2013]连通图(线段树分治,并查集)

Sample Input

4 5
1 2
2 3
3 4
4 1
2 4
3
1 5
2 2 3
2 1 2

Sample Output

Connected
Disconnected
Connected

HINT

N<=100000 M<=200000 K<=100000

Solution

线段树分治,根据询问把每条边存在的时间区间拆成几个区间,然后覆盖到线段树上,最后$DFS$一遍线段树。用带撤销的并查集维护一下连通块个数,到线段树叶子节点的时候根据连通块个数输出答案。

常数有点大……离$TLE$只有$0.3s$……在被卡的边缘疯狂试探……

Code

 #include<iostream>
#include<cstdio>
#include<vector>
#define N (100009)
using namespace std; int n,cnt,m,q,top,u[N<<],v[N<<];
int fa[N],dep[N];
pair<int,int>stack[N];
vector<int>p[N<<],Segt[N<<]; char buf[<<],*p1=buf,*p2=buf,obuf[<<],*O=obuf;
#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++) inline int read()
{
int x=,w=; char c=getchar();
while (c<'' || c>'') {if (c=='-') w=-; c=getchar();}
while (c>='' && c<='') x=x*+c-'', c=getchar();
return x*w;
} void Update(int now,int l,int r,int l1,int r1,int k)
{
if (l>r1 || r<l1) return;
if (l1<=l && r<=r1) {Segt[now].push_back(k); return;}
int mid=(l+r)>>;
Update(now<<,l,mid,l1,r1,k); Update(now<<|,mid+,r,l1,r1,k);
} int Find(int x)
{
return x==fa[x]?x:Find(fa[x]);
} void DFS(int now,int l,int r)
{
int mid=(l+r)>>,tmp=top;
for (int i=; i<Segt[now].size(); ++i)
{
int x=u[Segt[now][i]],y=v[Segt[now][i]];
int fx=Find(x),fy=Find(y);
if (fx==fy) continue;
if (dep[fx]>dep[fy]) swap(fx,fy);
fa[fx]=fy; dep[fy]+=(dep[fx]==dep[fy]); cnt--;
stack[++top]=make_pair(fx,fy);
}
if (l<r) DFS(now<<,l,mid), DFS(now<<|,mid+,r);
else puts(cnt==?"Connected":"Disconnected");
for (int i=top; i>tmp; --i)
{
int fx=stack[i].first,fy=stack[i].second;
fa[fx]=fx; dep[fy]-=(dep[fx]==dep[fy]); cnt++;
}
top=tmp;
} int main()
{
n=cnt=read(); m=read();
for (int i=; i<=n; ++i) fa[i]=i, dep[i]=;
for (int i=; i<=m; ++i) u[i]=read(), v[i]=read();
q=read();
for (int i=; i<=q; ++i)
{
int c=read();
for (int j=; j<=c; ++j) p[read()].push_back(i);
}
for (int i=; i<=m; ++i)
{
p[i].push_back(q+);
int last=;
for (int j=; j<p[i].size(); ++j)
Update(,,q,last,p[i][j]-,i), last=p[i][j]+;
}
DFS(,,q);
}