[BZOJ]1500 维修数列

1500: [NOI2005]维修数列

Time Limit: 10 Sec   Memory Limit: 64 MB
Submit: 14433   Solved: 4701
[ Submit][ Status][ Discuss]

Description

Input

输入的第1 行包含两个数N 和M(M ≤20 000),N 表示初始时数列中数的个数,M表示要进行的操作数目。
第2行包含N个数字,描述初始时的数列。
以下M行,每行一条命令,格式参见问题描述中的表格。
任何时刻数列中最多含有500 000个数,数列中任何一个数字均在[-1 000, 1 000]内。
插入的数字总数不超过4 000 000个,输入文件大小不超过20MBytes。

Output

对于输入数据中的GET-SUM和MAX-SUM操作,向输出文件依次打印结果,每个答案(数字)占一行。

Sample Input

9 8
2 -6 3 5 1 -5 -3 6 3
GET-SUM 5 4
MAX-SUM
INSERT 8 3 -5 7 2
DELETE 12 1
MAKE-SAME 3 3 2
REVERSE 3 6
GET-SUM 5 4
MAX-SUM

Sample Output

-1
10
1
10

HINT

Source

[ Submit][ Status][ Discuss]


HOME Back


     终于A掉这道题了,调了快一个小时...splay有个地方写错了导致rotate着的时候有一个儿子掉了...其他就没什么好说的,因为这道题是splay裸题,算是代码题(其实也不算太长).看一下代码的update就能懂了怎么求最大子段和了.

     纪念一下:

