普通平衡树

Posted cdcq(本博客废弃!现用博客:https://www.cn

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了普通平衡树相关的知识,希望对你有一定的参考价值。

平衡树模板题,然而WA惨了qaq,不过对平衡树理解加深还是不错的

原题:

您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:
1. 插入x数
2. 删除x数(若有多个相同的数,因只删除一个)
3. 查询x数的排名(若有多个相同的数,因输出最小的排名)
4. 查询排名为x的数
5. 求x的前驱(前驱定义为小于x,且最大的数)
6. 求x的后继(后继定义为大于x,且最小的数)

 

就是平衡树的个中操作没啥好说的= =,因为已经存在于平衡树中的权值也要插入,所以在每个节点上记录和这个节点重叠的个数,然后个中操作都很方便了

不过还是WA惨了,原因有二:

一曰:如果记录和节点重叠的个数,旋转的时候一定要把重叠的个数转移到size上,本来想size只是维护平衡的,没有考虑到还牵扯到rank和select,我还是太弱了qaq

二曰:maintainTMD也是关键字 maintainTMD也是关键字 maintainTMD也是关键字 maintainTMD也是关键字 maintainTMD也是关键字 maintainTMD也是关键字 maintainTMD也是关键字 maintainTMD也是关键字 maintainTMD也是关键字 maintainTMD也是关键字 maintainTMD也是关键字 maintainTMD也是关键字 maintainTMD也是关键字 maintainTMD也是关键字 maintainTMD也是关键字 maintainTMD也是关键字 maintainTMD也是关键字 maintainTMD也是关键字 maintainTMD也是关键字 maintainTMD也是关键字 maintainTMD也是关键字 maintainTMD也是关键字 maintainTMD也是关键字 maintainTMD也是关键字 

要用Maintain或smaintain

小技巧:

else if(tree[x].lchild && !tree[x].rchild)  x=tree[x].lchild;

else if(tree[x].rchild && !tree[x].lchild)  x=tree[x].rchild;

可以把if(!tree[x].lchild && !tree[x].rchild)放在前面,然后上面的就可以简化为

if(!(tree[x].lchild*tree[x].rchild))  x=tree[x].lchild+tree[x].rchild;

代码:

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<algorithm>
  4 #include<cstring>
  5 #include<cmath>
  6 using namespace std;
  7 const int oo=168430090;
  8 int read(){int z=0,mark=1;  char ch=getchar();
  9     while(ch<\'0\'||ch>\'9\'){if(ch==\'-\')mark=-1;  ch=getchar();}
 10     while(ch>=\'0\'&&ch<=\'9\'){z=(z<<3)+(z<<1)+ch-\'0\';  ch=getchar();}
 11     return z*mark;
 12 }
 13 int n;
 14 int wans[1100000],wtou=0;
 15 int q[1100000];
 16 struct dcd{int lchild,rchild,size,tvalue,ge;}tree[1110000];  int ttop=0,root=0;
 17 void left_rotate(int &x){
 18     int y=tree[x].rchild;
 19     tree[x].rchild=tree[y].lchild;
 20     tree[y].lchild=x;
 21     tree[y].size=tree[x].size;
 22     tree[x].size=tree[tree[x].lchild].size+tree[tree[x].rchild].size+tree[x].ge;//注意这里一定要把相同的个数带下去
 23     x=y;
 24 }
 25 void right_rotate(int &x){
 26     int y=tree[x].lchild;
 27     tree[x].lchild=tree[y].rchild;
 28     tree[y].rchild=x;
 29     tree[y].size=tree[x].size;
 30     tree[x].size=tree[tree[x].lchild].size+tree[tree[x].rchild].size+tree[x].ge;//本来想size只是维护平衡的,没有考虑到还牵扯到rank和select,我还是太弱了qaq
 31     x=y;
 32 }
 33 void Maintain(int &x,bool flag){
 34     if(!flag){
 35         if(tree[tree[tree[x].lchild].lchild].size>tree[tree[x].rchild].size)  right_rotate(x);
 36         else if(tree[tree[tree[x].lchild].rchild].size>tree[tree[x].rchild].size)  left_rotate(tree[x].lchild),right_rotate(x);
 37         else  return ;
 38     }
 39     else{
 40         if(tree[tree[tree[x].rchild].rchild].size>tree[tree[x].lchild].size)  left_rotate(x);
 41         else if(tree[tree[tree[x].rchild].lchild].size>tree[tree[x].lchild].size)  right_rotate(tree[x].rchild),left_rotate(x);
 42         else  return ;
 43     }
 44     Maintain(tree[x].lchild,false),Maintain(tree[x].rchild,true);
 45     Maintain(x,1),Maintain(x,0);
 46 }
 47 void insert(int &x,int z){
 48     if(!x){
 49         x=++ttop;
 50         tree[x].size=tree[x].ge=1;
 51         tree[x].lchild=tree[x].rchild=0;
 52         tree[x].tvalue=z;
 53     }
 54     else{
 55         tree[x].size++;
 56         if(tree[x].tvalue==z){  tree[x].ge++;  return; }
 57         else if(z<tree[x].tvalue)  insert(tree[x].lchild,z);
 58         else  insert(tree[x].rchild,z);
 59         Maintain(x,z>tree[x].tvalue);
 60     }
 61 }
 62 void remove(int &x,int z){
 63     if(!x)  return ;
 64     tree[x].size--;
 65     if(z>tree[x].tvalue)  remove(tree[x].rchild,z);
 66     else  if(z<tree[x].tvalue)  remove(tree[x].lchild,z);
 67     else{
 68         if(tree[x].ge>1)  tree[x].ge--;
 69         else if(!tree[x].lchild && !tree[x].rchild)  x=0;
 70         else if(!(tree[x].lchild*tree[x].rchild))  x=tree[x].lchild+tree[x].rchild;
 71         else{
 72             int temp;
 73             if(tree[x].rchild){
 74                 temp=tree[x].rchild;
 75                 while(tree[temp].lchild)  temp=tree[temp].lchild;
 76             }
 77             else{
 78                 temp=tree[x].lchild;
 79                 while(tree[temp].rchild)  temp=tree[temp].rchild;
 80             }
 81             tree[x].tvalue=tree[temp].tvalue;
 82             remove(tree[x].rchild,tree[temp].tvalue);
 83         }
 84     }
 85 }
 86 int select(int &x,int y){
 87     if(!x)  return 0;
 88     if(y<=tree[tree[x].lchild].size)  return select(tree[x].lchild,y);
 89     else if(y>tree[tree[x].lchild].size+tree[x].ge)  return select(tree[x].rchild,y-tree[tree[x].lchild].size-tree[x].ge);
 90     else return tree[x].tvalue;
 91 }
 92 int rank(int &x,int y){
 93     if(!x)  return 0;
 94     if(y>tree[x].tvalue)  return tree[tree[x].lchild].size+tree[x].ge+rank(tree[x].rchild,y);
 95     else if(y<tree[x].tvalue)  return rank(tree[x].lchild,y);
 96     else  return tree[tree[x].lchild].size+1;
 97 }
 98 int predecessor(int &x,int _father,int z){
 99     if(!x)  return tree[_father].tvalue;
100     if(z>tree[x].tvalue)  return predecessor(tree[x].rchild,x,z);
101     else  return predecessor(tree[x].lchild,_father,z);
102 }
103 int successor(int &x,int _father,int z){
104     if(!x)  return tree[_father].tvalue;
105     if(z<tree[x].tvalue)  return successor(tree[x].lchild,x,z);
106     else  return successor(tree[x].rchild,_father,z);
107 }
108 int main(){
109     //freopen("ddd.in","r",stdin);
110     //freopen("ddd.out","w",stdout);
111     freopen("phs.in","r",stdin);
112     freopen("phs.out","w",stdout);
113     cin>>n;
114     int _left,_right;
115     while(n --> 0){//趋向于
116         _left=read(),_right=read();
117         if(_left==1)  insert(root,_right);
118         else if(_left==2)  remove(root,_right);
119         else if(_left==3)  printf("%d\\n",wans[++wtou]=rank(root,_right));
120         else if(_left==4)  printf("%d\\n",wans[++wtou]=select(root,_right));
121         else if(_left==5)  printf("%d\\n",wans[++wtou]=predecessor(root,0,_right));
122         else  printf("%d\\n",wans[++wtou]=successor(root,0,_right));
123         if(_left>=3)  q[wtou]=_left;
124     }
125     /*int _bans;
126     for(int i=1;i<=wtou;i++){
127         _bans=read();
128         if(_bans!=wans[i]){
129             cout<<_bans<<" "<<wans[i]<<" "<<q[i]<<endl;
130         }
131     }*/
132     return 0;
133 }
View Code

 

以上是关于普通平衡树的主要内容,如果未能解决你的问题,请参考以下文章

普通平衡树(分块版)

[模板]普通平衡树

可持久化平衡树

[bzoj3224]普通平衡树

替罪羊树模版 普通平衡树

Luogu P3369 模板普通平衡树