题意:
区间[1, n],开始给出初值。
m个操作,包括单点修改和区间最大连续和询问。
思路:
重点在两个地方
1)维护,最大连续和可能在左半区间或右半区间,也可能跨越中点,为此我们需要对一个节点维护最大前缀和,最大后缀和,最大连续和,总和这四个变量。
2)查询,一个区间查询,覆盖了树上一些连续的节点,所以我们应该在查询的过程中把这些节点,相邻的两两合并,最后合并成一个节点返回。
借鉴了CLJ的代码,用失效节点来代替不存在的节点。感觉代码精炼了很多,+操作也得到复用了。写起来真的很溜。。
参考文章:
http://blog.csdn.net/jiangzh7/article/details/8745213
http://wjmzbmr.com/archives/vijos1083_white_the_park/
#define lson(x) ((x)<<1)
#define rson(x) (((x)<<1)+1)
struct node {
int pre_sum, suf_sum, tot_sum, sub_max;
node(int x = 0):pre_sum(0), suf_sum(0), tot_sum(x), sub_max(0){}
};
int v[Maxn+5];
node a[Maxn*4];
const node none(-inf); // 失效节点
node operator + (const node & lhs, const node & rhs) {
if (lhs.tot_sum == -inf) return rhs;
if (rhs.tot_sum == -inf) return lhs;
node ret;
ret.pre_sum = max (lhs.pre_sum, lhs.tot_sum + rhs.pre_sum);
ret.suf_sum = max (rhs.suf_sum, rhs.tot_sum + lhs.suf_sum);
ret.sub_max = max (max (lhs.sub_max, rhs.sub_max), lhs.suf_sum + rhs.pre_sum);
ret.tot_sum = lhs.tot_sum + rhs.tot_sum;
return ret;
}
void seg_edit(int L, int R, int o, int p, int x) {
if (L == R) {
a[o].pre_sum = a[o].suf_sum = a[o].sub_max = a[o].tot_sum = x;
return;
}
int lc = lson(o), rc = rson(o), mid = (L+R) >> 1;
if (p <= mid) {
seg_edit(L, mid, lc, p, x);
}
else {
seg_edit(mid+1, R, rc, p, x);
}
a[o] = a[lc] + a[rc];
}
node seg_query(int L, int R, int o, int qL, int qR) {
if (qR < L || qL > R) return none;
if (qL <= L && R <= qR) {return a[o];}
int mid = (L+R)>>1;
return seg_query(L, mid, lson(o), qL, qR) + seg_query(mid+1, R, rson(o), qL, qR);
}