线段树合并+并查集 || BZOJ 2733: [HNOI2012]永无乡 || Luogu P3224 [HNOI2012]永无乡
题解:
随便写写
代码:
1 #include<cstdio> 2 #include<cstring> 3 #include<iostream> 4 #include<algorithm> 5 using namespace std; 6 const int maxn=(1e5)+50,maxm=maxn,maxq=(3e5)+50; 7 int N,M,W[maxn],fa[maxn],root[maxn],U,V,num_treenode=0,Q,ans,belong[maxn]; 8 char c; 9 inline int getf(int x){ 10 if(fa[x]==x)return fa[x]; 11 fa[x]=getf(fa[x]); 12 return fa[x]; 13 } 14 struct Tree{int lc,rc,l,r,cnt;}tr[maxn*20]; 15 inline void Pushup(int x){ 16 int lc=tr[x].lc,rc=tr[x].rc; 17 tr[x].cnt=tr[lc].cnt+tr[rc].cnt; 18 return; 19 } 20 inline void Build(int x,int l,int r,int q){ 21 tr[x].l=l;tr[x].r=r;int mid=(l+r)>>1; 22 if(l==r){ 23 tr[x].cnt=1; 24 return; 25 } 26 if(q<=mid)Build(tr[x].lc=++num_treenode,l,mid,q); 27 else Build(tr[x].rc=++num_treenode,mid+1,r,q); 28 Pushup(x); 29 return; 30 } 31 inline int Merge(int u,int v){ 32 if(!u)return v; 33 if(!v)return u; 34 int l=tr[u].l,r=tr[u].r; 35 if(l==r){ 36 tr[u].cnt+=tr[v].cnt; 37 return u; 38 } 39 tr[u].lc=Merge(tr[u].lc,tr[v].lc); 40 tr[u].rc=Merge(tr[u].rc,tr[v].rc); 41 Pushup(u); 42 return u; 43 } 44 inline int Query(int x,int k){ 45 int l=tr[x].l,r=tr[x].r,lc=tr[x].lc,rc=tr[x].rc; 46 if(l==r)return l; 47 if(tr[lc].cnt>=k)return Query(lc,k); 48 else return Query(rc,k-tr[lc].cnt); 49 } 50 int main(){ 51 scanf("%d%d",&N,&M); 52 for(int i=1;i<=N;i++){ 53 scanf("%d",&W[i]); 54 fa[i]=i; 55 belong[W[i]]=i; 56 } 57 for(int i=1;i<=N;i++) 58 Build(root[i]=++num_treenode,1,N,W[i]); 59 for(int i=1;i<=M;i++){ 60 scanf("%d%d",&U,&V); 61 int fa1=getf(U),fa2=getf(V); 62 if(fa1!=fa2){ 63 Merge(root[fa1],root[fa2]); 64 fa[fa2]=fa1; 65 } 66 } 67 scanf("%d",&Q); 68 while(Q--){ 69 c=getchar(); 70 while(c!='Q'&&c!='B')c=getchar(); 71 scanf("%d%d",&U,&V); 72 if(c=='Q'){ 73 int f=getf(U); 74 ans=Query(root[f],V); 75 if(ans==0)ans=-1;else ans=belong[ans]; 76 printf("%d\n",ans); 77 } 78 else{ 79 int fa1=getf(U),fa2=getf(V); 80 if(fa1!=fa2){ 81 Merge(root[fa1],root[fa2]); 82 fa[fa2]=fa1; 83 } 84 } 85 } 86 return 0; 87 }
By:AlenaNuna