标签:
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