bzoj1500 维修数列

Posted 友人A

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj1500 维修数列相关的知识,希望对你有一定的参考价值。

这道题 我看了hzwer的代码 自己理会把 加油
技术分享
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
const int M=1000555,inf=1000000000;
int read(){
    int ans=0,f=1,c=getchar();
    while(c<0||c>9) {if(c==-) f=-1; c=getchar();}
    while(c>=0&&c<=9){ans=ans*10+(c-0); c=getchar();}
    return ans*f;
}
queue<int>q;
int n,m,root,cnt;
int c[M][2],a[M],fa[M],id[M];
int size[M],sum[M],v[M],mx[M],lx[M],rx[M];
bool tag[M],rev[M];
void up(int x){
    int l=c[x][0],r=c[x][1];
    sum[x]=sum[l]+sum[r]+v[x];
    size[x]=size[l]+size[r]+1;
    mx[x]=max(mx[l],mx[r]);
    mx[x]=max(mx[x],rx[l]+v[x]+lx[r]);
    lx[x]=max(lx[l],sum[l]+v[x]+lx[r]);
    rx[x]=max(rx[r],sum[r]+v[x]+rx[l]);
}
void down(int k){
    int l=c[k][0],r=c[k][1];
    if(tag[k]){
        rev[k]=0; tag[k]=0;
        if(l) tag[l]=1,v[l]=v[k],sum[l]=v[k]*size[l];
        if(r) tag[r]=1,v[r]=v[k],sum[r]=v[k]*size[r];
        if(v[k]>=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]=v[k];
            if(r) lx[r]=rx[r]=0,mx[r]=v[k];
        }
    }
    if(rev[k]){
        rev[k]=0; rev[l]^=1; rev[r]^=1;
        swap(lx[l],rx[l]); swap(lx[r],rx[r]);
        swap(c[l][0],c[l][1]); swap(c[r][0],c[r][1]);
    }
}
int find(int x,int rank){
    down(x);
    int l=c[x][0],r=c[x][1];
    if(size[l]+1==rank) return x;
    else if(size[l]>=rank) return find(l,rank);
    else return find(r,rank-size[l]-1);
}
void rotate(int x,int& k){
    int y=fa[x],z=fa[y],l=0,r=1;
    if(c[y][1]==x) l=1,r=0;
    if(y==k) k=x;
    else{if(c[z][0]==y) c[z][0]=x; else c[z][1]=x;}
    fa[y]=x; fa[x]=z; fa[c[x][r]]=y;
    c[y][l]=c[x][r]; c[x][r]=y;
    up(y); up(x); 
}
void splay(int x,int& k){
    while(x!=k){
        int y=fa[x],z=fa[y];
        if(y!=k){
            if(c[z][0]==y^c[y][0]==x) rotate(y,k);
            else rotate(x,k);
        }
        rotate(x,k);
    }
}
int split(int k,int tot){
    int x=find(root,k),y=find(root,k+tot+1);
    splay(x,root); splay(y,c[x][1]);
    return c[y][0];
}
void modify(int k,int tot,int w){
    int x=split(k,tot),y=fa[x];
    v[x]=w; sum[x]=w*size[x]; tag[x]=1;
    if(w>=0) lx[x]=rx[x]=mx[x]=sum[x];
    else lx[x]=rx[x]=0,mx[x]=w;
    up(y); up(fa[y]);
}
void rec(int k){
    if(!k) return ;
    int l=c[k][0],r=c[k][1];
    rec(l); rec(r); q.push(k);
    fa[k]=c[k][0]=c[k][1]=0;
    rev[k]=tag[k]=0;
}
void eraser(int k,int tot){
    int x=split(k,tot),y=fa[x];
    rec(x); c[y][0]=0;
    up(y); up(fa[y]);
}
/*void build(int l,int r,int f){
    if(l>r) return ;
    int mid=(l+r)>>1,now=id[mid],last=id[f];
    if(l==r){
        sum[now]=a[mid]; size[now]=1;
        tag[now]=0; rev[now]=0;
        if(a[l]>=0)lx[now]=rx[now]=mx[now]=a[mid];
        else lx[now]=rx[now]=0,mx[now]=a[mid];
    }
    else build(l,mid-1,mid),build(mid+1,r,mid);
    v[now]=a[mid]; fa[now]=last;  up(now);
    c[last][mid>=f]=now;
}*/
int build(int l,int r){
    if(l>r) return 0;
    int m=(l+r)>>1,now=id[m];
    tag[now]=rev[now]=0; v[now]=a[m];
    c[now][0]=build(l,m-1);
    c[now][1]=build(m+1,r);
    for(int i=0;i<2;i++) if(c[now][i]) fa[c[now][i]]=now;
    up(now); return now; 
}
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]=++cnt;
    int z=build(1,tot);
    int x=find(root,k+1),y=find(root,k+2);
    splay(x,root); splay(y,c[x][1]);
    fa[z]=y; c[y][0]=z;
    up(y); up(x);
}
void rever(int k,int tot){
    int x=split(k,tot),y=fa[x];
    if(!tag[x]){
        rev[x]^=1;
        swap(c[x][0],c[x][1]);
        swap(lx[x],rx[x]);
        up(y); up(fa[y]);
    }
}
void push_ans(int k,int tot){
    int x=split(k,tot);
    printf("%d\n",sum[x]);
}
int main()
{
    n=read(); m=read(); mx[0]=a[1]=a[n+2]=-inf;
    for(int i=1;i<=n;i++) a[i+1]=read();
    for(int i=1;i<=n+2;i++) id[i]=i;
    root=build(1,n+2); cnt=n+2;
    int k,tot,w;
    char ch[15];
    while(m--){
        scanf("%s",ch);
        if(ch[0]!=M||ch[2]!=X) k=read(),tot=read();
        if(ch[0]==I) insert(k,tot);
        if(ch[0]==D) eraser(k,tot);
        if(ch[0]==M){
            if(ch[2]==X) printf("%d\n",mx[root]);
            else w=read(),modify(k,tot,w);
        }
        if(ch[0]==R) rever(k,tot);
        if(ch[0]==G) push_ans(k,tot);
    }
    return 0;
}
View Code

 

以上是关于bzoj1500 维修数列的主要内容,如果未能解决你的问题,请参考以下文章

bzoj1500 维修数列 splay

BZOJ1500 维修数列

BZOJ 1500: [NOI2005]维修数列

BZOJ1500: [NOI2005]维修数列

BZOJ1500: [NOI2005]维修数列

bzoj:1500: [NOI2005]维修数列