N个点M条边的无向图,询问保留图中编号在[l,r]的边的时候图中的联通块个数。
N个点M条边的无向图,询问保留图中编号在[l,r]的边的时候图中的联通块个数。
第一行四个整数N、M、K、type,代表点数、边数、询问数以及询问是否加密。
接下来M行,代表图中的每条边。
接下来K行,每行两个整数L、R代表一组询问。对于type=0的测试点,读入的L和R即为询问的L、R;对于type=1的测试点,每组询问的L、R应为L xor lastans和R xor lastans。
K行每行一个整数代表该组询问的联通块个数。
对于100%的数据,1≤N、M、K≤200,000。
1 #include<cstdio> 2 #include<iostream> 3 #include<cmath> 4 #include<cstring> 5 #include<algorithm> 6 using namespace std; 7 char ch; 8 bool ok; 9 void read(int &x){ 10 for (ok=0,ch=getchar();!isdigit(ch);ch=getchar()) if (ch=='-') ok=1; 11 for (x=0;isdigit(ch);x=x*10+ch-'0',ch=getchar()); 12 if (ok) x=-x; 13 } 14 const int maxn=400005; 15 const int maxnode=4000000; 16 const int inf=2147483647; 17 int n,m,q,type,a[maxn],b[maxn],l,r,pos[maxn],pop[maxn],root[maxn],ans; 18 struct LCT{ 19 int son[maxn][2],fa[maxn],val[maxn],minv[maxn],pos[maxn],id[maxn],rev[maxn]; 20 void init(int x,int v,int i){val[x]=minv[x]=v,pos[x]=id[x]=i;} 21 int which(int x){return son[fa[x]][1]==x;} 22 bool isroot(int x){return son[fa[x]][0]!=x&&son[fa[x]][1]!=x;} 23 void reverse(int x){if (x) rev[x]^=1;} 24 void pushdown(int x){if (rev[x]) swap(son[x][0],son[x][1]),reverse(son[x][0]),reverse(son[x][1]),rev[x]=0;} 25 void relax(int x){if (!isroot(x)) relax(fa[x]); pushdown(x);} 26 void update(int x,int y){if (minv[x]>minv[y]) minv[x]=minv[y],pos[x]=pos[y];} 27 void update(int x){ 28 minv[x]=val[x],pos[x]=id[x]; 29 if (son[x][0]) update(x,son[x][0]); 30 if (son[x][1]) update(x,son[x][1]); 31 } 32 void rotate(int x){ 33 int y=fa[x],z=fa[y],d=which(x),dd=which(y); 34 fa[son[x][d^1]]=y,son[y][d]=son[x][d^1],fa[x]=fa[y]; 35 if (!isroot(y)) son[z][dd]=x; 36 son[x][d^1]=y,fa[y]=x,update(y),update(x); 37 } 38 void splay(int x){ 39 relax(x); 40 while (!isroot(x)){ 41 if (isroot(fa[x])) rotate(x); 42 else if (which(x)==which(fa[x])) rotate(fa[x]),rotate(x); 43 else rotate(x),rotate(x); 44 } 45 } 46 void access(int x){for (int p=0;x;x=fa[x]) splay(x),fa[son[x][1]=p]=x,update(p=x);} 47 void make_root(int x){access(x),splay(x),reverse(x);} 48 int find(int x){ 49 access(x),splay(x); 50 for (;son[x][0];x=son[x][0]) pushdown(x); 51 return x; 52 } 53 int query(int x,int y){ 54 if (find(x)==find(y)){make_root(x),access(y),splay(y);return pos[y];} 55 else return 0; 56 } 57 void cut(int x,int y){make_root(x),access(y),splay(y),fa[x]=0,son[y][0]=0;} 58 void link(int x,int y){make_root(x),fa[x]=y;} 59 }lct; 60 struct seg{ 61 int tot,sum[maxnode],son[maxnode][2]; 62 void insert(int p,int &k,int l,int r,int x){ 63 sum[k=++tot]=sum[p]+1; 64 if (l==r) return; 65 int m=(l+r)>>1; 66 if (x<=m) son[k][1]=son[p][1],insert(son[p][0],son[k][0],l,m,x); 67 else son[k][0]=son[p][0],insert(son[p][1],son[k][1],m+1,r,x); 68 } 69 int query(int k,int l,int r,int x){ 70 if (l==r) return sum[k]; 71 int m=(l+r)>>1; 72 if (x<=m) return query(son[k][0],l,m,x); 73 else return sum[son[k][0]]+query(son[k][1],m+1,r,x); 74 } 75 int query(int a,int b,int x){return query(b,0,m,x)-query(a,0,m,x);} 76 }T; 77 int main(){ 78 read(n),read(m),read(q),read(type); 79 for (int i=1;i<=n;i++) lct.init(i,inf,0); 80 for (int i=1;i<=m;i++) lct.init(n+i,i,i); 81 for (int i=1;i<=m;i++){ 82 read(a[i]),read(b[i]); 83 if (a[i]!=b[i]){ 84 pop[i]=lct.query(a[i],b[i]); 85 if (pop[i]) lct.cut(a[pop[i]],pop[i]+n),lct.cut(b[pop[i]],pop[i]+n); 86 lct.link(a[i],n+i),lct.link(b[i],n+i); 87 } 88 else pop[i]=i; 89 } 90 for (int i=1;i<=m;i++) T.insert(root[i-1],root[i],0,m,pop[i]); 91 while (q--){ 92 read(l),read(r); 93 if (type) l^=ans,r^=ans; 94 ans=n-T.query(root[l-1],root[r],l-1); 95 printf("%d\n",ans); 96 } 97 return 0; 98 }