• splay模板


    点操作:

    splay树可以一个一个的插入结点,这样的splay树是有序树,结点权值大于左儿子小于右儿子

    这样就是点操作

    区间操作:

    还有就是可以自己建树,这样的splay树就不是按权值的有序树,它不满足结点权值大于左儿子小于右儿子,,

    但是它也是有顺序的,无论怎么伸展,把它的结点中序遍历结果就是原来的数组顺序。

    因此自己建树可以操作区间!

    点操作模板

    // File Name: ACM/bzoj/1208.cpp
    // Author: Zlbing
    // Created Time: 2013年08月08日 星期四 16时33分53秒
    
    #include<iostream>
    #include<string>
    #include<algorithm>
    #include<cstdlib>
    #include<cstdio>
    #include<set>
    #include<map>
    #include<vector>
    #include<cstring>
    #include<stack>
    #include<cmath>
    #include<queue>
    using namespace std;
    #define CL(x,v); memset(x,v,sizeof(x));
    #define INF 0x3f3f3f3f
    #define LL long long
    #define REP(i,r,n) for(int i=r;i<=n;i++)
    #define RREP(i,n,r) for(int i=n;i>=r;i--)
    const int MAXN=8e4+100;
    const int mod=1000000;
    struct SplayTree {  
        int sz[MAXN];  
        int ch[MAXN][2];  
        int pre[MAXN];  
        int rt,top;  
        inline void up(int x){  
            sz[x]  = cnt[x]  + sz[ ch[x][0] ] + sz[ ch[x][1] ];  
        }  
        inline void Rotate(int x,int f){  
            int y=pre[x];  
            ch[y][!f] = ch[x][f];  
            pre[ ch[x][f] ] = y;  
            pre[x] = pre[y];  
            if(pre[x]) ch[ pre[y] ][ ch[pre[y]][1] == y ] =x;  
            ch[x][f] = y;  
            pre[y] = x;  
            up(y);  
        }  
        inline void Splay(int x,int goal){//将x旋转到goal的下面  
            while(pre[x] != goal){  
                if(pre[pre[x]] == goal) Rotate(x , ch[pre[x]][0] == x);  
                else   {  
                    int y=pre[x],z=pre[y];  
                    int f = (ch[z][0]==y);  
                    if(ch[y][f] == x) Rotate(x,!f),Rotate(x,f);  
                    else Rotate(y,f),Rotate(x,f);  
                }  
            }  
            up(x);  
            if(goal==0) rt=x;  
        }  
        inline void RTO(int k,int goal){//将第k位数旋转到goal的下面  
            int x=rt;  
            while(sz[ ch[x][0] ] != k-1) {  
                if(k < sz[ ch[x][0] ]+1) x=ch[x][0];  
                else {  
                    k-=(sz[ ch[x][0] ]+1);  
                    x = ch[x][1];  
                }  
            }  
            Splay(x,goal);  
        }  
        inline void vist(int x){  
            if(x){  
                printf("结点%2d : 左儿子  %2d   右儿子  %2d   %2d sz=%d
    ",x,ch[x][0],ch[x][1],val[x],sz[x]);  
                vist(ch[x][0]);  
                vist(ch[x][1]);  
            }  
        }  
        inline void Newnode(int &x,int c){  
            x=++top;  
            ch[x][0] = ch[x][1] = pre[x] = 0;  
            sz[x]=1; cnt[x]=1;  
            val[x] = c;  
        }  
        inline void init(){  
            ans=0;type=-1;  
            ch[0][0]=ch[0][1]=pre[0]=sz[0]=0;  
            rt=top=0; cnt[0]=0;  
            Newnode(rt,-INF);  
            Newnode(ch[rt][1],INF);  
            pre[top]=rt;  
            sz[rt]=2;  
        }  
        inline void Insert(int &x,int key,int f){  
            if(!x) {  
                Newnode(x,key);  
                pre[x]=f;  
                Splay(x,0);  
                return ;  
            }  
            if(key==val[x]){  
                cnt[x]++;  
                sz[x]++;  
                return ;  
            }else if(key<val[x]) {  
                Insert(ch[x][0],key,x);  
            } else {  
                Insert(ch[x][1],key,x);  
            }  
            up(x);  
        }  
    
        void Del(){  //删除根结点
          int t=rt;  
             if(ch[rt][1]) {  
                 rt=ch[rt][1];  
                 RTO(1,0);  
                 ch[rt][0]=ch[t][0];  
                 if(ch[rt][0]) pre[ch[rt][0]]=rt;  
             }  
             else rt=ch[rt][0];  
             pre[rt]=0;  
             up(rt);  
        }  
        void findpre(int x,int key,int &ans){  //找key前趋
            if(!x)  return ;  
            if(val[x] <= key){  
                ans=x;  
                findpre(ch[x][1],key,ans);  
            } else  
                findpre(ch[x][0],key,ans);  
        }  
        void findsucc(int x,int key,int &ans){  //找key后继
            if(!x) return ;  
            if(val[x]>=key) {  
                ans=x;  
                findsucc(ch[x][0],key,ans);  
            } else  
                findsucc(ch[x][1],key,ans);  
        } 
      
    //找第K大数
    inline int find_kth(int x,int k){  
            if(k<sz[ch[x][0]]+1) {  
                return find_kth(ch[x][0],k);  
            }else if(k > sz[ ch[x][0] ] + cnt[x] )   
                return find_kth(ch[x][1],k-sz[ch[x][0]]-cnt[x]);  
            else{   
                Splay(x,0);  
                return val[x];  
            }  
        }  
    
    
    int cnt[MAXN];  
        int val[MAXN];  
        int type;  
        int ans;  
    }spt;  
    int main()
    {
        int n;
        while(~scanf("%d",&n))
        {
            spt.init();
            int a,b;
            int ans=0;
            int type=-1;
            REP(i,1,n)
            {
                scanf("%d%d",&a,&b);
                if(a==type||spt.sz[spt.rt]==2)
                {
                    spt.Insert(spt.rt,b,0);
                    type=a;
                    //spt.vist(spt.rt);
                }
                else 
                {
                    int x,y;
                    if(spt.sz[spt.rt]==2)continue;
                    spt.findpre(spt.rt,b,x);
                    spt.findsucc(spt.rt,b,y);
                    if(abs(spt.val[x]-b)<=abs(spt.val[y]-b))
                    {
                        ans+=abs(spt.val[x]-b);
                        ans%=mod;
                        spt.Splay(x,0);
                        //spt.vist(spt.rt);
                        spt.Del();
                    }
                    else{
                        ans+=abs(spt.val[y]-b);
                        ans%=mod;
                        spt.Splay(y,0);
                        //spt.vist(spt.rt);
                        spt.Del();
                    }
                }
            }
            printf("%d
    ",ans);
        }
        return 0;
    }

    区间操作模板

    // File Name: ACM/HDU/3487.cpp
    // Author: Zlbing
    // Created Time: 2013年08月10日 星期六 21时35分28秒
    
    #include<iostream>
    #include<string>
    #include<algorithm>
    #include<cstdlib>
    #include<cstdio>
    #include<set>
    #include<map>
    #include<vector>
    #include<cstring>
    #include<stack>
    #include<cmath>
    #include<queue>
    using namespace std;
    #define CL(x,v); memset(x,v,sizeof(x));
    #define INF 0x3f3f3f3f
    #define LL long long
    #define REP(i,r,n) for(int i=r;i<=n;i++)
    #define RREP(i,n,r) for(int i=n;i>=r;i--)
    #define L ch[x][0]  
    #define R ch[x][1]  
    #define KT (ch[ ch[rt][1] ][0])  
    const int MAXN = 3e5+100;  
    struct SplayTree {  
        int sz[MAXN];  
        int ch[MAXN][2];  
        int pre[MAXN];  
        int rt,top;  
        inline void down(int x){  
            if(flip[x]) {  
                flip[ L ] ^= 1;  
                flip[ R ] ^= 1;  
                swap(L,R);  
                flip[x]=0;  
            }  
        }  
        inline void up(int x){  
            sz[x]=1+sz[ L ] + sz[ R ];  
        }  
        inline void Rotate(int x,int f){  
            int y=pre[x];  
            down(y);  
            down(x);  
            ch[y][!f] = ch[x][f];  
            pre[ ch[x][f] ] = y;  
            pre[x] = pre[y];  
            if(pre[x]) ch[ pre[y] ][ ch[pre[y]][1] == y ] =x;  
            ch[x][f] = y;  
            pre[y] = x;  
            up(y);  
        }  
        inline void Splay(int x,int goal){//将x旋转到goal的下面  
            down(x);////防止pre[x]就是目标点,下面的循环就进不去了,x的信息就传不下去了  
            while(pre[x] != goal){  
                down(pre[pre[x]]); down(pre[x]);down(x);//在旋转之前需要先下传标记,因为节点的位置可能会发生改变    
                if(pre[pre[x]] == goal) Rotate(x , ch[pre[x]][0] == x);  
                else   {  
                    int y=pre[x],z=pre[y];  
                    int f = (ch[z][0]==y);  
                    if(ch[y][f] == x) Rotate(x,!f),Rotate(x,f);  
                    else Rotate(y,f),Rotate(x,f);  
                }  
            }  
            up(x);  
            if(goal==0) rt=x;  
        }  
        inline void RTO(int k,int goal){//将第k位数旋转到goal的下面  
            int x=rt;  
            down(x);  
            while(sz[ L ]+1 != k) {  
                if(k < sz[ L ] + 1 ) x=L;  
                else {  
                    k-=(sz[ L ]+1);  
                    x = R;  
                }  
                down(x);  
            }  
            Splay(x,goal);  
        }  
        void vist(int x){  
            if(x){  
                printf("结点%2d : 左儿子  %2d   右儿子  %2d   %2d  flip:%d
    ",x,L,R,val[x],flip[x]);  
                vist(L);  
                vist(R);  
            }  
        }  
        void Newnode(int &x,int c,int f){  
            x=++top;flip[x]=0;  
            L = R = 0;  pre[x] = f;  
            sz[x]=1; val[x]=c;  
        }  
        inline void build(int &x,int l,int r,int f){  
            if(l>r) return ;  
            int m=(l+r)>>1;  
            Newnode(x,m,f);  
            build(L , l , m-1 , x);  
            build(R , m+1 , r , x);  
            pre[x]=f;  
            up(x);  
        }  
          
        inline void init(int n){  
            ch[0][0]=ch[0][1]=pre[0]=sz[0]=0;  
            rt=top=0; flip[0]=0; val[0]=0;  
            Newnode(rt,-1,0);
            Newnode(ch[rt][1],-1,rt);
            sz[rt]=2;
            build(KT,1,n,ch[rt][1]);
        }  
        //删除根结点
        void Del(){  
             int t=rt;  
             if(ch[rt][1]) {  
                 rt=ch[rt][1];  
                 RTO(1,0);  
                 ch[rt][0]=ch[t][0];  
                 if(ch[rt][0]) pre[ch[rt][0]]=rt;  
             }  
             else rt=ch[rt][0];  
             pre[rt]=0;  
             up(rt);  
        }  
    //把[a,b]放在c的后面
        void solve1(int a,int b,int c)
        {
           RTO(a,0);
           RTO(b+2,rt);
           int tmp=KT;
           KT=0;
           up(ch[rt][1]);
           up(rt);
    
           RTO(c+1,0);
           RTO(c+2,rt);
           KT=tmp;
           pre[tmp]=ch[rt][1];
           up(ch[rt][1]);
           up(rt);
        }
    //翻转[a,b]
        void solve2(int a,int b)
        {
            RTO(a,0);
            RTO(b+2,rt);
            flip[KT]^=1;
        }
        void print(int x)
        {
            if(x)
            {
                down(x);
                print(L);
                if(val[x]!=-1)
                {
                    if(flag)printf(" ");
                    flag=1;
                    printf("%d",val[x]);
                }
                print(R);
            }
        }
        void out()
        {
            flag=0;
            print(rt);
            printf("
    ");
        }
        int flip[MAXN];  
        int val[MAXN];  
        int flag;
    }spt;  
    
    int main()
    {
        int n,m;
        while(~scanf("%d%d",&n,&m))
        {
            if(n==-1)break;
            char op[5];
            int a,b,c;
            spt.init(n);
            REP(i,1,m)
            {
                scanf("%s",op);
                if(op[0]=='C')
                {
                    scanf("%d%d%d",&a,&b,&c);
                    spt.solve1(a,b,c);
                }
                else
                {
                    scanf("%d%d",&a,&b);
                    spt.solve2(a,b);
                }  
    
            }
            spt.out();
        }
        return 0;
    }
  • 相关阅读:
    (转)CentOS 和 Ubuntu 下的网络配置
    love 的Python 表示
    python mysqlLdb ImportError: DLL load failed: 找不到指定的模块
    elasticsearch7.11.1安装及使用小记
    python多进程代码示例
    在c++项目中使用高性能的rapidjson作为json处理库
    使用kenlm进行文本纠错
    供應商主檔建立流程
    SAP系統自帶范例
    内部订单作业流程
  • 原文地址:https://www.cnblogs.com/arbitrary/p/3253015.html
Copyright © 2020-2023  润新知