ZHX的题目。
类似于HH的项链我们考虑最后加入哪一条边以后合并了两个联通块,所以我们边权从大到小排然后依次加入。找出最晚加入的,记成last。
然后做主席树就好啦!
注意拆边为点。
By:大奕哥
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int N=1e6+5; 4 int c[N][2],mx[N],fa[N],w[N],pos[N],rev[N],s[N]; 5 int last[N],rt[N],cnt,n,m,k,type,ans,l,r; 6 struct node{ 7 int s,l,r; 8 }t[N<<2]; 9 struct edge{ 10 int x,y; 11 }a[N]; 12 bool isroot(int x){return c[fa[x]][0]!=x&&c[fa[x]][1]!=x;} 13 void update(int x) 14 { 15 mx[x]=w[x];pos[x]=x; 16 if(mx[x]<mx[c[x][0]])mx[x]=mx[c[x][0]],pos[x]=pos[c[x][0]]; 17 if(mx[x]<mx[c[x][1]])mx[x]=mx[c[x][1]],pos[x]=pos[c[x][1]]; 18 return; 19 } 20 void pushup(int x) 21 { 22 if(rev[x]) 23 { 24 rev[x]^=1;rev[c[x][0]]^=1;rev[c[x][1]]^=1; 25 swap(c[x][0],c[x][1]); 26 } 27 return; 28 } 29 void rotate(int x) 30 { 31 int y=fa[x],z=fa[y],l,r; 32 l=c[y][1]==x;r=l^1; 33 if(!isroot(y))c[z][c[z][1]==y]=x; 34 fa[x]=z;fa[y]=x;fa[c[x][r]]=y; 35 c[y][l]=c[x][r];c[x][r]=y; 36 update(y);update(x); 37 return; 38 } 39 void splay(int x) 40 { 41 int top=0,i; 42 for(i=x;!isroot(i);i=fa[i])s[++top]=i;s[++top]=i; 43 for(i=top;i;--i)pushup(s[i]); 44 while(!isroot(x)) 45 { 46 // cout<<x<<endl; 47 int y=fa[x],z=fa[y]; 48 if(!isroot(y)) 49 { 50 if(c[y][0]==x^c[z][0]==y)rotate(x); 51 else rotate(y); 52 } 53 rotate(x); 54 } 55 return; 56 } 57 void access(int x) 58 { 59 int y=0; 60 while(x) 61 { 62 splay(x); 63 c[x][1]=y; 64 y=x;x=fa[x]; 65 } 66 return; 67 } 68 void mroot(int x) 69 { 70 access(x);splay(x);rev[x]^=1; 71 } 72 void cut(int x,int y) 73 { 74 mroot(x);access(y);splay(y);c[y][0]=fa[x]=0; 75 } 76 void link(int x,int y) 77 { 78 mroot(x);fa[x]=y;splay(x); 79 } 80 int query(int x,int y) 81 { 82 mroot(x);access(y);splay(y);return pos[c[y][0]]; 83 } 84 int f[N]; 85 inline int get(int x) 86 { 87 return x==f[x]?x:f[x]=get(f[x]); 88 } 89 void solve() 90 { 91 for(int i=1;i<=n+m;++i)f[i]=i; 92 for(int i=1;i<=m;++i) 93 { 94 int fx=get(a[i].x);int fy=get(a[i].y); 95 if(a[i].x==a[i].y){ 96 last[i]=i;continue; 97 } 98 if(fx==fy) 99 { 100 int tmp=query(a[i].x,a[i].y); 101 last[i]=tmp-n; 102 cut(tmp,a[tmp-n].x);cut(tmp,a[tmp-n].y); 103 } 104 link(a[i].x,i+n);link(a[i].y,i+n);f[fx]=fy; 105 } 106 return; 107 } 108 void change(int &x,int l,int r,int pos) 109 { 110 t[++cnt]=t[x];x=cnt; 111 if(l==r){ 112 t[x].s++;return; 113 } 114 int mid=l+r>>1; 115 if(pos>mid)change(t[x].r,mid+1,r,pos); 116 else change(t[x].l,l,mid,pos); 117 t[x].s=t[t[x].l].s+t[t[x].r].s; 118 return; 119 } 120 int querysum(int x,int y,int l,int r,int L,int R) 121 { 122 if(l==L&&r==R)return t[y].s-t[x].s; 123 int mid=l+r>>1; 124 if(mid>=R)return querysum(t[x].l,t[y].l,l,mid,L,R); 125 else if(mid<L)return querysum(t[x].r,t[y].r,mid+1,r,L,R); 126 else return querysum(t[x].l,t[y].l,l,mid,L,mid)+querysum(t[x].r,t[y].r,mid+1,r,mid+1,R); 127 } 128 void work() 129 { 130 for(int i=1;i<=m;++i)rt[i]=rt[i-1],change(rt[i],0,m,last[i]); 131 for(int i=1;i<=k;++i) 132 { 133 scanf("%d%d",&l,&r);if(type)l^=ans,r^=ans; 134 ans=querysum(rt[l-1],rt[r],0,m,0,l-1);ans=n-ans; 135 printf("%d ",ans); 136 } 137 } 138 int main() 139 { 140 scanf("%d%d%d%d",&n,&m,&k,&type); 141 for(int i=1;i<=m;++i) 142 { 143 scanf("%d%d",&a[i].x,&a[i].y); 144 w[i+n]=m+n-i+1;mx[i+n]=m+n-i+1;pos[i+n]=i+n; 145 } 146 solve(); 147 work(); 148 return 0; 149 }