您的位置:首页 > 其它

HDU 5316 Magician(线段树)

2015-07-29 16:40 204 查看

题意:有两种操作,查询操作求区间内的最大子序列,需要保证子序列的下标为奇偶交替的,还有单点修改操作。

思路:对于一个合法的子序列,只有可能是以奇奇,奇偶,偶奇,偶偶为开头和结尾。

线段树维护区间内的这四个值,重载加法运算符简化编程。

#include<cstdio>  
#include<cstring>  
#include<cmath>  
#include<cstdlib>  
#include<iostream>  
#include<algorithm>  
#include<vector>  
#include<map>  
#include<queue>  
#include<stack> 
#include<string>
#include<map> 
#include<set>
#define eps 1e-6 
#define LL long long  
using namespace std;  

const int maxn = 200000 + 100;
const LL INF = 1e14;
int a[maxn];
struct Node {
	LL jj, jo, oo, oj;
} nodes[2*maxn]; 
Node operator + (const Node& A, const Node& B) {
	Node t;
	t.jj = max(max(A.jj, B.jj), max(A.jo+B.jj, A.jj+B.oj));
	t.jo = max(max(A.jo, B.jo), max(A.jo+B.jo, A.jj+B.oo));
	t.oo = max(max(A.oo, B.oo), max(A.oo+B.jo, A.oj+B.oo));
	t.oj = max(max(A.oj, B.oj), max(A.oo+B.jj, A.oj+B.oj));
	return t;
}

struct seg_tree {
	void update(int o, int L, int R, int p, LL v) {
		int M = (R+L) >> 1;
		if(L == R) {
			if(L&1) nodes[o].jj = v;
			else nodes[o].oo = v;
		}
		else {
			if(p <= M) update(o*2, L, M, p, v); else update(o*2+1, M+1, R, p, v);
			nodes[o] = nodes[2*o] + nodes[2*o+1];	
		}
	}
	
	Node query(int o, int L, int R, int ql, int qr) {
		int M = (L+R) >> 1;
		LL ans = -INF;
		if(ql <= L && qr >= R) return nodes[o];
		if(ql > M) return query(2*o+1, M+1, R, ql, qr);
		else if(qr <= M) return query(2*o, L, M, ql, qr);
		else return query(2*o, L, M, ql, qr) + query(2*o+1, M+1, R, ql, qr);
	}
	
	LL Ans(int o, int L, int R, int ql, int qr) {
		Node t = query(o, L, R, ql, qr);
		return max(	 max(t.jj, t.jo),  max(t.oo, t.oj)  );
	}
	
	void built_tree(int o, int L, int R) {
		int M = (L+R) >> 1;
		if(L == R) {
			if(L&1) {
				nodes[o].jj = (LL)a[L];
				nodes[o].jo = nodes[o].oo = nodes[o].oj = -INF;
			}
			else {
				nodes[o].oo = (LL)a[L];
				nodes[o].jo = nodes[o].jj = nodes[o].oj = -INF;
			}
		}
		else {
			built_tree(o*2, L, M); built_tree(o*2+1, M+1, R);
			nodes[o] = nodes[2*o] + nodes[2*o+1];
		}
	}
} st;

int main() {
//	freopen("input.txt", "r", stdin);
	int t; cin >> t;
	int n, m;
	while(t--) {
		cin >> n >> m;
		for(int i = 1; i <= n; i++) scanf("%d", &a[i]);
		st.built_tree(1, 1, n);
		while(m--) {
			int t1, t2, t3;
			scanf("%d%d%d", &t1, &t2, &t3);
			if(!t1) cout << st.Ans(1, 1, n, t2, t3) << endl;
			else st.update(1, 1, n, t2, (LL)t3);
		}
	}
	return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: