题目大意

给出一个由N个整数组成的序列A,你需要应用M个操作:

  • I p x p  处插入插入一个元素 x
  • D p 删除 p 处的一个元素
  • R p x 修改 p 处元素的值为 x
  • Q 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.

输入输出样例

输入样例#1: 
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
输出样例#1: 
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;
}