Magician
题意:n个数,由1~n编号,每个数的范围是[-1000000000, 1000000000],两种操作:0 a b :输出区间[a, b]中子序列的最大和,并且该子序列中的每两个相邻元素在原序列中的下标的奇偶性不同; 1 a b :将下标为a的数改为b;
思路:这里的子序列并不需要连续;对于每段区间都有四种子序列:奇首奇尾(oo), 奇首偶尾(oe), 偶首奇尾(eo), 偶首偶尾(ee),(ood表示奇数, even表示偶数);所以在合并两个相邻区间时就有8种合并方式:
oo+eo=oo, oo+ee=oe, oe+oe=oe, oe+oo=oo, eo+eo=eo, eo+ee=ee, ee+oe=ee, ee+oo=eo;
线段树单点更新再加上上边的区间合并就是updata()这个函数了;
那么查询呢?也说对于在两个相邻区间的查询来说,不能单纯的query(m<<1, l, mid)+query(m<<1|1, mid+1, r),这样合并出来的区间可能并不符合题意;所以我们可以先返回一个区间t,然后像上边一样合并两个相邻区间;
#include <bits/stdc++.h>
#define inf 0x3f3f3f3f3f3f3f3f
using namespace std;
const int maxn=1e5+10;
typedef long long ll;
struct node{
int l, r;
ll oo, oe, eo, ee;
}tr[maxn<<2];
void pushup(int m){
tr[m].oo=max(max(tr[m<<1].oo, tr[m<<1|1].oo), max(tr[m<<1].oo+tr[m<<1|1].eo, tr[m<<1].oe+tr[m<<1|1].oo));
tr[m].oe=max(max(tr[m<<1].oe, tr[m<<1|1].oe), max(tr[m<<1].oo+tr[m<<1|1].ee, tr[m<<1].oe+tr[m<<1|1].oe));
tr[m].eo=max(max(tr[m<<1].eo, tr[m<<1|1].eo), max(tr[m<<1].eo+tr[m<<1|1].eo, tr[m<<1].ee+tr[m<<1|1].oo));
tr[m].ee=max(max(tr[m<<1].ee, tr[m<<1|1].ee), max(tr[m<<1].eo+tr[m<<1|1].ee, tr[m<<1].ee+tr[m<<1|1].oe));
}
void build(int m, int l, int r){
tr[m].l=l;
tr[m].r=r;
if(l==r){
ll x;
scanf("%lld", &x);
if(l%2){
tr[m].oo=x;
tr[m].oe=tr[m].eo=tr[m].ee=-inf;
}
else{
tr[m].ee=x;
tr[m].oe=tr[m].eo=tr[m].oo=-inf;
}
return;
}
int mid=(l+r)>>1;
build(m<<1, l, mid);
build(m<<1|1, mid+1, r);
pushup(m);
}
void updata(int m, int index, ll val){
if(tr[m].l==tr[m].r){
if(index%2){
tr[m].oo=val;
}
else{
tr[m].ee=val;
}
return;
}
int mid=(tr[m].l+tr[m].r)>>1;
if(index<=mid) updata(m<<1, index, val);
else updata(m<<1|1, index, val);
pushup(m);
}
node Union(node a, node b){
node t;
t.oo=max(max(a.oo, b.oo), max(a.oo+b.eo, a.oe+b.oo));
t.oe=max(max(a.oe, b.oe), max(a.oe+b.oe, a.oo+b.ee));
t.eo=max(max(a.eo, b.eo), max(a.eo+b.eo, a.ee+b.oo));
t.ee=max(max(a.ee, b.ee), max(a.ee+b.oe, a.eo+b.ee));
return t;
}
node query(int m, int l, int r){
if(tr[m].l==l&&tr[m].r==r){
return tr[m];
}
int mid=(tr[m].l+tr[m].r)>>1;
node temp;
if(r<=mid) temp=query(m<<1, l, r);
else if(l>mid) temp=query(m<<1|1, l, r);
else{
temp=Union(query(m<<1, l, mid), query(m<<1|1, mid+1, r));
}
return temp;
}
int main(){
int T;
scanf("%d", &T);
while(T--){
int n, m;
scanf("%d%d", &n, &m);
build(1, 1, n);
int type, a, b;
while(m--){
scanf("%d%d%d", &type, &a, &b);
if(type){
updata(1, a, (ll)b);
}
else{
node t=query(1, a, b);
printf("%lld\n", max(max(t.oo, t.oe), max(t.eo, t.ee)));
}
}
}
return 0;
}