RunIDUserProblemResultMemoryTimeLanguageCode_LengthSubmit_Time
2186510MaxMercer1500Accepted28184 kb4360 msC++/Edit5492 B2017-07-25 10:45:55
#include<stdio.h>  
#include<algorithm>  
using namespace std;  
const int inf=(1<<29);  
const int maxn=500005;  
char ss[20];  
int n,T,newone,tot,a[maxn],rev[maxn],tag[maxn],w[maxn],s[maxn],root;  
int _recycle[maxn],_recycle_top,c[maxn][2],fa[maxn],siz[maxn],sum[maxn],lmax[maxn],rmax[maxn],ans[maxn];  
inline const int read(){  
    register int f=1,x=0;  
    register char ch=getchar();  
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}  
    while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}  
    return f*x;  
}
inline int newnode(){  
    if(_recycle_top) newone=_recycle[_recycle_top--];  
    else newone=++tot;  
    c[newone][0]=c[newone][1]=fa[newone]=0;  
    rev[newone]=tag[newone]=0,siz[newone]=1;  
    lmax[newone]=rmax[newone]=sum[newone]=w[newone]=-inf;  
    return newone;  
}
inline void reverse(int x){  
    if(!x) return;  
    swap(lmax[x],rmax[x]);  
    swap(c[x][0],c[x][1]);  
    rev[x]^=1;  
}
inline void replace(int x,int val){  
    w[x]=val;sum[x]=siz[x]*val;  
    lmax[x]=rmax[x]=ans[x]=max(val,siz[x]*val);  
    tag[x]=1;     
}
inline void update(int x){  
    if(!x) return;  
    siz[x]= siz[c[x][0]]+siz[c[x][1]]+1;  
    sum[x]= sum[c[x][0]]+sum[c[x][1]]+w[x];  
    lmax[x]=max(lmax[c[x][0]],sum[c[x][0]]+w[x]+max(lmax[c[x][1]],0));  
    rmax[x]=max(rmax[c[x][1]],sum[c[x][1]]+w[x]+max(rmax[c[x][0]],0));  
    ans[x]= max(max(ans[c[x][0]],ans[c[x][1]]),max(rmax[c[x][0]],0)+w[x]+max(lmax[c[x][1]],0));  
}
inline void pushdown(int x){
    if(rev[x]){
       if(c[x][0]) reverse(c[x][0]);
       if(c[x][1]) reverse(c[x][1]);
       rev[x]=0;
    }
    if(tag[x]){  
       if(c[x][0]) replace(c[x][0],w[x]);
       if(c[x][1]) replace(c[x][1],w[x]);
       tag[x]=0;  
    }
}
inline void rotate(int x,int &_wanna){  
    int y=fa[x],z=fa[y];  
    int l=(c[y][0]!=x),r=l^1;  
    if(y!=_wanna) c[z][c[z][0]!=y]=x;
    else _wanna=x;
    fa[x]=z,fa[y]=x,fa[c[x][r]]=y;
    c[y][l]=c[x][r],c[x][r]=y;
    update(y),update(x);
}  
inline void splay(int x,int &_wanna){  
    int top=0;  
    s[++top]=x;
    for(int i=x;fa[i];i=fa[i]) s[++top]=fa[i];  
    for(int i=top;i;i--)         pushdown(s[i]);  
    for(int f;x!=_wanna;rotate(x,_wanna))  
     if((f=fa[x])!=_wanna)  
        rotate(((c[f][1]==x^c[fa[f]][1]==f)?x:f),_wanna);  
}  
void build(int lf,int rg,int who){  
    int mid=(lf+rg)>>1;  
    w[who]=a[mid];  
    if(lf==rg) {sum[who]=lmax[who]=rmax[who]=ans[who]=w[who];siz[who]=1;return;}  
    if(lf<mid) {c[who][0]=newnode();fa[c[who][0]]=who;build(lf,mid-1,c[who][0]);}  
    if(rg>mid) {c[who][1]=newnode();fa[c[who][1]]=who;build(mid+1,rg,c[who][1]);}  
    update(who);  
}  
int find(int k,int x){  
    pushdown(k);
    if(x-1==siz[c[k][0]]) return k;  
    else if(x>siz[c[k][0]]+1) return find(c[k][1],x-siz[c[k][0]]-1);  
    else return find(c[k][0],x);  
}  
inline void Reverse(int x,int num){  
    x=find(root,x),splay(x,root);  
    int y=find(c[x][1],num+1);splay(y,c[x][1]);  
    reverse(c[y][0]);  
    update(y),update(x);  
}  
inline void Replace(int x,int num,int z){  
    x=find(root,x),splay(x,root);  
    int y=find(c[x][1],num+1);splay(y,c[x][1]);  
    replace(c[y][0],z);  
    update(y),update(x);  
}  
void erase(int x){  
    if(!x) return;  
    _recycle[++_recycle_top]=x;  
    if(c[x][0]) erase(c[x][0]);  
    if(c[x][1]) erase(c[x][1]);  
}  
inline void del(int x,int num){  
    x=find(root,x),splay(x,root);  
    int y=find(c[x][1],num+1);splay(y,c[x][1]);  
    erase(c[y][0]);  
    fa[c[y][0]]=c[y][0]=0;  
    update(y),update(x);  
}  
inline void insert(int x,int num){  
    for(register int i=1;i<=num;i++) a[i]=read();  
    x=find(root,x+1),splay(x,root);  
    int y=find(c[x][1],1);splay(y,c[x][1]);  
    c[y][0]=newnode();fa[c[y][0]]=y;  
    build(1,num,c[y][0]);  
    update(y),update(x);  
}  
inline void init(){  
    n=read(),T=read();  
    for(register int i=1;i<=n;i++) a[i]=read();  
    lmax[0]=rmax[0]=ans[0]=-inf;root=1,tot=2;  
    fa[1]=0,lmax[1]=rmax[1]=ans[1]=sum[1]=w[1]=-inf,c[1][1]=2,siz[1]=2;  
    fa[2]=1,lmax[2]=rmax[2]=ans[2]=sum[2]=w[2]=-inf,fa[2]=1,siz[1]=1;  
    c[2][0]=newnode(),fa[c[2][0]]=2,build(1,n,c[2][0]);  
    update(2),update(1); 
}  
int main(){  
    init();  
    while(T--){  
        int x,y,z;  
        scanf("%s",ss);  
        if(ss[0]=='I'){  
           x=read(),y=read();  
           insert(x,y);  
        }  
        if(ss[0]=='D'){  
           x=read(),y=read();  
           del(x,y);  
        }  
        if(ss[4]=='-'){  
           x=read(),y=read(),z=read();  
           Replace(x,y,z);  
        }  
        if(ss[0]=='R'){  
           x=read(),y=read();  
           Reverse(x,y);  
        }  
        if(ss[0]=='G'){  
           x=read(),y=read();  
           x=find(root,x);splay(x,root);
           y=find(c[x][1],y+1);splay(y,c[x][1]);
           printf("%d\n",sum[c[y][0]]);  
        }  
        if(ss[2]=='X') printf("%d\n",ans[root]);  
    }  
    return 0;  
} 


    

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值