HDU 5316
题意是给一个数列,有两种操作,一是询问[L,R]的最大子序列和,二是改变某个位置的值。单点修改,区间查询,很显然的线段树。关键在于,询问时的最大子序列要求相邻元素的在原序列中的位置奇偶性不同。
序列的奇偶性根据首位和末位的奇偶性最多就四种情况,奇奇,偶偶,奇偶,偶奇。
那么线段树中的每个节点保存这四种序列的最大和即可,并注意合并。
#include<bits/stdc++.h>
#define LS (root<<1)
#define RS ((root<<1)|1)
#define LSON LS,l,mid
#define RSON RS,(mid+1),r
#define MID mid=((l+r)/2)
#define LL long long
#define mm(a,b) memset(a,b,sizeof(a))
using namespace std;
const int maxn=1e5+5;
const LL Inf=1e18;
struct sum{
LL odd_odd, odd_even, even_odd, even_even;
sum(){odd_odd=-Inf; odd_even=-Inf; even_odd=-Inf; even_even=-Inf;}
};
sum s[maxn<<2];
LL a[maxn];
void pushup(int root){
s[root].odd_odd=max(max(s[LS].odd_odd, s[RS].odd_odd), max(s[LS].odd_odd+s[RS].even_odd, s[LS].odd_even+s[RS].odd_odd));
s[root].odd_even=max(max(s[LS].odd_even, s[RS].odd_even), max(s[LS].odd_odd+s[RS].even_even, s[LS].odd_even+s[RS].odd_even));
s[root].even_odd=max(max(s[LS].even_odd, s[RS].even_odd), max(s[LS].even_odd+s[RS].even_odd, s[LS].even_even+s[RS].odd_odd));
s[root].even_even=max(max(s[LS].even_even, s[RS].even_even), max(s[LS].even_even+s[RS].odd_even, s[LS].even_odd+s[RS].even_even));
}
void build(int root,int l,int r){
s[root].odd_odd=s[root].odd_even=s[root].even_odd=s[root].even_even=-Inf;
if(l==r){
if(l%2)
s[root].odd_odd=a[l];
else
s[root].even_even=a[l];
return;
}
int mid=(l+r)>>1;
build(LSON);
build(RSON);
pushup(root);
}
void update(int root,int l,int r,int pos,LL v){
if(l==r){
if(l%2)
s[root].odd_odd=v;
else
s[root].even_even=v;
return;
}
int mid=(l+r)>>1;
if(pos<=mid) update(LSON, pos, v);
else update(RSON, pos, v);
pushup(root);
}
sum unite(sum lsum, sum rsum){
sum ret;
ret.odd_odd=max(max(lsum.odd_odd, rsum.odd_odd), max(lsum.odd_odd+rsum.even_odd, lsum.odd_even+rsum.odd_odd));
ret.odd_even=max(max(lsum.odd_even, rsum.odd_even), max(lsum.odd_even+rsum.odd_even, lsum.odd_odd+rsum.even_even));
ret.even_odd=max(max(lsum.even_odd, rsum.even_odd), max(lsum.even_odd+rsum.even_odd, lsum.even_even+rsum.odd_odd));
ret.even_even=max(max(lsum.even_even, rsum.even_even), max(lsum.even_even+rsum.odd_even, lsum.even_odd+rsum.even_even));
return ret;
}
sum query(int root,int l,int r,int L,int R){
if(L<=l&&r<=R){
return s[root];
}
int mid=(l+r)>>1;
sum lsum, rsum;
if(L<=mid) lsum=query(LSON, L, R);
if(R>mid) rsum=query(RSON, L, R);
return unite(lsum,rsum);
}
int main(){
int T, n, m;
int op, L, R;
LL v;
scanf("%d",&T);
while(T--){
scanf("%d%d",&n, &m);
for(int i=1;i<=n;i++)
scanf("%lld",&a[i]);
build(1,1,n);
for(int i=0;i<m;i++){
scanf("%d",&op);
if(op==0){
scanf("%d%d", &L, &R);
sum ans=query(1,1,n,L,R);
printf("%lld\n",max(max(ans.odd_odd, ans.odd_even), max(ans.even_even, ans.even_odd)));
}else{
scanf("%d%lld",&L, &v);
update(1,1,n,L,v);
}
}
}
return 0;
}