bzoj2733[HNOI2012]永无乡
%%%lych_cys讲的线段树合并
蛮水的题,交上去一发MLE(made居然这年头还有128M的题,我瞎开了好多)一发AC
1 #include <bits/stdc++.h> 2 #define N 200001 3 #define mid (l+r>>1) 4 using namespace std; 5 int NODE,n,m,wei,root[N],p,q;char ch; 6 int fa[N],tr[N*20],rs[N*20],ls[N*20],rk[N]; 7 int getfa(int x) 8 { 9 if(fa[x]==x) return x; 10 else return fa[x]=getfa(fa[x]); 11 } 12 int change(int ac,int l,int r,int x) 13 { 14 int now=++NODE; 15 if(l==r) 16 { 17 ++tr[now]; 18 return now; 19 } 20 if(x<=mid) rs[now]=rs[ac],ls[now]=change(ls[ac],l,mid,x); 21 else ls[now]=ls[ac],rs[now]=change(rs[ac],mid+1,r,x); 22 tr[now]=tr[ls[now]]+tr[rs[now]]; 23 return now; 24 } 25 void merge(int x,int y) 26 { 27 tr[y]+=tr[x]; 28 if(!ls[y]) ls[y]=ls[x]; 29 else 30 if(ls[x]) merge(ls[x],ls[y]); 31 if(!rs[y]) rs[y]=rs[x]; 32 else 33 if(rs[x]) merge(rs[x],rs[y]); 34 } 35 int que(int now,int l,int r,int x) 36 { 37 while(l<r) 38 if(tr[ls[now]]<x) x-=tr[ls[now]],l=mid+1,now=rs[now]; 39 else r=mid,now=ls[now]; 40 return tr[now]?rk[l]:-1; 41 } 42 int main() 43 { 44 scanf("%d%d",&n,&m); 45 for(int i=1;i<=n;i++) 46 { 47 scanf("%d",&wei); 48 rk[wei]=i; 49 root[i]=change(0,1,n,wei); 50 fa[i]=i; 51 } 52 for(int i=1;i<=m;i++) 53 scanf("%d%d",&p,&q),merge(root[getfa(p)],root[getfa(q)]),fa[getfa(p)]=getfa(q); 54 scanf("%d",&m); 55 for(int i=1;i<=m;i++) 56 { 57 for(ch=getchar();!isalpha(ch);ch=getchar()); 58 scanf("%d%d",&p,&q); 59 if(ch=='B') merge(root[getfa(p)],root[getfa(q)]),fa[getfa(p)]=getfa(q); 60 if(ch=='Q') printf("%d\n",que(root[getfa(p)],1,n,q)); 61 } 62 return 0; 63 }