• bzoj2733[HNOI2012]永无乡


    bzoj2733[HNOI2012]永无乡

    题意:

    n个节点,每个节点有个权值,初始时有m次连通两点的操作,接下来有q次操作,每次可以连通两个点或求某个点所在连通块权值第k小的节点编号。n,m≤100000,q≤300000

    题解:

    treap启发式合并,就是暴力将小的树拆了插到大的树里,均摊复杂度O(log22n)。由于本弱用的是treap,不能维护fa数组,所以要并查集维护根节点。如果是splay就不用。

    代码:

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <algorithm>
     4 #include <cstdlib>
     5 #include <queue>
     6 #define inc(i,j,k) for(int i=j;i<=k;i++)
     7 #define maxn 100500
     8 using namespace std;
     9 
    10 int fa[maxn],rt[maxn],ch[maxn][2],v[maxn],sz[maxn],rnd[maxn];
    11 void update(int x){
    12     sz[x]=sz[ch[x][0]]+sz[ch[x][1]]+1;
    13 }
    14 void rot(int &x,bool lr){
    15     if(!x)return; int a=ch[x][lr]; ch[x][lr]=ch[a][!lr]; ch[a][!lr]=x;
    16     update(x); update(a); x=a; 
    17 }
    18 void insert(int &x,int y){
    19     if(!x){x=y; return;}
    20     if(v[y]<v[x])insert(ch[x][0],y);else insert(ch[x][1],y); update(x);
    21     if(ch[x][0]&&rnd[ch[x][0]]<rnd[x])rot(x,0);
    22     if(ch[x][1]&&rnd[ch[x][1]]<rnd[x])rot(x,1);
    23 }
    24 int find(int x,int k){
    25     if(sz[x]<k)return -1;
    26     if(sz[ch[x][0]]==k-1)return x;
    27     if(sz[ch[x][0]]<k-1)return find(ch[x][1],k-sz[ch[x][0]]-1);
    28     if(sz[ch[x][0]]>k-1)return find(ch[x][0],k);
    29 }
    30 queue <int> q;
    31 int fd(int x){return x==fa[x]?x:fa[x]=fd(fa[x]);}
    32 void merge(int xx,int yy){
    33     int x=fd(xx),y=fd(yy); if(x==y)return; if(sz[rt[x]]>sz[rt[y]])swap(x,y);
    34     fa[x]=y; while(! q.empty())q.pop(); q.push(rt[x]); y=rt[y];
    35     while(! q.empty()){
    36         int z=q.front(); q.pop(); sz[z]=1;
    37         if(ch[z][0])q.push(ch[z][0]); if(ch[z][1])q.push(ch[z][1]);
    38         ch[z][0]=ch[z][1]=0; insert(y,z);
    39     }
    40     rt[fa[x]]=y;
    41 }
    42 inline int read(){
    43     char ch=getchar(); int f=1,x=0;
    44     while(ch<'0'||ch>'9'){if(ch=='-')f=-1; ch=getchar();}
    45     while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
    46     return f*x;
    47 }
    48 int n,m;
    49 int main(){
    50     n=read(); m=read();
    51     inc(i,1,n)
    52         v[i]=read(),ch[i][0]=ch[i][1]=0,rnd[i]=rand(),fa[i]=rt[i]=i,sz[i]=1;
    53     inc(i,1,m){int a=read(),b=read(); merge(a,b);}
    54     m=read(); char opt[3];
    55     inc(i,1,m){
    56         scanf("%s",opt);
    57         if(opt[0]=='Q'){
    58             int a=read(),b=read(); printf("%d
    ",find(rt[fd(a)],b));
    59         }
    60         if(opt[0]=='B'){
    61             int a=read(),b=read(); merge(a,b);
    62         }
    63     }
    64     return 0;
    65 }

    201608608

  • 相关阅读:
    用java抓取网页信息!
    WPF之Binding对数据的转换(第五天)
    WPF读书笔记 x名称空间详解(第二天)
    WPF的UI布局(Layout)WPF读书笔记(第三天)
    WPF 数据绑定Bingding基础(第四天)
    WPF读书笔记(第一天)
    HelloWin程序(窗口与消息)
    django创建数据库表方法
    OpenSSH利用处理畸形长度密码造成的时间差,枚举系统用户(CVE20166210)
    ldap匿名访问测试脚本
  • 原文地址:https://www.cnblogs.com/YuanZiming/p/5778179.html
Copyright © 2020-2023  润新知