BZOJ1500:[NOI2005]维修数列——题解

https://www.lydsy.com/JudgeOnline/problem.php?id=1500

https://www.luogu.org/problemnew/show/P2042#sub

请写一个程序,要求维护一个数列,支持以下 6 种操作:
请注意,格式栏 中的下划线‘ _ ’表示实际输入文件中的空格

太神啦太神啦,我也不会做,我也是copycat的啊。

https://www.luogu.org/blog/IAmHellWord/solution-p2042

直接看上面这位神犇的题解吧。

#include<cstdio>
#include<queue>
#include<cctype>
#include<cstring>
#include<cmath>
#include<vector>
#include<algorithm>
using namespace std;
const int N=1e6+10;
const int INF=1e9;
inline int read(){
    int X=0,w=0;char ch=0;
    while(!isdigit(ch)){w|=ch=='-';ch=getchar();}
    while(isdigit(ch))X=(X<<3)+(X<<1)+(ch^48),ch=getchar();
    return w?-X:X;
}
char s[101];
int fa[N],tr[N][2],key[N],size[N],mx[N];
int root,sz,a[N],id[N],sum[N],lx[N],rx[N];
bool rev[N],tag[N];
queue<int>q;
inline void pushup(int x){
    int l=tr[x][0],r=tr[x][1];
    sum[x]=sum[l]+sum[r]+key[x];
    size[x]=size[l]+size[r]+1;
    mx[x]=max(mx[l],max(mx[r],rx[l]+key[x]+lx[r]));
    lx[x]=max(lx[l],sum[l]+key[x]+lx[r]);
    rx[x]=max(rx[r],sum[r]+key[x]+rx[l]);
}
inline void pushdown(int x){
    int l=tr[x][0],r=tr[x][1];
    if(tag[x]){
        rev[x]=tag[x]=0;
        if(l)tag[l]=1,key[l]=key[x],sum[l]=key[x]*size[l];
        if(r)tag[r]=1,key[r]=key[x],sum[r]=key[x]*size[r];
        if(key[x]>=0){
            if(l)lx[l]=rx[l]=mx[l]=sum[l];
            if(r)lx[r]=rx[r]=mx[r]=sum[r];
        }else{
            if(l)lx[l]=rx[l]=0,mx[l]=key[x];
            if(r)lx[r]=rx[r]=0,mx[r]=key[x];
        }
    }
    if(rev[x]){
        rev[x]=0;rev[l]^=1;rev[r]^=1;
        swap(lx[l],rx[l]);swap(lx[r],rx[r]);
        swap(tr[l][0],tr[l][1]);swap(tr[r][0],tr[r][1]);
    }
}
inline bool get(int x){
    return tr[fa[x]][1]==x;
}
inline void rotate(int x){
    int y=fa[x],z=fa[y],which=get(x);
    tr[y][which]=tr[x][which^1];fa[tr[y][which]]=y;  
    fa[y]=x;tr[x][which^1]=y;fa[x]=z;
    if(z)tr[z][tr[z][1]==y]=x;
    pushup(y);pushup(x);
    return;
}
inline void splay(int x,int y){
    int f=fa[x];
    while(f!=y){
    if(fa[f]!=y)rotate(get(x)==get(f)?f:x);
    rotate(x);f=fa[x];
    }
    if(!y)root=x;
    return;
}
inline int findx(int x){//找到排名为x的点
    int now=root;
    while(233){
    pushdown(now);
        if(tr[now][0]&&x<=size[tr[now][0]])now=tr[now][0];
        else{
            int temp=(tr[now][0]?size[tr[now][0]]:0)+1;
            if(x==temp)return now;
            x-=temp;now=tr[now][1];
        }
    }
}
inline int split(int k,int tot){
    int x=findx(k),y=findx(k+tot+1);
    splay(x,0);splay(y,x);
    return tr[y][0];
}
inline void query(int k,int tot){
    int x=split(k,tot);
    printf("%d\n",sum[x]);
}
inline void modify(int k,int tot,int v){
    int x=split(k,tot),y=fa[x];
    key[x]=v;tag[x]=1;sum[x]=size[x]*v;
    if(v>=0)lx[x]=rx[x]=mx[x]=sum[x];
    else lx[x]=rx[x]=0,mx[x]=v;
    pushup(y);pushup(fa[y]);
}
inline void turn(int k,int tot){
    int x=split(k,tot),y=fa[x];
    if(!tag[x]){
    rev[x]^=1;
    swap(tr[x][0],tr[x][1]);
    swap(lx[x],rx[x]);
    pushup(y);pushup(fa[y]);
    }
    return;
}
inline void recycle(int x){
    int &l=tr[x][0],&r=tr[x][1];
    if(l)recycle(l);
    if(r)recycle(r);
    q.push(x);
    fa[x]=l=r=tag[x]=rev[x]=0;
}
inline void build(int l,int r,int f){
    int mid=(l+r)>>1,now=id[mid],pre=id[f];
    if(l==r){
    mx[now]=sum[now]=a[l];
    tag[now]=rev[now]=0;
    lx[now]=rx[now]=max(a[l],0);
    size[now]=1;
    }
    if(l<mid)build(l,mid-1,mid);
    if(mid<r)build(mid+1,r,mid);
    key[now]=a[mid],fa[now]=pre;
    pushup(now);
    tr[pre][mid>=f]=now;
}
inline void insert(int k,int tot){
    for(int i=1;i<=tot;i++)a[i]=read();
    for(int i=1;i<=tot;i++){
    if(!q.empty())id[i]=q.front(),q.pop();
    else id[i]=++sz;
    }
    build(1,tot,0);
    int z=id[(1+tot)>>1];
    int x=findx(k+1),y=findx(k+2);
    splay(x,0);splay(y,x);
    fa[z]=y;tr[y][0]=z;
    pushup(y);pushup(x);
    return;
}
inline void del(int k,int tot){
    int x=split(k,tot),y=fa[x];
    recycle(x);tr[y][0]=0;
    pushup(y);pushup(fa[y]);
    return;
}
int main(){
    int n=read(),m=read();
    mx[0]=a[1]=a[n+2]=-INF;
    for(int i=2;i<=n+1;i++)a[i]=read();
    for(int i=1;i<=n+2;i++)id[i]=i;
    build(1,n+2,0);
    root=(n+3)>>1;sz=n+2;
    for(int i=1;i<=m;i++){
    scanf("%s",s);
    if(s[0]=='I'){
        int k=read(),tot=read();
        insert(k,tot);
    }
    if(s[0]=='D'){
        int k=read(),tot=read();
        del(k,tot);
    }
    if(s[0]=='M'){
        if(s[2]=='X')printf("%d\n",mx[root]);
        else{
        int k=read(),tot=read(),c=read();
        modify(k,tot,c);
        }
    }
    if(s[0]=='R'){
        int k=read(),tot=read();
        turn(k,tot);
    }
    if(s[0]=='G'){
        int k=read(),tot=read();
        query(k,tot);
    }
    }
    return 0;
}

+++++++++++++++++++++++++++++++++++++++++++

+本文作者:luyouqi233。               +

+欢迎访问我的博客:http://www.cnblogs.com/luyouqi233/+

+++++++++++++++++++++++++++++++++++++++++++

posted @ 2018-03-29 20:22  luyouqi233  阅读(153)  评论(0编辑  收藏  举报