BZOJ1500:[NOI2005]维修数列
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\n",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\n",Max[rt]);} } return 0; }