考虑CDQ分治 把这半边对后半边没有影响的操作做了 然后分治
用并查集维护 开个栈暴力还原
#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; }