【BZOJ 3224】普通平衡树 模板题

删除节点时把节点splay到根;

然后把根左子树的最右边节点splay到根的左孩子上;

然后删除就可以了;

我的教训是删根的时候根的右孩子的父亲指针一定要记得指向根的左孩子!!!

my AC code:

#include<cctype>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define for1(i,a,b) for(int i=(a);i<=(b);++i)
using namespace std;
typedef long long ll;
struct node{
    node();
    node *ch[2],*fa;
    int d,size,sum;
    short pl(){return this==fa->ch[1];}
    void count(){sum=ch[0]->sum+ch[1]->sum+size;}
}*null;
node::node(){ch[0]=ch[1]=fa=null;size=sum=0;}
int getint(){
    char c; int fh=1;
    while (!isdigit(c=getchar()))
     if (c=='-') fh=-1;
    int a=c-'0';
    while (isdigit(c=getchar()))
     a=a*10+c-'0';
    return a*fh;
}
namespace Splay{
    node *ROOT;
    void Build(){
        null=new node;
        *null=node();
        ROOT=null;
    }
    void rotate(node *k){
        node *r=k->fa; if (k==null||r==null) return;
        int x=k->pl()^1;
        r->ch[x^1]=k->ch[x];
        r->ch[x^1]->fa=r;
        if (r->fa!=null) r->fa->ch[r->pl()]=k;
        else ROOT=k;
        k->fa=r->fa; r->fa=k;
        k->ch[x]=r;
        r->count(); k->count();
    }
    void splay(node *r,node *tar=null){
        for (;r->fa!=tar;rotate(r))
         if (r->fa->fa!=tar) rotate(r->pl()==r->fa->pl()?r->fa:r);
    }
    void updata(node *r){
        while (r!=null){
            r->count();
            r=r->fa;
        }
    }
    void insert(int x){
        node *r=ROOT;
        if (ROOT==null){
            ROOT=new node;
            ROOT->d=x;
            ROOT->size=1;
            ROOT->sum=1;
            return;
        }
        while (1){
            int c;
            if (x<r->d) c=0;
            else if (x>r->d) c=1;
            else {r->size++;r->sum++;splay(r); return;}
            if (r->ch[c]==null){
                r->ch[c]=new node;
                r->ch[c]->fa=r;
                r->ch[c]->d=x;
                r->ch[c]->size=1;
                r->ch[c]->sum=1;
                splay(r->ch[c]);
                return;
            }else r=r->ch[c];
        }
    }
    node *kth(int k){
        node *r=ROOT;
        while (r!=null){
            if (r->ch[0]->sum>=k) r=r->ch[0];
            else if (r->ch[0]->sum+r->size>=k) return r;
            else k-=r->ch[0]->sum+r->size,r=r->ch[1];
        }
        return null;
    }
    node *ques(int k){
        node *r=ROOT; int ans=0;
        while (r!=null){
            if (k<r->d) r=r->ch[0];
            else if (k>r->d) ans+=r->ch[0]->sum+r->size,r=r->ch[1];
            else {printf("%d\n",ans+r->ch[0]->sum+1); return r;}
        }
        return null;
    }
    node *ques2(int k){
        node *r=ROOT;
        while (r!=null){
            if (k<r->d) r=r->ch[0];
            else if (k>r->d) r=r->ch[1];
            else return r;
        }
        return null;
    }
    node *rightdown(node *r){
        while (r->ch[1]!=null){
            r=r->ch[1];
        }return r;
    }
    node *leftdown(node *r){
        while (r->ch[0]!=null){
            r=r->ch[0];
        }return r;
    }
    void deleter(node *r){
        if (r->size>1){
            splay(r);
            r->size--; r->sum--; return;
        }else{
            splay(r);
            if ((r->ch[0]==null)&&(r->ch[1]==null)){
                ROOT=null;
                delete r;
            }else if (r->ch[0]==null){
                r->ch[1]->fa=null;
                ROOT=r->ch[1];
                delete r;
            }else if (r->ch[1]==null){
                r->ch[0]->fa=null;
                ROOT=r->ch[0];
                delete r;
            }else{
                splay(rightdown(r->ch[0]),ROOT);
                r->ch[0]->ch[1]=r->ch[1];
                r->ch[1]->fa=r->ch[0];
                r->ch[0]->fa=null;
                r->ch[0]->count();
                ROOT=r->ch[0];
                delete r;
            }
        }
    }
    int predd(node *r,int x){
        if (r==null) return -1E7-10;
        if (x<=r->d) return predd(r->ch[0],x);
        return max(r->d,predd(r->ch[1],x));
    }
    int pross(node *r,int x){
        if (r==null) return 1E7+10;
        if (r->d<=x) return pross(r->ch[1],x);
        return min(r->d,pross(r->ch[0],x));
    }
    int predds(int x){
        return predd(ROOT,x);
    }
    int prosss(int x){
        return pross(ROOT,x);
    }
}
int main()
{
    int n,x,num;
    n=getint();
    Splay::Build();
    while (n>0){n--;
        x=getint();
        switch(x){
            node *r;
            case 1:
                num=getint();
                Splay::insert(num);
            break;
            case 2:
                num=getint();
                r=Splay::ques2(num);
                Splay::deleter(r);
            break;
            case 3:
                num=getint();
                r=Splay::ques(num);
            break;
            case 4:
                num=getint();
                r=Splay::kth(num);
                printf("%d\n",r->d);
            break;
            case 5:
                num=getint();
                printf("%d\n",Splay::predds(num));
            break;
            case 6:
                num=getint();
                printf("%d\n",Splay::prosss(num));
            break;
        }
    }
    return 0;
}

这样就可以了

你可能感兴趣的:(【BZOJ 3224】普通平衡树 模板题)