BZOJ2733: [HNOI2012]永无乡
n<=1e5个点,每个点有排名,m次连接把某两个岛屿连起来,然后q次操作:合并两个岛屿;查询某个岛屿能到的所有岛屿的第k名次是哪一个。
线段树合并,并查集!
小坑:合并两棵线段树之前,记得判断这两棵树是不是已经在一起了,如果是就不理他;
合并线段树用的是并查集根节点对应的线段树。
1 #include<cstring> 2 #include<cstdlib> 3 #include<cstdio> 4 //#include<assert.h> 5 #include<math.h> 6 #include<algorithm> 7 //#include<iostream> 8 using namespace std; 9 10 int n,m,q; 11 #define maxn 100011 12 struct SMT 13 { 14 struct Node 15 { 16 int cnt; 17 int l,r; 18 int ls,rs; 19 }a[maxn*20]; 20 int size; 21 SMT() {size=0;} 22 void up(int x) 23 { 24 const int &p=a[x].ls,&q=a[x].rs; 25 a[x].cnt=a[p].cnt+a[q].cnt; 26 } 27 void build(int &x,int L,int R,int pos) 28 { 29 x=++size; 30 a[x].l=L;a[x].r=R; 31 if (L==R) 32 { 33 a[x].cnt=1; 34 a[x].ls=a[x].rs=0; 35 } 36 else 37 { 38 const int mid=(L+R)>>1; 39 if (pos<=mid) build(a[x].ls,L,mid,pos); 40 else build(a[x].rs,mid+1,R,pos); 41 up(x); 42 } 43 } 44 void build(int &x,int pos) {build(x,1,n,pos);} 45 int query(int x,int k) 46 { 47 if (a[x].l==a[x].r) return a[x].l; 48 if (a[a[x].ls].cnt<k) return query(a[x].rs,k-a[a[x].ls].cnt); 49 return query(a[x].ls,k); 50 } 51 int combine(int x,int y) 52 { 53 if (!x || !y) return x+y; 54 a[x].ls=combine(a[x].ls,a[y].ls); 55 a[x].rs=combine(a[x].rs,a[y].rs); 56 // cout<<a[x].cnt<<','<<a[y].cnt<<":)"; 57 a[x].cnt+=a[y].cnt; 58 return x; 59 } 60 }t; 61 int root[maxn],rank[maxn],id[maxn]; 62 int ufs[maxn]; 63 int Find(int x) {return x==ufs[x]?x:(ufs[x]=Find(ufs[x]));} 64 void Union(int x,int y) 65 { 66 x=Find(x),y=Find(y); 67 if (x==y) return; 68 ufs[x]=y; 69 } 70 bool isdigit(char c) {return c>='0' && c<='9';} 71 int qread() 72 { 73 char c;int s=0;while (!isdigit(c=getchar())); 74 do s=s*10+c-'0'; while (isdigit(c=getchar()));return s; 75 } 76 int main() 77 { 78 scanf("%d%d",&n,&m); 79 for (int i=1;i<=n;i++) id[(rank[i]=qread())]=ufs[i]=i; 80 for (int i=1;i<=n;i++) t.build(root[i],rank[i]); 81 for (int i=1,x,y;i<=m;i++) 82 { 83 x=Find(qread()),y=Find(qread()); 84 if (x!=y) root[x]=t.combine(root[x],root[y]),Union(y,x); 85 } 86 q=qread();int x,y; 87 while (q--) 88 { 89 char c=getchar();while (c!='B' && c!='Q') c=getchar(); 90 if (c=='Q') 91 { 92 x=Find(qread()),y=qread(); 93 if (t.a[root[x]].cnt<y) puts("-1"); 94 else printf("%d\n",id[t.query(root[x],y)]); 95 } 96 else 97 { 98 x=Find(qread()),y=Find(qread()); 99 if (x!=y) root[x]=t.combine(root[x],root[y]),Union(y,x); 100 } 101 // for (int j=1;j<=n;j++) cout<<t.a[root[Find(j)]].cnt<<' ';cout<<endl; 102 } 103 return 0; 104 }