题解:注意到本题的子序列实际上可以根据起始数值下标的奇偶性分为四类。对于每一类,如果你熟悉线段树,那么可以看出这个问题是可以进行区间合并的。即如果知道一个区间[L, R]两个子区间 [L,mid], [mid+1,R]的信息,我们可以推出[L,R]的信息。维护四个值,表示起点终点的下标的奇偶性。
线段树由子区间上传信息的时候,
偶数下标开始奇数下标结尾的最大值可以由 左儿子的偶偶+右儿子的奇奇 得到,也可以由左儿子的偶奇+右儿子偶奇得到。
当然,也可以直接由左儿子的偶奇或者右儿子的偶奇得到。
其他情况依此类推。
注意一下初始化的细节以及会有都是负数的情况。
#include <map>
#include <set>
#include <stack>
#include <queue>
#include <cmath>
#include <ctime>
#include <vector>
#include <cstdio>
#include <cctype>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
using namespace std;
#define INF 0x3f3f3f3f
#define inf -1LL<<61
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define mem0(a) memset(a,0,sizeof(a))
#define mem1(a) memset(a,-1,sizeof(a))
#define mem(a, b) memset(a, b, sizeof(a))
typedef long long ll;
const int maxn=100000;
ll max_odd_odd[4*maxn+1],max_odd_even[4*maxn+1], max_even_odd[4*maxn+1], max_even_even[4*maxn+1];
int a[maxn];
int p,L,R;
ll v;
ll max(ll a1,ll a2,ll a3,ll a4){
if(a1<a2)
a1=a2;
if(a1<a3)
a1=a3;
if(a1<a4)
a1=a4;
return a1;
}
struct node{
ll odd_odd;
ll odd_even;
ll even_odd;
ll even_even;
};
void pushup(int rt){
max_odd_odd[rt]=max(max_odd_odd[rt<<1],max_odd_odd[rt<<1|1],max_odd_odd[rt<<1]+max_even_odd[rt<<1|1],max_odd_even[rt<<1]+max_odd_odd[rt<<1|1]);
max_odd_even[rt]=max(max_odd_even[rt<<1],max_odd_even[rt<<1|1],max_odd_odd[rt<<1]+max_even_even[rt<<1|1],max_odd_even[rt<<1]+max_odd_even[rt<<1|1]);
max_even_odd[rt]=max(max_even_odd[rt<<1],max_even_odd[rt<<1|1],max_even_odd[rt<<1]+max_even_odd[rt<<1|1],max_even_even[rt<<1]+max_odd_odd[rt<<1|1]);
max_even_even[rt]=max(max_even_even[rt<<1],max_even_even[rt<<1|1],max_even_even[rt<<1]+max_odd_even[rt<<1|1],max_even_odd[rt<<1]+max_even_even[rt<<1|1]);
}
void build(int l,int r,int rt){
if(l==r){
max_odd_odd[rt]=inf;
max_even_odd[rt]=inf;
max_odd_even[rt]=inf;
max_even_even[rt]=inf;
if(l%2==1)
max_odd_odd[rt]=a[l];
else
max_even_even[rt]=a[l];
//printf("%d max_odd_odd is%lld,max_odd_even is%lld,max_even_odd is%lld,max_even_even is%lld\n",rt,max_odd_odd[rt],max_odd_even[rt],max_even_odd[rt],max_even_even[rt]);
return ;
}
int m=(l+r)>>1;
build(lson);
build(rson);
pushup(rt);
//printf("%d max_odd_odd is%I64d,max_odd_even is%I64d,max_even_odd is%I64d,max_even_even is%I64d\n",rt,max_odd_odd[rt],max_odd_even[rt],max_even_odd[rt],max_even_even[rt]);
}
void update(int l,int r,int rt){
if(l==r){
max_odd_odd[rt]=inf;
max_even_odd[rt]=inf;
max_odd_even[rt]=inf;
max_even_even[rt]=inf;
if(l%2==1)
max_odd_odd[rt]=v;
else
max_even_even[rt]=v;
return ;
}
int m=(l+r)>>1;
if(p<=m)
update(lson);
else
update(rson);
pushup(rt);
//printf("%d max_odd_odd is%I64d,max_odd_even is%I64d,max_even_odd is%I64d,max_even_even is%I64d\n",rt,max_odd_odd[rt],max_odd_even[rt],max_even_odd[rt],max_even_even[rt]);
}
node query(int l,int r,int rt){
node temp;
if(L<=l&&R>=r){
temp.odd_odd=max_odd_odd[rt];
temp.odd_even=max_odd_even[rt];
temp.even_odd=max_even_odd[rt];
temp.even_even=max_even_even[rt];
return temp;
}
int m=(l+r)>>1;
node temp1={inf,inf,inf,inf};
node temp2={inf,inf,inf,inf};
if(L<=m){
temp1=query(lson);
}
if(R>m)
temp2=query(rson);
temp.odd_odd=max(temp1.odd_odd,temp2.odd_odd,temp1.odd_odd+temp2.even_odd,temp1.odd_even+temp2.odd_odd);
temp.odd_even=max(temp1.odd_even,temp2.odd_even,temp1.odd_odd+temp2.even_even,temp1.odd_even+temp2.odd_even);
temp.even_even=max(temp1.even_even,temp2.even_even,temp1.even_odd+temp2.even_even,temp1.even_even+temp2.odd_even);
temp.even_odd=max(temp1.even_odd,temp2.even_odd,temp1.even_odd+temp2.even_odd,temp1.even_even+temp2.odd_odd);
return temp;
}
int main(){
int t;
int n,m;
//freopen("1001.in","r",stdin);
//freopen("1001.out","w",stdout);
scanf("%d",&t);
while(t--){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
build(1,n,1);
int op;
while(m--){
scanf("%d",&op);
if(op==1){
scanf("%d%I64d",&p,&v);
update(1,n,1);
}
else{
scanf("%d%d",&L,&R);
node ans=query(1,n,1);
printf("%I64d\n",max(ans.even_even,ans.even_odd,ans.odd_even,ans.odd_odd));
}
}
}
return 0;
}