【BZOJ】【2733】【HNOI2012】永无乡

平衡树+启发式合并+并查集

  因为要求一坨数中第k大的……用平衡树会很好维护……

  但又要求连通块?所以用并查集来维护……

  大概就是让并查集的fa和Treap的根是同一个节点吧……

TLE了N多发,可能是Treap的随机rank看脸的原因……QAQ

唯一过了的一次是小号……

  1 /**************************************************************
  2     Problem: 2733
  3     User: ProgrammingApe
  4     Language: C++
  5     Result: Accepted
  6     Time:2356 ms
  7     Memory:3640 kb
  8 ****************************************************************/
  9  
 10 //BZOJ 2733
 11 #include<cstdio>
 12 #include<cstdlib>
 13 #include<cstring>
 14 #include<iostream>
 15 #include<algorithm>
 16 #define rep(i,n) for(int i=0;i<n;++i)
 17 #define F(i,j,n) for(int i=j;i<=n;++i)
 18 #define D(i,j,n) for(int i=j;i>=n;--i)
 19 using namespace std;
 20  
 21 inline int getint(){
 22     int v=0,sign=1; char ch=getchar();
 23     while(ch<'0'||ch>'9') {if (ch=='-') sign=-1; ch=getchar();}
 24     while(ch>='0'&&ch<='9') {v=v*10+ch-'0'; ch=getchar();}
 25     return v*=sign;
 26 }
 27 /*******************tamplate********************/
 28 const int N=100010;
 29 struct node{
 30     int ch[2];
 31     int rk,v,size;
 32     node(){}
 33     #define L t[o].ch[0]
 34     #define R t[o].ch[1]
 35 }t[N];
 36 int fa[N],n;
 37 int getfa(int x){ return fa[x]==x ? x : getfa(fa[x]); }
 38 inline void push_up(int o){
 39     t[o].size=t[L].size+t[R].size+1;
 40 }
 41 inline void rotate(int &o,int d){
 42     int k=t[o].ch[!d];
 43     t[o].ch[!d]=t[k].ch[d];
 44     t[k].ch[d]=o;
 45     push_up(o);
 46     o=k;
 47 }
 48 inline void insert(int &o,int x){
 49     if (!o){
 50         o=x; t[o].size=1; L=R=0;
 51         t[o].rk=rand();
 52     }
 53     else{
 54         t[o].size++;
 55         if (t[x].v<t[o].v){
 56             insert(L,x);
 57             if (t[L].rk<t[o].rk) rotate(o,1);
 58         }
 59         else{
 60             insert(R,x);
 61             if (t[R].rk<t[o].rk) rotate(o,0);
 62         }
 63         push_up(o);
 64     }
 65 }
 66 inline void merge(int x,int y){//将x向y合并
 67     if (x==0) return;
 68     merge(t[x].ch[0],y); merge(t[x].ch[1],y);
 69     insert(y,x);
 70 }
 71 inline void solvemerge(){
 72     int x=getint(), y=getint();
 73     int f1=getfa(x),f2=getfa(y);
 74     if (f1==f2) return;
 75     if (t[f1].size>t[f2].size) swap(f1,f2);
 76     fa[f1]=f2;
 77     merge(f1,f2);
 78 }
 79 inline int kth(int o,int k){
 80     while(o){
 81         if (!o || k<=0 || k>t[o].size) return -1;
 82         int s=t[L].size;
 83         if (k==s+1) return o;
 84         else if (k<=s) o=L;
 85         else {o=R; k=k-s-1;}
 86     }
 87     return -1;
 88 }
 89 int main(){
 90     n=getint();
 91     int m=getint(),x,y;
 92     F(i,1,n){
 93         t[i].v=getint();
 94         fa[i]=i; t[i].size=1; t[i].ch[0]=t[i].ch[1]=0;
 95     }
 96     F(i,1,m) solvemerge();
 97     int q=getint();
 98     char cmd[3];
 99     F(i,1,q){
100         scanf("%s",cmd);
101         if (cmd[0]=='Q'){
102             x=getint(); y=getint();
103             int f1=getfa(x);
104             printf("%d
",kth(f1,y));
105         }
106         else solvemerge();
107     }
108     return 0;
109 }
View Code
原文地址:https://www.cnblogs.com/Tunix/p/4294774.html