BZOJ 1251 序列终结者(Splay)

 

【题目链接】 http://www.lydsy.com/JudgeOnline/problem.php?id=1251

 

【题目大意】

  给出全零序列,要求维护三个操作,区间加法,区间翻转和区间求最小值。

 

【题解】

  splay基础练习。

 

【代码】

#include <cstdio>
#include <algorithm>
using namespace std;
const int N=50010;
int n,m,a[N],val[N],mn[N],tag[N],size[N];
int son[N][2],f[N],tot,root;bool rev[N];
void rev1(int x){if(!x)return;swap(son[x][0],son[x][1]);rev[x]^=1;}
void add1(int x,int p){if(!x)return;val[x]+=p;mn[x]+=p;tag[x]+=p;}
void pb(int x){
    if(rev[x]){
        rev1(son[x][0]);
        rev1(son[x][1]);
        rev[x]=0;
    }
    if(tag[x]){
        add1(son[x][0],tag[x]);
        add1(son[x][1],tag[x]);
        tag[x]=0;
    }
}
void up(int x){
    size[x]=1,mn[x]=val[x];
    if(son[x][0]){
        size[x]+=size[son[x][0]];
        if(mn[x]<mn[son[x][0]])mn[x]=mn[son[x][0]];
    }
    if(son[x][1]){
        size[x]+=size[son[x][1]];
        if(mn[x]<mn[son[x][1]])mn[x]=mn[son[x][1]];
    }
}
void rotate(int x){
    int y=f[x],w=son[y][1]==x;
    son[y][w]=son[x][w^1];
    if(son[x][w^1])f[son[x][w^1]]=y;
    if(f[y]){
        int z=f[y];
        if(son[z][0]==y)son[z][0]=x;
        if(son[z][1]==y)son[z][1]=x;
    }f[x]=f[y];son[x][w^1]=y;f[y]=x;up(y);
}
void splay(int x,int w){
    int s=1,i=x,y;a[1]=x;
    while(f[i])a[++s]=i=f[i];
    while(s)pb(a[s--]);
    while(f[x]!=w){
        y=f[x];
        if(f[y]!=w){if((son[f[y]][0]==y)^(son[y][0]==x))rotate(x);else rotate(y);}
        rotate(x);
    }if(!w)root=x;
    up(x);
}
int build(int l,int r,int fa){
    int x=++tot,mid=(l+r)>>1;
    f[x]=fa;val[x]=a[mid];
    if(l<mid)son[x][0]=build(l,mid-1,x);
    if(r>mid)son[x][1]=build(mid+1,r,x);
    up(x);
    return x;
}
int kth(int k){
    int x=root,tmp;
    while(1){
        pb(x);
        tmp=size[son[x][0]]+1;
        if(k==tmp)return x;
        if(k<tmp)x=son[x][0];else k-=tmp,x=son[x][1];
    }
}
int main(){
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)a[i]=0;
    root=build(0,n+1,0);
    while(m--){
        int op,x,y,z;
        scanf("%d",&op);
        if(op==1){
            scanf("%d%d%d",&x,&y,&z);
            x=kth(x),y=kth(y+2);
            splay(x,0),splay(y,x),add1(son[y][0],z);
        }else if(op==2){
            scanf("%d%d",&x,&y);
            x=kth(x),y=kth(y+2);
            splay(x,0),splay(y,x),rev1(son[y][0]);
        }else{
            scanf("%d%d",&x,&y);
            x=kth(x),y=kth(y+2);
            splay(x,0),splay(y,x),printf("%d\n",mn[son[y][0]]);
        }
    }return 0;
}
posted @ 2017-04-17 20:27  forever97  阅读(166)  评论(0编辑  收藏  举报