题意:
给定长度为N的数列A,以及M条指令(N,M<=50000),每条指令可能是以下两种之一:
1."0 x y",把A【x】改成y。
2."1 x y",查询区间[x,y]中的最大连续子段和。
对于每次询问,输出一个整数表示答案。
分析:
一个区间的最大连续子段和只有三种情况。
图片来自:https://www.cnblogs.com/shenben/p/6361623.html
#include <bits/stdc++.h>
using namespace std;
#define N 100005
#define lson rt<<1
#define rson rt<<1|1
int a[N];
struct TREE{
int sum,gss,lgss,rgss;
}tr[N<<2];
void updata(int rt){
tr[rt].sum = tr[lson].sum+tr[rson].sum;
tr[rt].lgss = max(tr[lson].lgss,tr[lson].sum+tr[rson].lgss);
tr[rt].rgss = max(tr[rson].rgss,tr[rson].sum+tr[lson].rgss);
tr[rt].gss = max(max(tr[lson].gss,tr[rson].gss),tr[lson].rgss+tr[rson].lgss);
}
void bulid(int rt,int l,int r){
if(l == r){
tr[rt].sum = tr[rt].gss = tr[rt].lgss = tr[rt].rgss = a[l];
return;
}
int mid = l+r>>1;
bulid(lson,l,mid);
bulid(rson,mid+1,r);
updata(rt);
}
TREE query(int rt,int l,int r,int x,int y){
if(l == x&&r == y)return tr[rt];
int mid = l+r>>1;
if(y<=mid)return query(lson,l,mid,x,y);
else if(x>mid)return query(rson,mid+1,r,x,y);
else {
TREE left,right,result;
left = query(lson,l,mid,x,mid);
right = query(rson,mid+1,r,mid+1,y);
result.sum = left.sum = right.sum;
result.lgss = max(left.lgss,left.sum+right.lgss);
result.rgss = max(right.rgss,right.sum+left.rgss);
result.gss = max(left.gss,max(right.gss,left.rgss+right.lgss));
return result;
}
}
int main(){
int n,Que,x,y;
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
}
bulid(1,1,n);
scanf("%d",&Que);
for(int i=0;i<Que;i++){
scanf("%d%d",&x,&y);
printf("%d\n",query(1,1,n,x,y).gss);
}
return 0;
}