treap通过左右旋维护了一个二叉查找树,根据随机的优先级建立满足优先级大根堆的二叉查找树,在实践中有不错的食府,code也简单。
cogs1829 普通平衡树
题目大意:进行插入、删除、名次、前驱后继。
思路:前面的三种操作都很普通,前驱后继有两种做法(非常不正统吧。。。):1)找到这个数的名次,然后+-1,(如果是后继,并且和原数相同就名次+1,直到不同);2)进行递归查找,以前驱为例:如果这个点的值比x小,就更新一下前驱,找他的右子树,如果>=x,就找他的左子树。这里有可能出现插入多个重复的数,我们可以再开一个域num,记录这种数的个数,然后在操作中相应的进行更改。
#include<iostream> #include<cstdio> #include<cstdlib> using namespace std; struct Node{ Node *ch[2]; int r,v,s,num; Node(int v):v(v) {ch[0]=ch[1]=NULL;r=rand();s=1;num=1;} int cmp(int x) const{ if (x==v) return -1; else return x<v?0:1; } void Maintain(){ s=num; if (ch[0]!=NULL) s+=ch[0]->s; if (ch[1]!=NULL) s+=ch[1]->s; } }; Node* root; void rotate(Node* &o,int d) { Node* k=o->ch[d^1];o->ch[d^1]=k->ch[d];k->ch[d]=o; o->Maintain();k->Maintain();o=k; } void insert(Node* &o,int x) { if (o==NULL) o=new Node(x); else { int d=o->cmp(x); if (d==-1) ++o->num; else { insert(o->ch[d],x); if (o->ch[d] ->r > o->r) rotate(o,d^1); } } o->Maintain(); } void del(Node* &o,int x) { int d=o->cmp(x); if (d==-1) { if (o->num==1) { if (o->ch[0]==NULL) o=o->ch[1]; else { if (o->ch[1]==NULL) o=o->ch[0]; else { int d2=(o->ch[0] ->r > o->ch[1] ->r ? 1 : 0); rotate(o,d2);del(o->ch[d2],x); } } } else --o->num; } else del(o->ch[d],x); if (o!=NULL) o->Maintain(); } int rank(Node* &o,int x) { int d=o->cmp(x); if (d==-1) return (o->ch[0]==NULL ? 1 : o->ch[0] ->s +1); else { if (d==0) return rank(o->ch[d],x); else return rank(o->ch[d],x) + (o->ch[0]==NULL ? o->num : o->ch[0] ->s +o->num); } } int kth(Node* &o,int x) { if (o==NULL||x<=0||x > o->s) return 0; int s=(o->ch[0]==NULL ? 0 : o->ch[0] ->s); if (x>=s+1&&x<=s+ o->num) return o->v; if (x<=s) return kth(o->ch[0],x); else return kth(o->ch[1],x-s- o->num); } int main() { freopen("phs.in","r",stdin); freopen("phs.out","w",stdout); int n,i,j,x,t,k; scanf("%d",&n); for (i=1;i<=n;++i) { scanf("%d%d",&j,&x); if (j==1) insert(root,x); if (j==2) del(root,x); if (j==3) { t=rank(root,x); printf("%d\n",t); } if (j==4) { t=kth(root,x); printf("%d\n",t); } if (j==5) { insert(root,x); k=rank(root,x); t=kth(root,k-1); del(root,x); printf("%d\n",t); } if (j==6) { insert(root,x); k=rank(root,x); t=kth(root,k+1); while(t==x) { ++k;t=kth(root,k+1); } del(root,x); printf("%d\n",t); } } fclose(stdin); fclose(stdout); }
1)
#include<iostream> #include<cstdio> #include<cstdlib> using namespace std; struct Node{ Node *ch[2]; int r,v,s,num; Node(int v):v(v) {ch[0]=ch[1]=NULL;r=rand();s=1;num=1;} int cmp(int x) const{ if (x==v) return -1; else return x<v?0:1; } void Maintain(){ s=num; if (ch[0]!=NULL) s+=ch[0]->s; if (ch[1]!=NULL) s+=ch[1]->s; } }; Node* root; int t; void rotate(Node* &o,int d) { Node* k=o->ch[d^1];o->ch[d^1]=k->ch[d];k->ch[d]=o; o->Maintain();k->Maintain();o=k; } void insert(Node* &o,int x) { if (o==NULL) o=new Node(x); else { int d=o->cmp(x); if (d==-1) ++o->num; else { insert(o->ch[d],x); if (o->ch[d] ->r > o->r) rotate(o,d^1); } } o->Maintain(); } void del(Node* &o,int x) { int d=o->cmp(x); if (d==-1) { if (o->num==1) { if (o->ch[0]==NULL) o=o->ch[1]; else { if (o->ch[1]==NULL) o=o->ch[0]; else { int d2=(o->ch[0] ->r > o->ch[1] ->r ? 1 : 0); rotate(o,d2);del(o->ch[d2],x); } } } else --o->num; } else del(o->ch[d],x); if (o!=NULL) o->Maintain(); } int rank(Node* &o,int x) { int d=o->cmp(x); if (d==-1) return (o->ch[0]==NULL ? 1 : o->ch[0] ->s +1); else { if (d==0) return rank(o->ch[d],x); else return rank(o->ch[d],x) + (o->ch[0]==NULL ? o->num : o->ch[0] ->s +o->num); } } int kth(Node* &o,int x) { if (o==NULL||x<=0||x > o->s) return 0; int s=(o->ch[0]==NULL ? 0 : o->ch[0] ->s); if (x>=s+1&&x<=s+ o->num) return o->v; if (x<=s) return kth(o->ch[0],x); else return kth(o->ch[1],x-s- o->num); } void pre(Node* &o,int x) { if (o->v >=x) { if (o->ch[0]!=NULL) pre(o->ch[0],x); } else { t=max(t,o->v); if (o->ch[1]!=NULL) pre(o->ch[1],x); } } void succ(Node* &o,int x) { if (o->v <=x) { if (o->ch[1]!=NULL) succ(o->ch[1],x); } else { t=min(t,o->v); if (o->ch[0]!=NULL) succ(o->ch[0],x); } } int main() { freopen("phs.in","r",stdin); freopen("phs.out","w",stdout); int n,i,j,x; scanf("%d",&n); for (i=1;i<=n;++i) { scanf("%d%d",&j,&x); if (j==1) insert(root,x); if (j==2) del(root,x); if (j==3) { t=rank(root,x); printf("%d\n",t); } if (j==4) { t=kth(root,x); printf("%d\n",t); } if (j==5) { t=-2100000000; pre(root,x); printf("%d\n",t); } if (j==6) { t=2100000000; succ(root,x); printf("%d\n",t); } } fclose(stdin); fclose(stdout); }
2)
时间: 2024-10-02 18:41:54