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 }
View Code

 

posted @ 2017-10-25 07:33  Blue233333  阅读(121)  评论(0编辑  收藏  举报