题目:https://www.luogu.org/problem/P4513
题意:操作1:每次查询[l, r]内的最大子段和,操作2:修改a[x] 为 y。
思路:线段树维护,注意查询时值的返回。
代码:
#include <bits/stdc++.h>
#define LL long long
#define ls rt<<1
#define rs rt<<1|1
using namespace std;
const int maxn = 5e5+5;
struct T{ int sum, lm, rm, mm;}t[maxn<<2];
int n, m, a[maxn];
void pushup(int rt){
t[rt].sum = t[ls].sum + t[rs].sum;
t[rt].lm = max(t[ls].lm, t[ls].sum+t[rs].lm);
t[rt].rm = max(t[rs].rm, t[rs].sum+t[ls].rm);
t[rt].mm = max(max(t[ls].mm, t[rs].mm), t[ls].rm+t[rs].lm);
}
void build(int rt, int l, int r){
t[rt].lm = t[rt].rm = t[rt].mm = t[rt].sum = a[l];
if(l == r) return ;
int mid = l+r >> 1;
build(ls, l, mid); build(rs, mid+1, r);
pushup(rt);
}
void update(int rt, int l, int r, int pos, int val){
if(l == r) {
t[rt].lm = t[rt].rm = t[rt].mm = t[rt].sum = val;
return ;
}
int mid = l+r >> 1;
if(pos <= mid) update(ls, l, mid, pos, val);
else update(rs, mid+1, r, pos, val);
pushup(rt);
}
T query(int rt, int l, int r, int L, int R){
if(L <= l && R >= r) return t[rt];
int mid = l+r >> 1;
if(R <= mid) return query(ls, l, mid, L, R);
else if(L > mid) return query(rs, mid+1, r, L, R);
else {
T res, t1 = query(ls, l, mid, L, R), t2 = query(rs, mid+1, r, L, R);
res.lm = max(t1.lm, t1.sum+t2.lm);
res.rm = max(t2.rm, t2.sum+t1.rm);
res.mm = max(max(t1.mm, t2.mm), t1.rm+t2.lm);
return res;
}
}
int main()
{
cin >> n >> m;
for(int i=1; i<=n; i++) cin >> a[i];
build(1, 1, n);
int op, x, y;
for(int i=1; i<=m; i++){
cin >> op >> x >> y;
if(op == 1) {
if(x > y) swap(x, y);
cout << query(1, 1, n, x, y).mm << endl;
}else update(1, 1, n, x, y);
}
}