http://www.spoj.pl/problems/GSS3/
题意:给出一个数列,求某个区间内的最大子序列和,并进行对某些点的更新。GSS1是个不更新只查询的简化版题目,差别不大。
跟hdu3397有点像,统计量也很像,但是犯了经验主义的错误,左起最大字段和=左区间左起最大字段和 或 左区间和+右区间左起最大字段和(如果左区间左起最大字段和==左区间和)是错误的,例如:100 -1 100 100,因此pushup操作应改为maxl=MAX(L[maxl],L[sum]+R[maxl]);
spoj对java支持不是很好,所以翻译了一个c--版本才能AC
#include<cstdio>
#include <algorithm>
using namespace std;
struct SegTree {
struct node {
int left, right;
int max, maxl, maxr, sum;
int mid() {
return (left + right) >> 1;
}
void init(int k) {
max = maxl = maxr = sum = k;
}
} tree[150010];
void init(int left, int right, int idx, int a[]) {
tree[idx].left = left;
tree[idx].right = right;
if (left == right) {
tree[idx].init(a[left]);
return;
}
int mid = tree[idx].mid();
init(left, mid, idx << 1, a);
init(mid + 1, right, (idx << 1)+1, a);
pushup(idx);
}
void update(int pos, int idx, int value) {
if (tree[idx].left == tree[idx].right && pos == tree[idx].left) {
tree[idx].init(value);
return;
}
int mid = tree[idx].mid();
if (pos <= mid)
update(pos, idx << 1, value);
else
update(pos, (idx << 1)+1, value);
pushup(idx);
}
node query(int left, int right, int idx) {
if (left == tree[idx].left && right == tree[idx].right) {
return tree[idx];
}
int mid = tree[idx].mid();
if (right <= mid)
return query(left, right, idx << 1);
else if (left > mid)
return query(left, right, (idx << 1) + 1);
else {
node ll = query(left, mid, idx << 1);
node rr = query(mid + 1, right, (idx << 1) + 1);
node ans;
ans.sum = ll.sum + rr.sum;
int a = ll.max;
int b = rr.max;
int c = ll.maxr + rr.maxl;
ans.max = max(max(a, b), c);
ans.maxl = max(ll.maxl, ll.sum + rr.maxl);
ans.maxr = max(rr.maxr, rr.sum + ll.maxr);
return ans;
}
}
int getanswer(int l, int r) {
return query(l, r, 1).max;
}
void pushup(int idx) {
if (tree[idx].left == tree[idx].right)
return;
int a = tree[idx << 1].max;
int b = tree[(idx << 1) + 1].max;
int c = tree[idx << 1].maxr + tree[(idx << 1) + 1].maxl;
tree[idx].max = max(max(a, b), c);
tree[idx].sum = tree[idx << 1].sum + tree[(idx << 1) + 1].sum;
a = tree[idx << 1].maxl;
b = tree[(idx << 1) + 1].maxl + tree[idx << 1].sum;
tree[idx].maxl = max(a, b);
a = tree[(idx << 1) + 1].maxr;
b = tree[(idx << 1) + 1].sum + tree[idx << 1].maxr;
tree[idx].maxr = max(a, b);
}
} st;
int main() {
int n, m, x, y, op;
int a[50010];
scanf("%d", &n);
for (int i = 1; i <= n; i++)
scanf("%d", a + i);
st.init(1, n, 1, a);
scanf("%d", &m);
while (m-- > 0) {
scanf("%d%d%d", &op, &x, &y);
if (op == 0)
st.update(x,1,y);
else
printf("%d\n", st.getanswer(x, y));
}
return 0;
}