洛谷P6136 【模板】普通平衡树(数据加强版)

题目

https://www.luogu.com.cn/problem/P6136

思路

板子题,就贴个代码吧,如果需要讲解splay的话珂以评论。

PS:相同的数可以合并在一个树节点,这样求前驱/后继什么的可以排除相同数的干扰,也许也能节省一点时间。

代码

#include<cstdlib>
#define maxn (int)(1e6+1e5+10)
using namespace std;
struct SplayTree{
    struct node{
        int lson,rson,father,val,size,num;
    } tree[maxn];
    int cnt,root;
    private:
        void update(int x){
            tree[x].size=tree[tree[x].lson].size+tree[tree[x].rson].size+tree[x].num;
        }
        void zig(int x){
            int y=tree[x].father;
            tree[x].father=tree[y].father;
            if(tree[y].father){
                if(tree[tree[y].father].lson==y) tree[tree[y].father].lson=x;
                else tree[tree[y].father].rson=x;
            }
            int z=tree[x].rson;
            if(z) tree[z].father=y;
            tree[y].lson=z;
            tree[x].rson=y;
            tree[y].father=x;
            update(y);update(x);
        }
        void zag(int x){
            int y=tree[x].father;
            tree[x].father=tree[y].father;
            if(tree[y].father){
                if(tree[tree[y].father].lson==y) tree[tree[y].father].lson=x;
                else tree[tree[y].father].rson=x;
            }
            int z=tree[x].lson;
            if(z) tree[z].father=y;
            tree[y].rson=z;
            tree[x].lson=y;
            tree[y].father=x;
            update(y);update(x);
        }
        void splay(int x){
            while(tree[x].father){
                int y=tree[x].father,z=tree[y].father;
                if(!z){
                    if(tree[y].lson==x) zig(x);
                    else zag(x);
                }
                else{
                    if(tree[y].lson==x&&tree[z].lson==y){
                        zig(y);zig(x);
                    }
                    else if(tree[y].rson==x&&tree[z].rson==y){
                        zag(y);zag(x);
                    }
                    else if(tree[y].lson==x&&tree[z].rson==y){
                        zig(x);zag(x);
                    }
                    else{
                        zag(x);zig(x);
                    }
                }
            }
            root=x;
        }
        int find(int x,int key){
            if(!x) return 0;
            if(tree[x].val==key) return x;
            if(tree[x].val<key) return find(tree[x].rson,key);
            else return find(tree[x].lson,key);
        }
        void add(int x,int y){
            if(!x){
                root=y;
                return;
            }
            if(tree[x].val<tree[y].val){
                if(tree[x].rson) add(tree[x].rson,y);
                else{
                    tree[x].rson=y;
                    tree[y].father=x;
                }
            }
            else{
                if(tree[x].lson) add(tree[x].lson,y);
                else{
                    tree[x].lson=y;
                    tree[y].father=x;
                }
            }
            update(x);
            return;
        }
        int dfs(int x,int k){
            int t1=tree[tree[x].lson].size;
            int t2=tree[x].num;
            if(t1<k&&t1+t2>=k) return x;
            if(k>t1+t2) return dfs(tree[x].rson,k-t1-t2);
            else return dfs(tree[x].lson,k);
        }
        int find_pre(int x){
            while(tree[x].rson)
                x=tree[x].rson;
            return x;
        }
        int find_next(int x){
            while(tree[x].lson)
                x=tree[x].lson;
            return x;
        }
    public:
        void clear(){
            cnt=root=0;
            tree[0].father=tree[0].lson=tree[0].rson=0;
            tree[0].num=tree[0].size=tree[0].val=0;
        }
        int insert(int x){//插入一个整数 x
            int t=find(root,x);
            if(t){
                splay(t);
                tree[t].num++;
                tree[t].size++;
                return t;
            }
            else{
                tree[++cnt].val=x;
                tree[cnt].num=1;
                tree[cnt].size=1;
                tree[cnt].lson=tree[cnt].rson=0;
                add(root,cnt);
                splay(cnt);
                return cnt;
            }
        }
        void erase(int x){//删除一个整数 x
            int t=find(root,x);
            splay(t);
            if(tree[t].num==1){
                int ll=tree[t].lson,rr=tree[t].rson;
                tree[ll].father=tree[rr].father=0;
                if(ll&&rr){
                    int t2=find_next(rr);
                    splay(t2);
                    tree[t2].lson=ll;
                    tree[ll].father=t2;
                    update(t2);
                }
                else if(ll) root=ll;
                else if(rr) root=rr;
                else root=0;
            }
            else{
                tree[t].num--;
                tree[t].size--;
            }
        }
        int rank(int x){//查询整数 x 的排名
            int t,ans;
            t=insert(x);
            ans=tree[tree[t].lson].size+1;
            erase(x);
            return ans;
        }
        int pos(int x){//查询排名为 x 的数
            int t=dfs(root,x);
            splay(t);
            return tree[t].val;
        }
        int pre(int x){//求 x 的前驱
            int t,ans;
            t=insert(x);
            ans=find_pre(tree[t].lson);
            erase(x);
            return tree[ans].val;
        }
        int next(int x){//求 x 的后继
            int t,ans;
            t=insert(x);
            ans=find_next(tree[t].rson);
            erase(x);
            return tree[ans].val;
        }
        int tot(){
            return root;
        }

}T;
int main(){
    int n,m,i,x,lastans=0,opt,ans=0;
    // freopen("T.in","r",stdin);
    // freopen("myans.out","w",stdout);
    scanf("%d%d",&n,&m);
    T.clear();
    for(i=1;i<=n;i++){
        scanf("%d",&x);
        T.insert(x);
    }
    for(i=1;i<=m;i++){
        scanf("%d%d",&opt,&x);
        x^=lastans;
        if(opt==1){
            T.insert(x);
        }
        else if(opt==2){
            T.erase(x);
        }
        else if(opt==3){
            lastans=T.rank(x);
            ans^=lastans;
        }
        else if(opt==4){
            lastans=T.pos(x);
            ans^=lastans;
        }
        else if(opt==5){
            lastans=T.pre(x);
            ans^=lastans;
        }
        else{
            lastans=T.next(x);
            ans^=lastans;
        }
    }
    printf("%d
",ans);
    // system("pause");
    return 0;
}
原文地址:https://www.cnblogs.com/landmine-sweeper/p/14512327.html