1. 程式人生 > >HDU 5316 線段樹區間合併

HDU 5316 線段樹區間合併

題意:對數字序列有兩個操作,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;
}