标签:
Treap模板题.支持如下几种操作:
1.插入;
2.删除;
3.rank(x);
4.kth(k);
5.pre(x);
6.suc(x);
写多了就熟了...昨天看了书,今天调试的时候敲了好多遍,感觉满脑子是tree+heap.
p.s.
1.rank,kth,pre,suc函数都可以写成非递归的形式.
2.remove函数有两种写法:
(1).LRJ白书上的方法:
如果待删除节点只有一个子树,则用该子树代替待删除节点,删除待删除节点即可.如果有两个子树,则将优先值小的(小根堆)子树旋转上去,再在另一 个子树中递归删除待删除节点,每次这样的旋转操作都会减小子树,最终会达到第一种情况.
(2).在题解里看来的方法:
如果待删除节点没有子树,那么可以直接删除.如果有子树,则不管有两个还是一个,将优先值小的子树旋转上去(这里注意可以将null的优先值设为 INF),然后再在另一个子树中递归删除节点,每次这样的旋转操作都会减小子树,最终会达到第一种情况.
#include <cstdio> #include <cstdlib> using namespace std; const int oo=~0u<<1; struct Treap{ struct node{ node* ch[2]; int v,s,r,c; node(int v,node *t):v(v){ ch[0]=ch[1]=t; r=rand(); s=c=1; } bool operator < (const node &rhs) const { return r<rhs.r; } void push_up(){ s=ch[0]->s+ch[1]->s+c; } }*root,*null; Treap(){ null=new node(0,0); null->s=null->c=0; null->r=oo; root=null; } void rotate(node* &o,bool d){ node* k=o->ch[!d]; o->ch[!d]=k->ch[d]; k->ch[d]=o; o->push_up(); k->push_up(); o=k; } void insert(node* &o,int x){ if(o==null) o=new node(x,null); else{ if(o->v==x){ o->c++; o->s++; } else{ bool d=x>o->v; insert(o->ch[d],x); if(o->ch[d]<o) rotate(o,!d); o->push_up(); } } } void remove(node* &o,int x){ if(o->v==x){ if(o->c>1) o->c--; else{ if(o->ch[0]!=null&&o->ch[1]!=null){ bool d=o->ch[0]<o->ch[1]; rotate(o,d); remove(o->ch[d],x); } else{ node* u=o; if(o->ch[0]==null) o=o->ch[1]; else o=o->ch[0]; delete u; } } } else{ bool d=x>o->v; remove(o->ch[d],x); } if(o!=null) o->push_up(); } int kth(node* o,int k){ int s=o->ch[0]->s+o->c; if(k>o->ch[0]->s&&k<=s) return o->v; if(k<=o->ch[0]->s) return kth(o->ch[0],k); else return kth(o->ch[1],k-s); } int rank(node *o,int x){ int s=o->ch[0]->s+o->c; if(x==o->v) return o->ch[0]->s+1; if(x<o->v) return rank(o->ch[0],x); else return s+rank(o->ch[1],x); } int pre(int x){ node* t=root; int ret=0; while(t!=null){ if(t->v<x){ ret=t->v; t=t->ch[1]; } else t=t->ch[0]; } return ret; } int suc(int x){ node *t=root; int ret=0; while(t!=null){ if(t->v>x){ ret=t->v; t=t->ch[0]; } else t=t->ch[1]; } return ret; } }tree; int main() { int n,a,b; scanf("%d",&n); while(n--){ scanf("%d%d",&a,&b); switch(a){ case(1):tree.insert(tree.root,b);break; case(2):tree.remove(tree.root,b);break; case(3):printf("%d\n",tree.rank(tree.root,b));break; case(4):printf("%d\n",tree.kth(tree.root,b));break; case(5):printf("%d\n",tree.pre(b));break; case(6):printf("%d\n",tree.suc(b));break; } } return 0; }
标签:
原文地址:http://www.cnblogs.com/Sunnie69/p/5483880.html