zoukankan      html  css  js  c++  java
  • [模板] Splay

    欠了好久的Splay,以后就它了。
    默写真不容易,过几天估计就忘了..
    整个Splay真的精妙,不拖泥带水那种..
    前驱后继之所以不能用rk转到根,是因为这个数不一定存在。。
    kth中<=老忘记=

    #include<iostream>
    #include<cstdio>
    #define check(x) (x==ch[fa[x]][1])
    #define clear(x) val[x]=cnt[x]=siz[x]=ch[x][0]=ch[x][1]=fa[x]=0
    #define pushup(x) siz[x]=siz[ch[x][0]]+siz[ch[x][1]]+cnt[x]
    
    using namespace std;
    
    const int MAXN=100005;
    
    int val[MAXN],cnt[MAXN],siz[MAXN];
    int ch[MAXN][2],fa[MAXN];
    int tot,root;
    inline int newnode(int x){cnt[++tot]++;siz[tot]=1;val[tot]=x;return tot;}
    void rotate(int x){
      int y=fa[x],z=fa[fa[x]];
      bool ck=check(x);
      fa[ch[x][ck^1]]=y;ch[y][ck]=ch[x][ck^1];
      ch[x][ck^1]=y;fa[y]=x;fa[x]=z;
      if(z) ch[z][ch[z][1]==y]=x;
      pushup(y);pushup(x);
    }
    void splay(int x){
      for(int f=fa[x];f;rotate(x),f=fa[x])
        if(fa[f]) rotate(check(f)==check(x)?f:x);
      root=x;
    }
    void insert(int x){
      if(!root){root=newnode(x);return;}
      int cur=root,f=0;
      while(1){
        if(val[cur]==x){cnt[cur]++;pushup(cur);pushup(f);splay(cur);return;}
        f=cur;cur=ch[cur][x>val[cur]];
        if(!cur){cur=newnode(x);fa[cur]=f;ch[f][x>val[f]]=cur;pushup(f);splay(cur);return;}
      }
    }
    int rk(int x){
      int cur=root,ret=0;
      while(1){
        if(x<val[cur]) cur=ch[cur][0];
        else{
          ret+=siz[ch[cur][0]];
          if(val[cur]==x) return splay(cur),ret+1;//
          ret+=cnt[cur];cur=ch[cur][1];
        }
      }
    }
    int kth(int x){
      int cur=root;
      while(1){
        if(ch[cur][0]&&x<=siz[ch[cur][0]]) cur=ch[cur][0];
        else{
          x-=siz[ch[cur][0]]+cnt[cur];
          if(x<=0) return cur;
          cur=ch[cur][1];
        }
      }
    }
    int prev(){
      int cur=ch[root][0];
      while(ch[cur][1]) cur=ch[cur][1];
      return cur;
    }
    int nxtv(){
      int cur=ch[root][1];
      while(ch[cur][0]) cur=ch[cur][0];
      return cur;
    }
    void del(int x){
      rk(x);
      if(cnt[root]>1){cnt[root]--;pushup(root);return;}
      if(!ch[root][0]&&!ch[root][1]){clear(root);root=0;return;}
      if(!ch[root][0]){int sav=root;root=ch[sav][1];fa[root]=0;clear(sav);return;}
      if(!ch[root][1]){int sav=root;root=ch[sav][0];fa[root]=0;clear(sav);return;}
      int sav=root;
      splay(prev());
      ch[root][1]=ch[sav][1];
      fa[ch[sav][1]]=root;
      clear(sav);
      pushup(root);
    }
    
    int n;
    
    inline int rd(){
      int ret=0,f=1;char c;
      while(c=getchar(),!isdigit(c))f=c=='-'?-1:1;
      while(isdigit(c))ret=ret*10+c-'0',c=getchar();
      return ret*f;
    }
    
    int main(){
      n=rd();
      int x,y;
      for(int i=1;i<=n;i++){
        x=rd();y=rd();
        switch(x){
        case 1:{insert(y);break;}
        case 2:{del(y);break;}
        case 3:{printf("%d
    ",rk(y));break;}
        case 4:{printf("%d
    ",val[kth(y)]);break;}
        case 5:{insert(y);printf("%d
    ",val[prev()]);del(y);break;}
        case 6:{insert(y);printf("%d
    ",val[nxtv()]);del(y);break;}
        }
      }
      return 0;
    }
    

    本文来自博客园,作者:GhostCai,转载请注明原文链接:https://www.cnblogs.com/ghostcai/p/9247387.html

  • 相关阅读:
    【leetcode】Letter Combinations of a Phone Number
    【leetcode】_3sum_closest
    【leetcode】_3Sum
    【LeetCode】Longest Common Prefix
    入门:PHP:hello world!
    入门:HTML:hello world!
    入门:HTML表单与Java 后台交互(复选框提交)
    codeforces 712B. Memory and Trident
    codeforces 712A. Memory and Crow
    hdu 5878 I Count Two Three (2016 ACM/ICPC Asia Regional Qingdao Online 1001)
  • 原文地址:https://www.cnblogs.com/ghostcai/p/9247387.html
Copyright © 2011-2022 走看看