BZOJ 2733: [HNOI2012]永无乡
线段树合并
#include<cstdio> using namespace std; int cnt,F[100005],ls[2000005],rs[2000005],ID[2000005],sz[2000005],root[100005]; char s[15]; int find(int x){ if (F[x]!=x) F[x]=find(F[x]); return F[x]; } void insert(int &t,int l,int r,int x,int y){ if (!t) t=++cnt; sz[t]++; if (l==r){ ID[t]=y; return; } int mid=(l+r)>>1; if (x<=mid) insert(ls[t],l,mid,x,y); else insert(rs[t],mid+1,r,x,y); } int query(int t,int l,int r,int K){ if (l==r) return ID[t]; int mid=(l+r)>>1; if (K<=sz[ls[t]]) return query(ls[t],l,mid,K); else return query(rs[t],mid+1,r,K-sz[ls[t]]); } int merge(int x,int y){ if (!x || !y) return x^y; sz[x]+=sz[y]; ls[x]=merge(ls[x],ls[y]); rs[x]=merge(rs[x],rs[y]); return x; } int main(){ int n,m; scanf("%d%d",&n,&m); for (int i=1; i<=n; i++){ int x; scanf("%d",&x); insert(root[i],1,n,x,i); } for (int i=1; i<=n; i++) F[i]=i; for (int i=1; i<=m; i++){ int x,y; scanf("%d%d",&x,&y); int fx=find(x),fy=find(y); if (fx!=fy) { F[fy]=fx; root[fx]=merge(root[fx],root[fy]); } } int q; scanf("%d",&q); while (q--){ scanf("%s",s); if (s[0]=='Q'){ int x,k; scanf("%d%d",&x,&k); int fx=find(x); if (sz[root[fx]]<k) printf("-1\n"); else printf("%d\n",query(root[fx],1,n,k)); } else{ int x,y; scanf("%d%d",&x,&y); int fx=find(x),fy=find(y); if (fx!=fy){ F[fy]=fx; root[fx]=merge(root[fx],root[fy]); } } } return 0; }