AcWing 245. 你能回答这些问题吗
线段树维护多个信息,因为要找区间内连续子序列最大和,所以要多维护四个信息,分别是前缀和lmax,后缀和rmax,和区间和最大值tmax,还有区间总和sum
#include<bits/stdc++.h>
using namespace std;
const int N = 5e5 + 10;
struct Node{
int l, r;
int sum, lmax, rmax, tmax;
}tr[N * 4];
int n, m;
int w[N];
void pushup(Node &u, Node &l, Node &r){
u.sum = l.sum + r.sum;
u.lmax = max(l.lmax, l.sum + r.lmax);
u.rmax = max(r.rmax, l.rmax + r.sum);
u.tmax = max(l.rmax + r.lmax, max(l.tmax, r.tmax));
}
void pushup(int u){
pushup(tr[u], tr[u << 1], tr[u << 1 | 1]);
}
void build(int u, int l, int r){
if(l == r) tr[u] = {l, r, w[r], w[r], w[r], w[r]};
else{
tr[u] = {l, r};
int mid = l + r >> 1;
build(u << 1, l, mid);
build(u << 1 | 1, mid + 1, r);
pushup(u); //因为需要更新的信息多,所以建立之后也需要pushup
}
}
void modify(int u, int x, int v){
if(tr[u].l == x && tr[u].r == x) tr[u] = {x, x, v, v, v, v};
else{
int mid = tr[u].l + tr[u].r >> 1;
if(x <= mid) modify(u << 1, x, v);
else if(x > mid) modify(u << 1 | 1, x, v);
pushup(u);
}
}
Node query(int u, int l, int r){
if(tr[u].l >= l && tr[u].r <= r) return tr[u];
else{
int mid = tr[u].l + tr[u].r >> 1;
Node right, left;
if(r <= mid) return query(u << 1, l, r);
else if(l > mid) return query(u << 1 | 1, l, r);
else{ //横跨两个区间的情况
left = query(u << 1, l, r);
right = query(u << 1 | 1, l, r);
Node tree;
pushup(tree, left, right);
return tree;
}
}
}
int main()
{
cin>>n>>m;
for(int i = 1; i <= n; i ++ ) cin>>w[i];
build(1, 1, n);
for(int i = 1; i <= m; i ++ ){
int k, a, b;
cin>>k>>a>>b;
if(k == 1){
if(a > b) swap(a, b);
Node t = query(1, a, b);
cout<<t.tmax<<endl;
}
else{
modify(1, a, b);
}
}
return 0;
}