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; }