问题描述:
acwing245 你能回答这些问题吗
题目链接:传送门
输入样例:
5 3
1 2 -3 4 5
1 2 3
2 2 -1
1 3 2
输出样例:
2
-1
思路:
要维护一个区间的连续最大字段和(tmax) ,就要从左右子区间来看,是否可以根据子区间维护出父区间的信息。
要想维护父区间的tmax, 它有这样几种情况:
-
该连续最大子段区间不跨越左右子区间,即单独在左子区间或右子区间
-
该连续最大子段区间跨越左右子区间,此时我们现有的信息不足以维护出父区间的最大子段区间,所以需要额外维护每个区间的最大前缀和(lmax) 和最大后缀和(rmax) 所以跨越左右子区间的最大子段区间 就可以由 左子区间的rmax + 右子区间的lmax 维护出来。
然后一个区间的最大前缀和和最大后缀和是否可以由现有信息维护出来,答案是不行的,
所以我们还需要多维护一个变量sum,保存父区间的所有数之和, 这样,一个区间的lmax = max(左子区间的lmax , 左子区间的sum + 右子区间的lmax) rmax也是同样的道理。
所以通过这道题,要维护信息时候,要维护到直到完备态才行,
代码:
#include <bits/stdc++.h>
using namespace std;
const int N = 500010;
struct node {
int l,r;
int tmax;
int lmax;
int rmax;
int sum;
} tr[N<<2];
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,r.sum + l.rmax);
u.tmax = max(max(l.tmax,r.tmax),l.rmax+r.lmax );
}
void pushup(int u) {
tr[u].sum = tr[u<<1].sum + tr[u<<1|1].sum;
tr[u].lmax = max(tr[u<<1].lmax, tr[u<<1].sum + tr[u<<1|1].lmax);
tr[u].rmax = max(tr[u<<1|1].rmax,tr[u<<1|1].sum + tr[u<<1].rmax);
tr[u].tmax = max(max(tr[u<<1].tmax,tr[u<<1|1].tmax),tr[u<<1].rmax+tr[u<<1|1].lmax );
// 或 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);
}
}
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 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];
int mid = tr[u].l + tr[u].r >> 1;
if(l>mid) return query(u<<1|1, l,r);
else if(r<=mid) return query(u<<1,l,r);
else {
node res;
auto left = query(u<<1,l,r);
auto right = query(u<<1|1,l,r);
pushup(res,left,right);
return res;
}
}
int main() {
cin>>n>>m;
for(int i=1; i<=n; i++) cin>>w[i];
build(1,1,n);
while(m--) {
int k,x,y;
cin>>k>>x>>y;
if(k==1) {
if(x>y) swap(x,y);
cout<<query(1,x,y).tmax<<endl;
} else modify(1,x,y);
}
return 0;
}