• 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
  • 相关阅读:
    Golang Gin 框架 Route备注
    golang的时区和神奇的time.Parse
    Linux下查看内存使用情况方法总结
    Golang 图片上绘制文字
    在linux中安装字体
    一键解决 go get golang.org/x 包失败
    go如何进行交叉编译
    Ubuntu中apt与apt-get命令的区别
    linux dns 工具包 -- bind-utils
    nohup 和 &的含义
  • 原文地址:https://www.cnblogs.com/Blue233333/p/7726946.html
Copyright © 2020-2023  润新知