考虑CDQ分治 把这半边对后半边没有影响的操作做了 然后分治
用并查集维护 开个栈暴力还原
UPD:找到一个新做法:http://www.cnblogs.com/clrs97/p/4403252.html
#include<cstdio>
#include<cstdlib>
using namespace std;
inline char nc()
{
static char buf[100000],*p1=buf,*p2=buf;
if (p1==p2) { p2=(p1=buf)+fread(buf,1,100000,stdin); if (p1==p2) return EOF; }
return *p1++;
}
inline void read(int &x)
{
char c=nc(),b=1;
for (;!(c>='0' && c<='9');c=nc()) if (c=='-') b=-1;
for (x=0;c>='0' && c<='9';x=x*10+c-'0',c=nc()); x*=b;
}
const int N=200005;
struct edge{
int u,v;
}edges[N];
struct abcd{
int idx;
int c,e[5];
}eve[N];
int n,m,K;
int clk,del[N];
int ans[N];
int fat[N];
int Stk[50*N],pnt;
inline int Fat(int u){
if (fat[u]==u) return u;
Stk[++pnt]=u; Stk[++pnt]=fat[u];
return fat[u]=Fat(fat[u]);
}
inline void Union(int x,int y){
int fx=Fat(x),fy=Fat(y);
if (fx!=fy)
Stk[++pnt]=fx,Stk[++pnt]=fat[fx],fat[fx]=fy;
}
inline void Restore(int bot){
while (pnt!=bot)
fat[Stk[pnt-1]]=Stk[pnt],pnt-=2;
}
inline void Solve(int l,int r){
int bot=pnt;
if (l==r){
int flag=1;
for (int i=1;i<=eve[l].c && flag;i++)
if (Fat(edges[eve[l].e[i]].u)!=Fat(edges[eve[l].e[i]].v))
flag=0;
ans[eve[l].idx]=flag;
Restore(bot);
return;
}
int mid=(l+r)>>1;
clk++;
for (int i=l;i<=mid;i++)
for (int j=1;j<=eve[i].c;j++)
del[eve[i].e[j]]=clk;
for (int i=mid+1;i<=r;i++)
for (int j=1;j<=eve[i].c;j++)
if (del[eve[i].e[j]]!=clk)
Union(edges[eve[i].e[j]].u,edges[eve[i].e[j]].v);
Solve(l,mid);
Restore(bot);
clk++;
for (int i=mid+1;i<=r;i++)
for (int j=1;j<=eve[i].c;j++)
del[eve[i].e[j]]=clk;
for (int i=l;i<=mid;i++)
for (int j=1;j<=eve[i].c;j++)
if (del[eve[i].e[j]]!=clk)
Union(edges[eve[i].e[j]].u,edges[eve[i].e[j]].v);
Solve(mid+1,r);
Restore(bot);
}
int main()
{
freopen("t.in","r",stdin);
freopen("t.out","w",stdout);
read(n); read(m);
for (int i=1;i<=n;i++) fat[i]=i;
for (int i=1;i<=m;i++)
read(edges[i].u),read(edges[i].v);
read(K);
for (int i=1;i<=K;i++)
{
read(eve[i].c); eve[i].idx=i;
for (int j=1;j<=eve[i].c;j++) read(eve[i].e[j]);
}
++clk;
for (int i=1;i<=K;i++)
for (int j=1;j<=eve[i].c;j++)
del[eve[i].e[j]]=clk;
for (int i=1;i<=m;i++)
if (del[i]!=clk)
Union(edges[i].u,edges[i].v);
Solve(1,K);
for (int i=1;i<=K;i++)
ans[i]?printf("Connected\n"):printf("Disconnected\n");
return 0;
}