题意:有两种操作,查询操作求区间内的最大子序列,需要保证子序列的下标为奇偶交替的,还有单点修改操作。
思路:对于一个合法的子序列,只有可能是以奇奇,奇偶,偶奇,偶偶为开头和结尾。
线段树维护区间内的这四个值,重载加法运算符简化编程。
#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; }
版权声明:本文为博主原创文章,未经博主允许不得转载。
原文地址:http://blog.csdn.net/u014664226/article/details/47130033