1500: [NOI2005]维修数列
Time Limit: 10 Sec Memory Limit: 64 MBSubmit: 14486 Solved: 4723
[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
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
10
1
10
HINT

思路{
为何发现我的蛋碎了..........
为何发现被维修的不是数列,而是我.........
关键是最后一个操作!
设l[x]为以当前节点所代表的区间左端点为起点的序列最大值,
那么往上传的时候,由于以下标为键值l[x]=Max(l[ls],Sum[ls]+v[x]+l[rs]);
同理更新r[x],设Max[x]为一段区间内最大值,Max[x]在上传的过程中一路更新(很妙啊~~~)
然后就轻巧地用嘴巴AC辣~~~~(调得想死.......)
膜Hzwer的代码咯.
}
#include<bits/stdc++.h>
#define RG register
#define il inline
#define N 1000005
#define rs (ch[x][1])
#define ls (ch[x][0])
using namespace std;
int ch[N][2],fa[N],sum[N],l[N],r[N],sz[N],v[N],Max[N],rt,id[N],a[N],n,m,cnt;bool tag[N],rev[N];
void up(int x){
sz[x]=sz[ls]+sz[rs]+1;
sum[x]=sum[rs]+sum[ls]+v[x];
Max[x]=max(Max[rs],Max[ls]);
Max[x]=max(Max[x],v[x]+r[ls]+l[rs]);
l[x]=max(l[ls],sum[ls]+v[x]+l[rs]);
r[x]=max(r[rs],sum[rs]+v[x]+r[ls]);
}
void down(int x){
if(tag[x]){
rev[x]=tag[x]=0;
if(rs)v[rs]=v[x],sum[rs]=sz[rs]*v[x],tag[rs]=1;
if(ls)v[ls]=v[x],sum[ls]=sz[ls]*v[x],tag[ls]=1;
if(v[x]>=0){
if(ls)l[ls]=r[ls]=Max[ls]=sum[ls];
if(rs)l[rs]=r[rs]=Max[rs]=sum[rs];
}else {
if(ls)l[ls]=r[ls]=0,Max[ls]=v[x];
if(rs)l[rs]=r[rs]=0,Max[rs]=v[x];
}
}if(rev[x])rev[x]^=1,rev[rs]^=1,rev[ls]^=1,swap(rs,ls),swap(l[rs],r[rs]),swap(l[ls],r[ls]);
}
void Rotate(int x,int &k){
int y=fa[x],z=fa[y],l,r;if(z)down(z);down(y),down(x);
l=ch[y][1]==x,r=l^1;
if(y==k)k=x;
else ch[z][ch[z][1]==y]=x;
fa[x]=z,fa[y]=x,fa[ch[x][r]]=y;ch[y][l]=ch[x][r];
ch[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(ch[z][0]==y^ch[y][0]==x)Rotate(x,k);
else Rotate(y,k);
}Rotate(x,k);
}
}queue<int>que;
int find(int x,int rnk){
down(x);
if(sz[ls]+1==rnk)return x;
if(sz[ls]>=rnk)return find(ls,rnk);
return find(rs,rnk-sz[ls]-1);
}
void clean(int x){
if(!x)return;
clean(rs),clean(ls),que.push(x);
fa[x]=rs=ls=tag[x]=rev[x]=0;
}
int Split(int k,int tot){
int x=find(rt,k),y=find(rt,k+tot+1);
Splay(x,rt),Splay(y,ch[x][1]);
return ch[y][0];
}
void Querysum(int k,int tot){
int x=Split(k,tot);
printf("%d
",sum[x]);
}
void Modify(int k,int tot,int val){
int x=Split(k,tot),y=fa[x];
v[x]=val;tag[x]=1;sum[x]=sz[x]*v[x];
if(val>=0)l[x]=r[x]=Max[x]=sum[x];
else l[x]=r[x]=0,Max[x]=v[x];
up(y),up(fa[y]);
}
void rever(int k,int tot){
int x=Split(k,tot),y=fa[x];
if(!tag[x]){
rev[x]^=1;swap(l[x],r[x]);
up(y),up(fa[y]);
}
}
void del(int k,int tot){
int x=Split(k,tot),y=fa[x];
clean(x);ch[y][0]=0;up(y),up(fa[y]);
}
#define mid ((L+R)>>1)
void build(int L,int R,int f){
if(L>R)return;
int x=id[mid],faa=id[f];
if(L==R){
sz[x]=1,sum[x]=a[L];
tag[x]=0;
if(a[L]>=0)l[x]=r[x]=Max[x]=a[L];
else l[x]=r[x]=0,Max[x]=a[L];
}else build(L,mid-1,mid),build(mid+1,R,mid);
v[x]=a[mid],fa[x]=faa;up(x);
ch[faa][f<=mid]=x;
}
void Insert(int k,int tot){
for(int i=1;i<=tot;++i)scanf("%d",&a[i]);
for(int i=1;i<=tot;++i)
if(!que.empty())id[i]=que.front(),que.pop();
else id[i]=++cnt;
build(1,tot,0);int z=id[((1+tot)>>1)];
int x=find(rt,k+1),y=find(rt,k+2);
Splay(x,rt),Splay(y,ch[x][1]);
fa[z]=y,ch[y][0]=z,up(y),up(x);
}int k,tot;
int main(){
scanf("%d%d",&n,&m);Max[0]=a[1]=a[n+2]=-6666666;
for(int i=1;i<=n;++i)scanf("%d",&a[i+1]);
for(int i=1;i<=n+2;++i)id[i]=i;
build(1,n+2,0);rt=(n+3)>>1,cnt=n+2;
char s[10];
for(int i=1;i<=m;++i){
scanf("%s",s);
if(s[0]=='I'){scanf("%d%d",&k,&tot),Insert(k,tot);}
if(s[0]=='D'){scanf("%d%d",&k,&tot),del(k,tot);}
if(s[0]=='M'&&s[2]=='K'){int c;scanf("%d%d%d",&k,&tot,&c),Modify(k,tot,c);}
if(s[0]=='R'){scanf("%d%d",&k,&tot),rever(k,tot);}
if(s[0]=='G'){scanf("%d%d",&k,&tot),Querysum(k,tot);}
if(s[0]=='M'&&s[2]=='X'){printf("%d
",Max[rt]);}
}
return 0;
}