Virtualtan @ 2019-07-25 10:02:23
#include<cstdio>
#include<algorithm>
using namespace std;
#define MAX 500000+99
int n,m, a[MAX];
int sumv[MAX<<2], lm[MAX<<2], rm[MAX<<2], xm[MAX<<2];
/*
画图分析,几种情况
[a,b]中最大子段和 =
max( [左子树的最大子段和, 右子树的最大子段和, 过中间点且不到a,b的最大字段和 )
即: xm[o] = max( xm[o<<1], xm[o<<1|1], rm[o<<1]+lm[o<<1|1])
//注意这里是左子树和右子树的最大子段和, 而不是lm[o] 和 rm[o], 因为它最大的时候可能不经过边界
lm[o] = max(lm[o<<1], sumv[o<<1]+lm[o<<1|1] )
rm[o] = max(rm[o<<1|1], sumv[o<<1|1]+rm[o<<1] )
*/
void push_up(int o) {
sumv[o] = sumv[o<<1] + sumv[o<<1|1];
lm[o] = max(lm[o<<1], sumv[o<<1]+lm[o<<1|1]);
rm[o] = max(rm[o<<1|1], sumv[o<<1|1]+rm[o<<1]);
xm[o] = max( max(xm[o<<1], xm[o<<1|1]), rm[o<<1]+lm[o<<1|1] );//.......
}
void build(int o, int l, int r) {
if(l == r) {
sumv[o] = lm[o] = rm[o] = xm[o] = a[l];
return ;
}
int mid = (l+r)>>1;
build(o<<1, l, mid);
build(o<<1|1, mid+1, r);
push_up(o);
}
void update(int o, int l, int r, int t, int v) {
if(l == r) {
sumv[o] = lm[o] = rm[o] = xm[o] = v;
return ;
}
int mid = (l+r)>>1;
if(t <= mid) update(o<<1, l, mid, t, v);
else update(o<<1|1, mid+1, r, t, v);
push_up(o);
}
int query(int o, int l, int r, int ql, int qr) {
if(ql <= l && r <= qr) return xm[o];
int mid = (l+r)>>1;
int ans2 = 2147000047;
int ans1 = 2147000047;
if(ql <= mid) ans1 = query(o<<1, l, mid, ql, qr);
if(mid < qr) ans2 = query(o<<1|1, mid+1, r, ql, qr);
if(ans1 == 2147000047) return ans2;
if(ans2 == 2147000047) return ans1;
return max(ans1, ans2);
}
int main() {
scanf("%d%d",&n,&m);
for(int i = 1; i <= n; i++) scanf("%d",&a[i]);
build(1, 1, n);
int x,y,tmp;
for(int i = 1; i <= m; i++) {
scanf("%d%d%d",&tmp, &x, &y);
if(tmp == 1) { if(x > y) swap(x,y); printf("%d\n", query(1, 1, n, x, y)) ;}
else update(1, 1, n, x, y);
}
return 0;
}