zoukankan      html  css  js  c++  java
  • BZOJ_1895_Pku3580 supermemo_Splay

    BZOJ_1895_Pku3580 supermemo_Splay

    Description

    给出一个初始序列fA1;A2;:::Ang,要求你编写程序支持如下操作: 1. ADDxyD:给子序列fAx:::Ayg的每个元素都加上D。例如对f1,2, 3,4,5g执行"ADD 241" 会得到f1,3,4,5,5g。 2. REVERSExy:将子序列fAx:::Ayg翻转。例如对f1,2,3,4,5g执 行"REVERSE 24"会得到f1,4,3,2,5g。 3. REVOLVExyT:将子序列fAx:::Ayg旋转T个单位。例如, 对f1,2,3,4,5g执行"REVOLVE 242"会得到f1,3,4,2,5g。 4. INSERTxP:在Ax后插入P。例如,对f1,2,3,4,5g执行"INSERT 24"会得到f1,2,4,3,4,5g。 5. DELETEx:删去Ax。例如,对f1,2,3,4,5g执行"DELETE 2"会得 到f1,3,4,5g。 6. MINxy:查询子序列fAx:::Ayg中的最小元素。例如,对于序列f1, 2,3,4,5g,询问"MIN 24"的返回应为2。

    Input

    第一行包含一个整数n,表示初始序列的长度。 以下n行每行包含一个整数,描述初始的序列。 接下来一行包含一个整数m,表示操作的数目。 以下m行每行描述一个操作。

    Output

    对于所有"MIN"操作,输出正确的答案,每行一个。

    Sample Input

    5
    1
    2
    3
    4
    5
    2
    ADD 2 4 1
    MIN 4 5

    Sample Output

    5

    HINT

    输入、输出以及中间运算结果均不会超过32位整数。
    对于30%的数据,n;m 6 1000;
    对于100%的数据,n;m 6 100000。


    splay裸题,操作稍微多了点。

    旋转操作可以理解为进行三次区间翻转操作,这样就十分方便了。

    注意旋转单位要mod区间长度。

    具体实现在代码中:

    #include <stdio.h>
    #include <string.h>
    #include <algorithm>
    using namespace std;
    #define N 1200050
    #define ls ch[p][0]
    #define rs ch[p][1]
    #define get(x) (ch[f[x]][1]==x)
    int ch[N][2],f[N],siz[N],turn[N],val[N],mn[N],rt;
    int a[N],n,add[N],sz,m,now;
    char opt[10];
    void pushup(int p){
        if(!p)return ;
        siz[p]=1;
        if(ls) siz[p]+=siz[ls];
        if(rs) siz[p]+=siz[rs];
        mn[p]=min(mn[ls],mn[rs]);
        mn[p]=min(mn[p],val[p]);
    }
    void pushdown(int p)
    {
        if(add[p]){
            if(ls) mn[ls]+=add[p],val[ls]+=add[p],add[ls]+=add[p];
            if(rs) mn[rs]+=add[p],val[rs]+=add[p],add[rs]+=add[p];
            add[p]=0;
        }
        if(turn[p]){
            swap(ls,rs);
            if(ls) turn[ls]^=1;
            if(rs) turn[rs]^=1;
            turn[p]=0;
        }
    }
    void rotate(int x)
    {
        int y=f[x],z=f[y],k=get(x);
        ch[y][k]=ch[x][!k];f[ch[y][k]]=y;
        ch[x][!k]=y;f[y]=x;f[x]=z;
        if(z) ch[z][ch[z][1]==y]=x;
        pushup(y);pushup(x);
        if(rt==y) rt=x;
    }
    void splay(int x,int y)
    {
        for(int fa;(fa=f[x])!=y;rotate(x))
            if(f[fa]!=y)
                rotate((get(x)==get(fa)) ? fa : x);
    }
    int find(int x)
    {
        int p=rt;
        while(1)
        {
            pushdown(p);
            if(x<=siz[ls]) p=ls;
            else{
                x-=siz[ls]+1;
                if(!x) return p;
                p=rs;
            }
        }
    }
    void addadd(int x,int p,int v)
    {
        x=find(x);
        p=find(p);
        splay(x,0);
        splay(p,rt);
        add[ls]+=v;
        mn[ls]+=v;
        val[ls]+=v;
        pushup(p);pushup(x);
    }
    void reverse(int x,int p)
    {
        x=find(x);
        p=find(p);
        splay(x,0);
        splay(p,rt);
        turn[ls]^=1;
    }
    void build(int fa,int l,int r)
    {
        if(l>r) return ;
        int mid=l+r>>1;
        ch[fa][mid>fa]=mid;
        f[mid]=fa;
        val[mid]=mn[mid]=a[mid-1];
        build(mid,l,mid-1);
        build(mid,mid+1,r);
        pushup(mid);
    }
    void insert(int x,int v)
    {
        now++;
        int p=x+1;
        x=find(x);
        p=find(p);
        splay(x,0);
        splay(p,rt);
        ls=++sz;
        val[ls]=mn[ls]=v;
        f[ls]=p;
        siz[ls]=1;
        pushup(p);pushup(x);
    }
    void del(int x)
    {
        now--;
        int p=x+2;
        x=find(x);
        p=find(p);
        splay(x,0);
        splay(p,rt);
        ls=0;
        pushup(p);pushup(x);
    }
    int ask(int x,int p)
    {
        x=find(x);
        p=find(p);
        splay(x,0);
        splay(p,rt);
        return mn[ls];
    }
    /*void print()
    {
        int p,i;
        for(i=1;i<=now;i++){
            p=find(i);
            printf("p=%d val[p]=%d
    ",p,val[p]);
        }
    }*/
    int main(){
        //memset(mn,0x3f,sizeof(mn));
        mn[0]=1<<30;
        scanf("%d",&n);
        int i,x,y,z;
        for(i=1;i<=n;i++) scanf("%d",&a[i]);
        build(0,1,n+2);
        sz=now=n+2;
        rt=n+3>>1;
        scanf("%d",&m);
        for(i=1;i<=m;i++)
        {
            scanf("%s%d",opt,&x);
            if(opt[0]=='A')
            {
                scanf("%d%d",&y,&z);
                x++;y++;
                addadd(x-1,y+1,z);
            }
            else if(opt[0]=='R')
            {
                scanf("%d",&y);
                x++;y++;
                if(opt[3]=='E')
                {
                    reverse(x-1,y+1);
                }
                else
                {
                    scanf("%d",&z);
                    z%=(y-x+1);
                    if(z==0)continue;
                    reverse(x-1,y+1);
                    reverse(x-1,x+z);
                    reverse(x+z-1,y+1);
                }
            }
            else if(opt[0]=='I')
            {
                scanf("%d",&y);
                x++;
                insert(x,y);
            }
            else if(opt[0]=='D')
            {
                x++;
                del(x-1);
            }
            else {
                scanf("%d",&y);
                x++;y++;
                printf("%d
    ",ask(x-1,y+1));
            }
        }
    }
    
  • 相关阅读:
    太忙了
    Delphi 的接口(2) 第一个例子
    Delphi 的接口(3) 关于接口的释放
    VS.NET让我做了一场恶梦
    [推荐阅读]The Best Of .The NET 1.x Years
    向大家说声对不起
    [致歉]16:30~17:10电信网络出现问题
    服务器恢复正常
    [SharePoint]更改活动目录(AD)中用户名的问题
    [正式决定]博客园开始接受捐助
  • 原文地址:https://www.cnblogs.com/suika/p/8698447.html
Copyright © 2011-2022 走看看