题目大意
给出一个由N个整数组成的序列A,你需要应用M个操作:
I p x
在 p 处插入插入一个元素 xD p
删除 p 处的一个元素R p x
修改 p 处元素的值为 xQ l r
查询一个区间[l,r]的最大子段和
输入格式
第一行一个数N,表示序列的长度
第二行N个数,表示初始序列A
第三行一个数M,表示操作的次数
接下来的M行,每行一个操作,格式见题目描述
输出格式
输出若干行,每行一个整数,表示查询区间的最大子段和
感谢@Anoxiacxy 提供的翻译
题目描述
Given a sequence A of N (N <= 100000) integers, you have to apply Q (Q <= 100000) operations:
Insert, delete, replace an element, find the maximum contiguous(non empty) sum in a given interval.
输入输出格式
输入格式:
The first line of the input contains an integer N.
The following line contains N integers, representing the starting
sequence A1..AN, (|Ai| <= 10000).
The third line contains an integer Q. The next Q lines contains the operations in following form:
I x y: insert element y at position x (between x - 1 and x).
D x : delete the element at position x.
R x y: replace element at position x with y.
Q x y: print max{Ai + Ai+1 + .. + Aj | x <= i <= j <= y}.
All given positions are valid, and given values are between -10000 and +10000.
The sequence will never be empty.
输出格式:
For each "Q" operation, print an integer(one per line) as described above.
输入输出样例
5
3 -4 3 -1 6
10
I 6 2
Q 3 5
R 5 -4
Q 3 5
D 2
Q 1 5
I 2 -10
Q 1 6
R 2 -1
Q 1 6
8
3
6
3
5
Solution:
某天下午和机房巨佬们比赛做这题谁最快AC,巨恶心。
题意毫无思维难度,写一个平衡树就好了,关键是信息的维护情况贼多,在更新子树信息时要把所有的情况都考虑到,然后就比较码农了。
代码:
/*Code by 520 -- 10.18*/ #include<bits/stdc++.h> #define il inline #define ll long long #define RE register #define For(i,a,b) for(RE int (i)=(a);(i)<=(b);(i)++) using namespace std; const int N=300005; int n,m,root,ch[N][2],rnd[N],date[N],cnt,siz[N]; int lf[N],rf[N],maxn[N],sum[N]; int gi(){ int a=0;char x=getchar();bool f=0; while((x<'0'||x>'9')&&x!='-') x=getchar(); if(x=='-') x=getchar(),f=1; while(x>='0'&&x<='9') a=(a<<3)+(a<<1)+(x^48),x=getchar(); return f?-a:a; } il int newnode(int v){ ++cnt; siz[cnt]=1,maxn[cnt]=sum[cnt]=date[cnt]=v,rnd[cnt]=rand(),lf[cnt]=rf[cnt]=max(date[cnt],0); return cnt; } il void up(int rt){ siz[rt]=siz[ch[rt][0]]+siz[ch[rt][1]]+1; sum[rt]=date[rt]+sum[ch[rt][0]]+sum[ch[rt][1]]; if(ch[rt][0]&&ch[rt][1]){ lf[rt]=max(lf[ch[rt][0]],date[rt]+sum[ch[rt][0]]+lf[ch[rt][1]]); rf[rt]=max(rf[ch[rt][1]],date[rt]+sum[ch[rt][1]]+rf[ch[rt][0]]); maxn[rt]=max(lf[ch[rt][1]]+date[rt]+rf[ch[rt][0]],max(maxn[ch[rt][0]],maxn[ch[rt][1]])); } else if(ch[rt][0]) lf[rt]=max(max(0,lf[ch[rt][0]]),sum[ch[rt][0]]+date[rt]),rf[rt]=max(0,date[rt]+rf[ch[rt][0]]),maxn[rt]=max(maxn[ch[rt][0]],rf[ch[rt][0]]+date[rt]); else if(ch[rt][1]) rf[rt]=max(max(0,rf[ch[rt][1]]),date[rt]+sum[ch[rt][1]]),lf[rt]=max(0,date[rt]+lf[ch[rt][1]]),maxn[rt]=max(maxn[ch[rt][1]],date[rt]+lf[ch[rt][1]]); else maxn[rt]=date[rt],lf[rt]=rf[rt]=max(date[rt],0); } int merge(int x,int y){ if(!x||!y) return x+y; if(rnd[x]<rnd[y]) {ch[x][1]=merge(ch[x][1],y),up(x);return x;} else {ch[y][0]=merge(x,ch[y][0]),up(y);return y;} } void split(int rt,int v,int &x,int &y){ if(!rt) {x=y=0;return;} if(siz[ch[rt][0]]>=v) y=rt,split(ch[rt][0],v,x,ch[y][0]),up(y); else x=rt,split(ch[rt][1],v-siz[ch[rt][0]]-1,ch[x][1],y),up(x); } il void ins(int k,int v){ int x,y; split(root,k-1,x,y); root=merge(merge(x,newnode(v)),y); } il void del(int k){ int x,y,z; split(root,k-1,x,y),split(y,1,y,z); root=merge(x,z); } il void change(int k,int v){ int x,y,z; split(root,k-1,x,y),split(y,1,y,z); root=merge(merge(x,newnode(v)),z); } il int query(int l,int r){ int x,y,z,ans; split(root,r,x,y),split(x,l-1,x,z); ans=maxn[z]; root=merge(merge(x,z),y); return ans; } int main(){ n=gi(); char opt[2];int x,y; For(i,1,n) ins(i,gi()); m=gi(); while(m--){ scanf("%s",opt),x=gi(); if(opt[0]=='I') y=gi(),ins(x,y); else if(opt[0]=='D') del(x); else if(opt[0]=='R') y=gi(),change(x,y); else y=gi(),printf("%d\n",query(x,y)); } return 0; }