1500: [NOI2005]维修数列
Time Limit: 10 Sec Memory Limit: 64 MBSubmit: 8397 Solved: 2530
Description
Input
输入文件的第1行包含两个数N和M,N表示初始时数列中数的个数,M表示要进行的操作数目。第2行包含N个数字,描述初始时的数列。以下M行,每行一条命令,格式参见问题描述中的表格。
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
#include<iostream> #include<cstring> #include<cstdio> using namespace std; #define N 500010 int n,m,num[N]; struct SplayTree { int sz[N],ch[N][2],pre[N],que[N],sta[N]; int top1,top2,root; int sum[N],maxm[N],maxl[N],maxr[N],val[N]; bool ro[N],same[N]; inline void SameNode(int x,int c) { if(x==0) return; val[x]=c; sum[x]=sz[x]*val[x]; maxm[x]=maxl[x]=maxr[x]=max(sum[x],val[x]); same[x]=1; } inline void ReverseNode(int x) { if(x==0) return; ch[x][0]^=ch[x][1]^=ch[x][0]^=ch[x][1]; maxl[x]^=maxr[x]^=maxl[x]^= maxr[x]; ro[x]^=1; } inline void PushDown(int x) { if(x==0) return; if(ro[x]) { ReverseNode(ch[x][0]); ReverseNode(ch[x][1]); ro[x]^=1; } if(same[x]) { SameNode(ch[x][0],val[x]); SameNode(ch[x][1],val[x]); same[x]=0; } } inline void PushUp(int x) { if(x==0) return; sz[x]=1+sz[ch[x][0]]+sz[ch[x][1]]; sum[x]=val[x]+sum[ch[x][0]]+sum[ch[x][1]]; maxl[x]=max(maxl[ch[x][0]],sum[ch[x][0]]+val[x]+max(0,maxl[ch[x][1]])); maxr[x]=max(maxr[ch[x][1]],sum[ch[x][1]]+val[x]+max(0,maxr[ch[x][0]])); maxm[x]=max(max(maxl[ch[x][1]],0)+val[x]+max(maxr[ch[x][0]],0),max(maxm[ch[x][0]],maxm[ch[x][1]])); } inline void Rotate(int x,int c) { int y=pre[x]; PushDown(y); PushDown(x); ch[y][!c]=ch[x][c]; if(ch[x][c]) pre[ch[x][c]]=y; pre[x]=pre[y]; if(pre[y]) ch[pre[y]][ch[pre[y]][1]==y]=x; ch[x][c]=y; pre[y]=x; PushUp(y); if(y==root) root=x; } inline void Splay(int x,int f) { PushDown(x); while(pre[x]!=f) { PushDown(pre[pre[x]]); PushDown(pre[x]); PushDown(x); if(pre[pre[x]]==f) Rotate(x,ch[pre[x]][0]==x); else { int y=pre[x],z=pre[y]; int c=(ch[z][0]==y); if(ch[y][c]==x) Rotate(x,!c),Rotate(x,c); else Rotate(y,c),Rotate(x,c); } } PushUp(x); if(f==0) root=x; } inline void SplayKth(int k,int f) { int x=root; k+=1; while(1) { PushDown(x); if(k==sz[ch[x][0]]+1) break; else if(k<=sz[ch[x][0]]) x=ch[x][0]; else k-=sz[ch[x][0]]+1,x=ch[x][1]; } Splay(x,f); } inline void Erase(int x) { int head=1,rear=1; que[head]=x; while(head<=rear) { sta[++top2]=que[head]; if(ch[que[head]][0]) que[++rear]=ch[que[head]][0]; if(ch[que[head]][1]) que[++rear]=ch[que[head]][1]; head++; } } inline void NewNode(int &x,int c) { if(top2) x=sta[top2--]; else x=++top1; ch[x][0]=ch[x][1]=pre[x]=0; sz[x]=1; ro[x]=same[x]=0; val[x]=sum[x]=maxm[x]=maxl[x]=maxr[x]=c; } inline void Build(int &x,int l,int r,int f) { if(l>r) return; int m=(l+r)>>1; NewNode(x,num[m]); Build(ch[x][0],l,m-1,x); Build(ch[x][1],m+1,r,x); pre[x]=f; PushUp(x); } inline void Init(int n) { ch[0][0]=ch[0][1]=pre[0]=sz[0]=0; ro[0]=same[0]=0; maxr[0]=maxl[0]=maxm[0]=-1001; sum[0]=0; root=top1=top2=0; for(int i=1;i<=n;i++) scanf("%d",&num[i]); Build(root,0,n+1,0); } void GetSum() { int a,b; scanf("%d%d",&a,&b); SplayKth(a-1,0); SplayKth(a+b,root); printf("%d ", sum[ch[ch[root][1]][0]]); } void MaxSum() { SplayKth(0, 0); SplayKth(sz[root]-1,root); printf("%d ",maxm[ch[ch[root][1]][0]]); } void Insert() { int pos,tot; scanf("%d%d",&pos,&tot); for(int i=1;i<=tot;i++) scanf("%d", &num[i]); SplayKth(pos,0); SplayKth(pos+1,root); Build(ch[ch[root][1]][0],1,tot,ch[root][1]); PushUp(ch[root][1]); PushUp(root); } void Delete() { int pos,tot; scanf("%d%d",&pos,&tot); SplayKth(pos-1,0); SplayKth(pos+tot,root); Erase(ch[ch[root][1]][0]); ch[ch[root][1]][0]=0; PushUp(ch[root][1]); PushUp(root); } void MakeSame() { int pos,tot,c; scanf("%d%d%d",&pos,&tot,&c); SplayKth(pos-1,0); SplayKth(pos+tot,root); SameNode(ch[ch[root][1]][0],c); } void Reverse() { int pos,tot; scanf("%d%d",&pos,&tot); SplayKth(pos-1,0); SplayKth(pos+tot,root); ReverseNode(ch[ch[root][1]][0]); } }t; int main() { char op[20]; scanf("%d%d",&n,&m); t.Init(n); while(m--) { scanf("%s",&op); if(op[0]=='G') t.GetSum(); else if(op[0]=='M' && op[2]=='X') t.MaxSum(); else if(op[0]=='I') t.Insert(); else if(op[0]=='D') t.Delete(); else if(op[0]=='M' && op[2]=='K') t.MakeSame(); else if(op[0]=='R') t.Reverse(); } return 0; }