普通平衡树
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 }
以上是关于普通平衡树的主要内容,如果未能解决你的问题,请参考以下文章