线段树加最大连续子段和分治思想。
#include<cstdio>
#include<algorithm>
using namespace std;
const int maxn = 500000, INF = 1<<30;
int n, m, X, Y;
int sumv[4*maxn], a[maxn], lmaxv[4*maxn], rmaxv[4*maxn], maxv[4*maxn];
//int _s,_m,_lm,_rm;
struct Node{
int s, m, lm, rm;
};
void maintain(int o){
sumv[o] = sumv[o<<1] + sumv[o<<1|1];
lmaxv[o] = max(lmaxv[o<<1], sumv[o<<1]+lmaxv[o<<1|1]);
rmaxv[o] = max(rmaxv[o<<1|1], rmaxv[o<<1]+sumv[o<<1|1]);
maxv[o] = max(max(maxv[o<<1], maxv[o<<1|1]), rmaxv[o<<1]+lmaxv[o<<1|1]);
}
void create(int o, int l, int r){
if(l == r){
sumv[o] = lmaxv[o] = rmaxv[o] = maxv[o] = a[l];
}
else{
int m = (l+r)>>1;
create(o<<1, l, m);
create(o<<1|1, m+1, r);
maintain(o);
}
}
void update(int o, int l, int r){
if(l == r){
sumv[o] = lmaxv[o] = rmaxv[o] = maxv[o] = Y;
}
else{
int m = (l+r)>>1;
if(X <= m)update(o<<1, l, m);
else if(X > m)update(o<<1|1, m+1, r);
maintain(o);
}
}
Node query(int o, int l, int r){//这里一开始不想用结构体的。。然后发现好像必须得这么用
if(X <= l && r <= Y){
Node a;
a.m = maxv[o];
a.s = sumv[o];
a.lm = lmaxv[o];
a.rm = rmaxv[o];
return a;
}
else{
int m = (r+l)>>1;
if(X > m) return query(o<<1|1, m+1, r);
if(Y <= m) return query(o<<1, l, m);
Node a, b, c;
b = query(o<<1, l, m);
c = query(o<<1|1, m+1, r);
a.m = max(max(b.m, c.m), b.rm+c.lm);
a.rm = max(c.s+b.rm, c.rm);
a.lm = max(b.lm, b.s+c.lm);
return a;
}
}
int main(){
scanf("%d%d", &n, &m);
for(int i = 1; i <= n; i++)
scanf("%d", &a[i]);
create(1, 1, n);
int p;
while(m--){
scanf("%d %d %d",&p, &X, &Y);
if(p==2)
update(1, 1, n);
else{
if(X > Y)swap(X, Y);
//_m = _s = _lm = _rm = -INF;
printf("%d\n", query(1, 1, n).m);
}
}
return 0;
}