BZOJ_1895_Pku3580 supermemo_Splay

Posted fcwww

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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\n",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\n",ask(x-1,y+1));
        }
    }
}

 

 

以上是关于BZOJ_1895_Pku3580 supermemo_Splay的主要内容,如果未能解决你的问题,请参考以下文章

BZOJ1895Pku3580 supermemo Splay

BZOJ1467_Pku3243 clever Y_EXBSGS

P3580 [POI2014]ZAL-Freight(单调队列dp)

bzoj 3580 冒泡排序 乱搞+思维

BZOJ_1901_&_ZJU_2112_Dynamic_Rankings(主席树+树状数组/线段树+(Treap/Splay))

PKU2018校赛 H题 Safe Upper Bound