标签:
Time Limit: 18000/9000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 1613 Accepted Submission(s): 470

题目大意:有t组测试数据。每组有n,m。分别表示有n个精灵,m次询问。每个精灵有个能量值(可能为负值)。询问时,1 a,b表示将a位置的精灵赋值为b。0 a,b表示查询从a位置到b位置的精灵的美丽子序列的最大和。美丽子序列为下标呈现奇偶交替出现的子序列。
解题思路:这个题目很显然是线段树的题目。唯一比较难处理的是查询区间时需要是奇偶交替的子序列和。所以我们考虑四种情况,即 奇偶、偶奇、奇奇、偶偶。偶数下标开始奇数下标结尾的最大值可以由 左儿子的偶偶+右儿子的奇奇 得到,也可以由左儿子的偶奇+右儿子偶奇得到。也可以是直接由左儿子或者右儿子的偶奇得到的。类推其他三种情况。
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+20;
const int INF=0x3f3f3f3f;
typedef long long INT;
#define mid (L+R)/2
#define lson rt*2,L,mid
#define rson rt*2+1,mid+1,R
#define max(a,b) ((a)>(b)?(a):(b))
INT a[maxn];
int n;
struct SegTree{
INT oj,jo,jj,oo;
void change(){
jo=jj=oo=oj=-INF;
}
}seg[maxn*4];
void PushUpDif(SegTree &ret,SegTree <ree,SegTree &rtree){
INT jjv1,jjv2,jov1,jov2,oov1,oov2,ojv1,ojv2;
jjv1=max(ltree.jj,rtree.jj);//从左右子树得到jj的情况
jjv2=max(ltree.jj+rtree.oj,ltree.jo+rtree.jj);//需要合并左子树jj右子树oj和左子树jo右子树jj的情况
ret.jj=max(jjv1,jjv2);//取最值
//下面三种同理可得
ojv1=max(ltree.oj,rtree.oj);
ojv2=max(ltree.oo+rtree.jj,ltree.oj+rtree.oj);
ret.oj=max(ojv1,ojv2);
jov1=max(ltree.jo,rtree.jo);
jov2=max(ltree.jj+rtree.oo,ltree.jo+rtree.jo);
ret.jo=max(jov1,jov2);
oov1=max(ltree.oo,rtree.oo);
oov2=max(ltree.oj+rtree.oo,ltree.oo+rtree.jo);
ret.oo=max(oov1,oov2);
}
void build(int rt,int L,int R){
seg[rt].jo=seg[rt].oj=seg[rt].jj=seg[rt].oo=-INF;
if(L==R){
if(L%2==0){
seg[rt].oo=a[L];
}else{
seg[rt].jj=a[L];
}
return ;
}
build(lson);
build(rson);
PushUpDif(seg[rt],seg[rt*2],seg[rt*2+1]);
}
void update(int rt,int L,int R,INT pos,INT val){
if(L==R){
if(L%2==0){
seg[rt].oo=val;
}else{
seg[rt].jj=val;
}
return ;
}
if(pos<=mid){
update(lson,pos,val);
}else{
update(rson,pos,val);
}
PushUpDif(seg[rt],seg[rt*2],seg[rt*2+1]);
}
SegTree query(int rt,int L,int R,INT l_ran,INT r_ran){
if(l_ran<=L&&R<=r_ran){
return seg[rt];
}
SegTree ret,lret,rret;
ret.change(),lret.change(),rret.change();
if(l_ran<=mid){
lret=query(lson,l_ran,r_ran);
}
if(r_ran>mid){
rret=query(rson,l_ran,r_ran);
}
PushUpDif(ret,lret,rret);
return ret;
}
int main(){
int t,m,typ;
INT aa,bb;
SegTree ans;
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%lld%lld",&typ,&aa,&bb);
if(typ==1){
update(1,1,n,aa,bb);
}else{
ans=query(1,1,n,aa,bb);
INT ans1=max(ans.jj,ans.oo),ans2=max(ans.jo,ans.oj);
printf("%lld\n",max(ans1,ans2));
}
}
}
return 0;
}
/*
20
10 6
1 2 3 4 5 5 6 -4 5 10
0 1 5
0 4 7
0 4 8
1 1 -1
0 1 3
0 1 4
5 3
-5 7 -3 4 5
0 1 3
1 1 0
0 1 3
*/
HDU 5316——Magician——————【线段树区间合并区间最值】
标签:
原文地址:http://www.cnblogs.com/chengsheng/p/4687828.html