这道题是线段树+动态规划??我看不见得,就是一个线段树区间合并求动态最大连续子串和,但是说实话这道题还是不那么简单的。不过思想就是基本的区间合并思想,每一个节点维护七个值,最大连续子串和,最小连续子串和,区间总和,左起最大连续子串和,右起最大连续子串和,左起最小连续子串和,右起最小连续子串和,七个值都维护出来以后,思想就是简简单单的区间合并思想(简单么。。)
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define lson l, m, rt << 1
#define rson m + 1, r, rt << 1 | 1
const int maxn = 111111;
int sum[maxn << 2];
int lmax[maxn << 2], rmax[maxn << 2];
int lmin[maxn << 2], rmin[maxn << 2];
int maxseg[maxn << 2], minseg[maxn << 2];
void PushUp(int rt){
sum[rt] = sum[rt << 1] + sum[rt << 1 | 1];//下面六行就是区间合并,其实看起来这些思想就是一般区间合并的一个变形。
maxseg[rt] = max(max(maxseg[rt << 1], maxseg[rt << 1 | 1]), rmax[rt << 1] + lmax[rt << 1 | 1]);
minseg[rt] = min(min(minseg[rt << 1], minseg[rt << 1 | 1]), rmin[rt << 1] + lmin[rt << 1 | 1]);
lmax[rt] = max(lmax[rt << 1], sum[rt << 1] + lmax[rt << 1 | 1]);
rmax[rt] = max(rmax[rt << 1 | 1], sum[rt << 1 | 1] + rmax[rt << 1]);
lmin[rt] = min(lmin[rt << 1], sum[rt << 1] + lmin[rt << 1 | 1]);
rmin[rt] = min(rmin[rt << 1 | 1], sum[rt << 1 | 1] + rmin[rt << 1]);
}
void build(int l, int r, int rt){
if (l == r){
scanf("%d", &sum[rt]);
lmax[rt] = rmax[rt] = lmin[rt] = rmin[rt] = maxseg[rt] = minseg[rt] = sum[rt];
return;
}
int m = (l + r) >> 1;
build(lson); build(rson);
PushUp(rt);
}
void update(int x, int c, int l, int r, int rt){
if (l == r){
sum[rt] = maxseg[rt] = minseg[rt] = lmax[rt] = rmax[rt] = lmin[rt] = rmin[rt] = c;
return;
}
int m = (l + r) >> 1;
if (x <= m) update(x, c, lson);
else update(x, c, rson);
PushUp(rt);
}
int main(){
int n, m, ans;
while(~scanf("%d", &n)){
build(1, n, 1);
scanf("%d", &m);
while(m--){
int x, y;
scanf("%d%d", &x, &y);
update(x, y, 1, n, 1);
if (sum[1] == maxseg[1])
ans = sum[1] - minseg[1];
else ans = max(maxseg[1], sum[1] - minseg[1]);
printf("%d\n", ans);
}
}
return 0;
}