zoukankan      html  css  js  c++  java
  • 洛谷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;
    }
  • 相关阅读:
    Java 几个权限关键字
    Java变量的定义
    Hibernate反射DAO模式
    BroadcastReceiver与Notification的综合应用自定义Action的调用方式
    SEO优化技术之关键字
    中软国际助力四所高校建设国家级大学生校外实践教育基地
    讲师团队的培养
    IT与学习
    程序员,你的粮草何在?
    如何更好的学好Linux操作系统
  • 原文地址:https://www.cnblogs.com/landmine-sweeper/p/14512327.html
Copyright © 2011-2022 走看看