【模板】Splay

 

 

  1 #include<cstdio>
  2 #include<algorithm>
  3 #define ls (a[u].l)
  4 #define rs (a[u].r)
  5 #define fa (a[u].f)
  6 using namespace std;
  7 const int maxn=200010;
  8 int n,opt,x,root,size;
  9 struct tree{int f,l,r,val,cnt,size;}a[maxn];
 10 inline int read(){
 11     int k=0,f=1; char c=getchar();
 12     while(c<'0'||c>'9')c=='-'&&(f=-1),c=getchar();
 13     while('0'<=c&&c<='9')k=k*10+c-'0',c=getchar();
 14     return k*f;
 15 }
 16 inline void clear(int u){a[u]=(tree){0,0,0,0,0,0};}//将当前结点的各项值都清零 
 17 inline bool which(int u){return a[fa].l==u;}//判断当前节点是父亲的左孩子还是右孩子
 18 inline void update(int u){//发生修改之后,更新当前节点的size值 
 19     if(!u) return;
 20     a[u].size=a[u].cnt;
 21     if(ls) a[u].size+=a[ls].size;
 22     if(rs) a[u].size+=a[rs].size;
 23 }
 24 inline void rotate(int u){
 25     int f=a[u].f,gf=a[f].f;
 26     if(which(u)){
 27         a[f].l=a[u].r;
 28         a[rs].f=f;
 29         a[u].r=f;
 30     }
 31     else{
 32         a[f].r=a[u].l;
 33         a[ls].f=f;
 34         a[u].l=f;
 35     }
 36     a[f].f=u; a[u].f=gf;
 37     if(gf){
 38         if(a[gf].l==f) a[gf].l=u;
 39         else a[gf].r=u;
 40     }
 41     update(f); update(u);
 42 } 
 43 inline void splay(int u){
 44     for(int f;f=a[u].f;rotate(u)){
 45         //printf("QAQ %d\n",f);
 46         if(a[f].f) rotate(which(u)==which(f)?f:u);
 47     }
 48     root=u;
 49 }
 50 inline int pre(){
 51      int now=a[root].l;
 52      while(a[now].r) now=a[now].r;
 53      return now;
 54 }
 55 inline int next(){
 56      int now=a[root].r;
 57      while(a[now].l) now=a[now].l;
 58      return now;
 59 }
 60 inline void insert(int val){
 61     if(!root){a[root=(++size)]=(tree){0,0,0,val,1,1}; return;}
 62     int now=root,f=0;
 63     while(1){
 64         if(a[now].val==val){
 65             a[now].cnt++;
 66             update(now); update(f); splay(now);
 67             break;
 68         }
 69         f=now; now=(val>a[now].val)?a[now].r:a[now].l;
 70         if(!now){
 71             a[++size]=(tree){f,0,0,val,1,1};
 72             if(val>a[f].val) a[f].r=size; else a[f].l=size;
 73             update(f); splay(size);
 74             break;
 75         }
 76     }
 77 }
 78 inline int qrank(int val){
 79      int ans=0,now=root;
 80      while(1){
 81          if(val<a[now].val) now=a[now].l;
 82          else{
 83              if(a[now].l) ans+=a[a[now].l].size;
 84              if(val==a[now].val){splay(now); return ans+1;}
 85              ans+=a[now].cnt;
 86              now=a[now].r;
 87          }
 88      }
 89 }
 90 inline int qval(int rank){
 91     int now=root;
 92      while(1){
 93          if(a[now].l&&rank<=a[a[now].l].size) now=a[now].l;
 94          else{
 95              int tmp=(a[now].l?a[a[now].l].size:0)+a[now].cnt;
 96              if(rank<=tmp) return a[now].val;
 97              rank-=tmp; now=a[now].r;
 98          }
 99      }
100 }
101 inline void del(int u){
102     int whatever=qrank(u);
103     if(a[root].cnt>1){a[root].cnt--; update(root); return;}//不止有一个要删除的值,直接cnt-1 
104     if(!a[root].l&&!a[root].r){clear(root); root=0; return;}//只有一个点
105     if(!a[root].l){//只有左孩子
106         int oldrt=root;
107         a[root=a[root].r].f=0;
108         clear(oldrt);
109         return;
110     }
111     if(!a[root].r){//只有右孩子
112         int oldrt=root;
113         a[root=a[root].l].f=0;
114         clear(oldrt);
115         return;
116     }
117     int prefix=pre(),oldrt=root;//有两个孩子
118     splay(prefix);//新根为u的前驱
119     a[root].r=a[oldrt].r;
120     a[a[oldrt].r].f=root;
121     clear(oldrt); update(root);
122 }
123 void out(int u){
124     if(ls) out(ls);
125     for(int i=1;i<=a[u].cnt;i++)printf("%d ",a[u].val);
126     if(rs) out(rs);
127 }
128 int main(){
129     n=read();
130      while(n--){
131          opt=read(); x=read();
132          if(opt==1) insert(x);//插入x 
133          if(opt==2) del(x);//删除x 
134          if(opt==3) printf("%d\n",qrank(x));//求x的排名 
135          if(opt==4) printf("%d\n",qval(x));//求排名为x的数 
136          if(opt==5) insert(x),printf("%d\n",a[pre()].val),del(x);//求x的前驱 
137         if(opt==6) insert(x),printf("%d\n",a[next()].val),del(x);//求x的后继
138         //printf("[ "); out(root); puts("]");
139      }
140 }
View Code

洛谷 3369

posted @ 2018-01-09 21:18  Driver_Lao  阅读(184)  评论(0编辑  收藏  举报