HDU 5316 線段樹區間合併
阿新 • • 發佈:2019-02-07
題意:對數字序列有兩個操作,1是將值修改,而0是詢問a到b的最大值,最大值定義為所選的相鄰的數的下標一個為偶數一個為奇數
思路:肯定是線段樹的題目,因為有這樣的限制條件那麼會用到線段樹的區間合併,而這道題我們可以找最大值的情況很多,1可以是奇數開頭奇數結束的,2可以是奇數開頭偶數結束的,3可以是偶數開頭奇數結束的,4可以是偶數開頭偶數結束的,所以我們最後的最大值也要在這四個裡面選,那麼我們就要維護四個最大值了,而區間更新的操作就是模版用就好了,唯一要注意的就是在返回的時候我們不能直接返回四個中最大值,因為最下面的時候我們還可能有一個合併的操作
#include <stdio.h> #include <string.h> #include <stdlib.h> #include <iostream> #include <algorithm> using namespace std; typedef long long ll; typedef unsigned long long ull; const int inf=0x3f3f3f3f; const ll INF=0x3f3f3f3f3f3f; const int maxn=100010; ll max1[maxn*4],max2[maxn*4],max3[maxn*4],max4[maxn*4],A[maxn];//jj jo oj oo struct pos{ ll aa,ab,ba,bb; }; void pushup(int node){ max1[node]=max(max1[node<<1],max(max1[node<<1|1],max(max1[node<<1]+max3[node<<1|1],max2[node<<1]+max1[node<<1|1]))); max2[node]=max(max2[node<<1],max(max2[node<<1|1],max(max2[node<<1]+max2[node<<1|1],max1[node<<1]+max4[node<<1|1]))); max3[node]=max(max3[node<<1],max(max3[node<<1|1],max(max4[node<<1]+max1[node<<1|1],max3[node<<1]+max3[node<<1|1]))); max4[node]=max(max4[node<<1],max(max4[node<<1|1],max(max3[node<<1]+max4[node<<1|1],max4[node<<1]+max2[node<<1|1]))); } void buildtree(int le,int ri,int node){ max1[node]=max2[node]=max3[node]=max4[node]=-INF; if(le==ri){ if(le%2==0) max4[node]=A[le]; else max1[node]=A[le]; return ; } int t=(le+ri)>>1; buildtree(le,t,node<<1); buildtree(t+1,ri,node<<1|1); pushup(node); } void update(int pos,int val,int le,int ri,int node){ if(le==ri){ if(pos%2==0) max4[node]=(ll)val; else max1[node]=(ll)val; return ; } int t=(le+ri)>>1; if(pos<=t) update(pos,val,le,t,node<<1); else update(pos,val,t+1,ri,node<<1|1); pushup(node); } pos query(int l,int r,int le,int ri,int node){ if(l<=le&&ri<=r){ pos s; s.aa=max1[node];s.ab=max2[node],s.ba=max3[node],s.bb=max4[node]; return s; } int t=(le+ri)>>1; if(r<=t) return query(l,r,le,t,node<<1); if(l>t) return query(l,r,t+1,ri,node<<1|1); pos ans1=query(l,r,le,t,node<<1); pos ans2=query(l,r,t+1,ri,node<<1|1); pos ans3; ans3.aa=max(ans1.aa,max(ans2.aa,max(ans1.aa+ans2.ba,ans1.ab+ans2.aa))); ans3.ab=max(ans1.ab,max(ans2.ab,max(ans1.ab+ans2.ab,ans1.aa+ans2.bb))); ans3.ba=max(ans1.ba,max(ans2.ba,max(ans1.bb+ans2.aa,ans1.ba+ans2.ba))); ans3.bb=max(ans1.bb,max(ans2.bb,max(ans1.ba+ans2.bb,ans1.bb+ans2.ab))); return ans3; } int main(){ int T,n,m,a,b,c; scanf("%d",&T); while(T--){ scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) scanf("%I64d",&A[i]); buildtree(1,n,1); while(m--){ scanf("%d%d%d",&a,&b,&c); if(a==1) update(b,c,1,n,1); else{ pos ans=query(b,c,1,n,1); printf("%I64d\n",max(ans.aa,max(ans.ab,max(ans.ba,ans.bb)))); } } } return 0; }