题意:有两种操作,查询操作求区间内的最大子序列,需要保证子序列的下标为奇偶交替的,还有单点修改操作。
思路:对于一个合法的子序列,只有可能是以奇奇,奇偶,偶奇,偶偶为开头和结尾。
线段树维护区间内的这四个值,重载加法运算符简化编程。
#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;
}