SPOJ/GSS3:Can you answer these queries III(线段树)

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




你可能感兴趣的:(java,c,struct,tree,query)