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;
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值