zoukankan      html  css  js  c++  java
  • 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
    ",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
  • 相关阅读:
    人生转折点:弃文从理
    人生第一站:大三暑假实习僧
    监听器启动顺序和java常见注解
    java常识和好玩的注释
    182. Duplicate Emails (Easy)
    181. Employees Earning More Than Their Managers (Easy)
    180. Consecutive Numbers (Medium)
    178. Rank Scores (Medium)
    177. Nth Highest Salary (Medium)
    176. Second Highest Salary(Easy)
  • 原文地址:https://www.cnblogs.com/Blue233333/p/7726946.html
Copyright © 2011-2022 走看看