bzoj2733 永无乡 平衡树按秩合并
链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2733
题意:动态连边,求出某个联通块中权值第$k$小的点。
首先,看到名次果断想平衡树……查询这个问题很好解决,但是合并……恐怕只能暴力修改了吧……
这时候我们需要一个武器:启发式合并,通俗的讲就是小的插到大的里面去突然污了起来。我们可以想象一下,如果把大的那棵树合并到小的那棵去,那么每个节点暴力合并……时间代价不堪设想……因此按秩合并可以有效减短合并时间……然后就是暴力插点删点就行了……
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #define lc(x) ((x)->ch[0]) 6 #define rc(x) ((x)->ch[1]) 7 #define size(x) ((x)?(x->siz):0) 8 using namespace std; 9 const int maxn=100005; 10 int n,m; 11 struct node 12 { 13 int val,fix,siz,id; 14 node *ch[2]; 15 node(){} 16 node(int v=0,int d=0):val(v),fix(rand()),id(d),siz(1){memset(ch,0,sizeof(ch));} 17 void maintain(){siz=1+size(ch[0])+size(ch[1]);} 18 }; 19 struct Treap 20 { 21 node *root[maxn]; 22 void rotate(node* &rt,int d) 23 { 24 node *t=rt->ch[d^1];rt->ch[d^1]=t->ch[d];t->ch[d]=rt; 25 rt->maintain();t->maintain();rt=t; 26 } 27 void insert(node* &rt,int x,int y) 28 { 29 if(!rt){rt=new node(x,y);return;} 30 int d=rt->val>x;insert(rt->ch[d^1],x,y);rt->maintain(); 31 if(rt->ch[d^1]->fix<rt->fix)rotate(rt,d); 32 rt->maintain(); 33 } 34 void del(node* &rt,int x) 35 { 36 if(rt->val==x) 37 { 38 if(lc(rt)&&rc(rt)) 39 { 40 int d=lc(rt)->fix>rc(rt)->fix; 41 rotate(rt,d);del(rt->ch[d],x); 42 } 43 else 44 { 45 node *t=NULL; 46 if(lc(rt))t=lc(rt);else t=rc(rt); 47 delete(rt);rt=t; 48 } 49 } 50 else 51 { 52 int d=rt->val>x; 53 del(rt->ch[d^1],x);rt->maintain(); 54 if(rt->ch[d^1]->fix>rt->fix)rotate(rt,d); 55 } 56 } 57 int rank(node *rt,int x) 58 { 59 int res=0; 60 while(rt) 61 if(x>rt->val)res+=size(lc(rt))+1,rt=rc(rt); 62 else rt=lc(rt); 63 return res; 64 } 65 int kth(node *rt,int x) 66 { 67 while(rt) 68 { 69 if(size(lc(rt))+1==x)return rt->id; 70 if(size(lc(rt))+1>x)rt=lc(rt); 71 else x-=size(lc(rt))+1,rt=rc(rt); 72 } 73 return -1; 74 } 75 void mergeto(node* src,node* &to) 76 { 77 if(lc(src))mergeto(lc(src),to); 78 if(rc(src))mergeto(rc(src),to); 79 insert(to,src->val,src->id); 80 delete src,src=NULL; 81 } 82 }T; 83 int f[maxn]; 84 int getfa(int x) 85 { 86 return f[x]==x?x:f[x]=getfa(f[x]); 87 } 88 void unionn(int x,int y) 89 { 90 x=getfa(x),y=getfa(y); 91 if(x!=y) 92 { 93 if(T.root[x]->siz<T.root[y]->siz)f[x]=y,T.mergeto(T.root[x],T.root[y]); 94 else f[y]=x,T.mergeto(T.root[y],T.root[x]); 95 } 96 } 97 int a[maxn]; 98 int haha() 99 { 100 scanf("%d%d",&n,&m); 101 for(int i=1;i<=n;i++)scanf("%d",&a[i]),T.root[i]=new node(a[i],i),f[i]=i; 102 for(int i=1;i<=m;i++) 103 { 104 int x,y;scanf("%d%d",&x,&y); 105 unionn(x,y); 106 } 107 int q;scanf("%d",&q); 108 for(int i=1;i<=q;i++) 109 { 110 char opt[3];int x,y;scanf("%s%d%d",opt,&x,&y); 111 if(opt[0]=='Q')printf("%d\n",T.kth(T.root[getfa(x)],y)); 112 else unionn(x,y); 113 } 114 } 115 int sb=haha(); 116 int main(){;}
只要是活着的东西,就算是神我也杀给你看。