• POJ-3580-SuperMemo(splay的各种操作)


    题意:对数组进行各种操作

    其中 REVOLVE右移操作。将区间[a,b]右移c位

    首先c可能比较多,可以先对区间长度取模。

    在右移之后,可以发现[a,b]被分为两个区间[a,b-c]  [b-c+1,b],将后者插入到前者之前即可。

    // File Name: ACM/POJ/3580.cpp
    // Author: Zlbing
    // Created Time: 2013年08月10日 星期六 10时51分07秒
    
    #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 0x3fffffff
    #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 = 2e5+100;
    int num[MAXN];
    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;
            }
            if(add[x])
            {
                if(L)
                {
                    add[L]+=add[x];
                    mi[L]+=add[x];
                    val[L]+=add[x];
                }
                if(R)
                {
                    add[R]+=add[x];
                    mi[R]+=add[x];
                    val[R]+=add[x];
                }
                add[x]=0;
            }
        }
        inline void up(int x){
            sz[x]=1+sz[ L ] + sz[ R ];
            mi[x]=min(val[x],min(mi[L],mi[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]);
                printf("结点%2d mi=%2d
    ",x,mi[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;
            mi[x]=c; add[x]=0;
        }
        inline void build(int &x,int l,int r,int f){
            if(l>r) return ;
            int m=(l+r)>>1;
            Newnode(x,num[m],f);
            build(L , l , m-1 , x);
            build(R , m+1 , r , x);
            pre[x]=f;
            up(x);
        }
    
        //终于明白初始化结点0的用处了。就是所有的叶子结点,是终止结点
        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;
            add[0]=0;mi[0]=INF;
            Newnode(rt,INF,0);
            Newnode(ch[rt][1],INF,rt);
            sz[rt]=2;
            build(KT,1,n,ch[rt][1]);
            up(ch[rt][1]);up(rt);
        }
        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 ADD(int a,int b,int d)
        {
            if(a>b)swap(a,b);
           RTO(a,0);
           RTO(b+2,rt);
           add[KT]+=d;
           val[KT]+=d;
           mi[KT]+=d;
        }
        void REVERSE(int a,int b)
        {
            if(a>b)swap(a,b);
            RTO(a,0);
            RTO(b+2,rt);
            flip[KT]^=1;
        }
        //t有可能为负
        void REVOLVE(int x,int y,int t)
        {
            if(x>y)swap(x,y);
            t=t%(y-x+1);
            t=(t+y-x+1)%(y-x+1);
            if(t==0)return;
            int l=y-t+1;
            int r=y+2;
            RTO(l,0);
            RTO(r,rt);
            int tmp=KT;
            KT=0;
            up(ch[rt][1]);up(rt);
    
            RTO(x,0);
            RTO(x+1,rt);
            KT=tmp;pre[tmp]=ch[rt][1];
            up(ch[rt][1]);up(rt);
        }
        void INSERT(int x,int p)
        {
            RTO(x+1,0);
            RTO(x+2,rt);
            Newnode(KT,p,ch[rt][1]);
            up(ch[rt][1]);up(rt);
        }
        void DELETE(int x)
        {
            RTO(x,0);
            RTO(x+2,rt);
            KT=0;
            up(ch[rt][1]);up(rt);
        }
        int  MIN(int x,int y)
        {
            if(x>y)swap(x,y);
            RTO(x,0);
            RTO(y+2,rt);
            return mi[KT];
        }
        int flip[MAXN];
        int val[MAXN];
        int mi[MAXN];
        int add[MAXN];
    }spt;
    
    int main()
    {
        int n,m;
        while(~scanf("%d",&n))
        {
            REP(i,1,n)
                scanf("%d",&num[i]);
            scanf("%d",&m);
            spt.init(n);
            char op[10];
            int a,b,c;
            REP(i,1,m)
            {
                scanf("%s",op);
                if(op[0]=='A')
                {
                    scanf("%d%d%d",&a,&b,&c);
                    spt.ADD(a,b,c);
                }
                else if(op[0]=='I')
                {
                    scanf("%d%d",&a,&b);
                    spt.INSERT(a,b);
                }
                else if(op[0]=='D')
                {
                    scanf("%d",&a);
                    spt.DELETE(a);
                }
                else if(op[0]=='M')
                {
                    scanf("%d%d",&a,&b);
                    int ans=spt.MIN(a,b);
                    printf("%d
    ",ans);
                }
                else if(strcmp(op,"REVERSE")==0)
                {
                    scanf("%d%d",&a,&b);
                    spt.REVERSE(a,b);
                }
                else if(strcmp(op,"REVOLVE")==0)
                {
                    scanf("%d%d%d",&a,&b,&c);
                    spt.REVOLVE(a,b,c);
                }
            }
        }
        return 0;
    }
  • 相关阅读:
    ZedGraph 总论
    ZedGraph图形控件在Web开发中的应用
    zedgraph基本教程篇第八节PieSampleDemo.cs介绍
    zedgraph基本教程篇第三节、第四节DateAxisSampleDemo.cs和TextAxisSampleDemo.cs介绍
    zedgraph 基本教程篇第二节:ModInitialSampleDemo.cs介绍
    zedgraph基本教程篇第五节BarChartSampleDemo.cs介绍
    zedgraph基本教程篇第九节MasterSampleDemo.cs介绍
    JavaScript 中创建自定义对象
    SQL Server 索引结构及其使用(一)
    Javascript 的基本对象
  • 原文地址:https://www.cnblogs.com/arbitrary/p/3252862.html
Copyright © 2020-2023  润新知