hdu5316 Magician(线段树区间合并)

题意:

T组数据

n个数,m个操作,0表示把位置a上的数改成b,1表示求区间[a,b]的最大的美丽子串和

美丽子串:相邻元素下标奇偶性不同,序列可不连续。


#include<iostream>
#include<cstdio>
#include<cstring>
#define LL __int64
#define lson rt<<1
#define rson rt<<1|1
using namespace std;

const int N=100100;
const LL INF=0x3f3f3f3f3f3f3f3f;

//子序列情况:奇始奇终、奇始偶终、偶始奇终、偶始偶终
struct Node
{
    int l,r;
    LL oo,ee,oe,eo;
    int Mid(){return (l+r)/2;}
}tree[4*N];

LL num[N];

LL Max(LL a,LL b)
{
    return a<b ?b :a;
}

void pushUp(int rt)
{
    LL a=tree[lson].oe+tree[rson].oe;
    LL b=tree[lson].eo+tree[rson].eo;
    LL c=tree[lson].ee+tree[rson].oo;
    LL d=tree[lson].oo+tree[rson].ee;

    LL e=tree[lson].oe+tree[rson].oo;
    LL f=tree[lson].oo+tree[rson].eo;
    LL g=tree[lson].ee+tree[rson].oe;
    LL h=tree[lson].eo+tree[rson].ee;

    tree[rt].oe=Max(Max(a,d),Max(tree[lson].oe,tree[rson].oe));
    tree[rt].eo=Max(Max(b,c),Max(tree[lson].eo,tree[rson].eo));
    tree[rt].oo=Max(Max(e,f),Max(tree[lson].oo,tree[rson].oo));
    tree[rt].ee=Max(Max(g,h),Max(tree[lson].ee,tree[rson].ee));
}

Node query(int rt,int l,int r)
{
    Node temp,t1,t2;
    if(tree[rt].l==l&&tree[rt].r==r){
        temp.eo=tree[rt].eo;
        temp.ee=tree[rt].ee;
        temp.oe=tree[rt].oe;
        temp.oo=tree[rt].oo;
        return temp;
    }
    if(r<=tree[rt].Mid()){
        return query(lson,l,r);
    }
    else if(l>tree[rt].Mid()){
        return query(rson,l,r);
    }
    else{
        t1=query(lson,l,tree[rt].Mid());
        t2=query(rson,tree[rt].Mid()+1,r);
        temp.oe=Max(Max(t1.oe+t2.oe,t1.oo+t2.ee),Max(t1.oe,t2.oe));
        temp.eo=Max(Max(t1.eo+t2.eo,t1.ee+t2.oo),Max(t1.eo,t2.eo));
        temp.oo=Max(Max(t1.oe+t2.oo,t1.oo+t2.eo),Max(t1.oo,t2.oo));
        temp.ee=Max(Max(t1.eo+t2.ee,t1.ee+t2.oe),Max(t1.ee,t2.ee));
        return temp;
    }
}

void update(int rt,int x,int v)
{
    if(tree[rt].l==x&&tree[rt].r==x){
        if(x&1){
            tree[rt].oo=v;
        }
        else{
            tree[rt].ee=v;
        }
        return;
    }
    if(x<=tree[rt].Mid()){
        update(2*rt,x,v);
    }
    else{
        update(2*rt+1,x,v);
    }
    pushUp(rt);
}

void build(int rt,int l,int r)
{
    tree[rt].l=l;tree[rt].r=r;
    if(l==r){
        if(l&1){
            tree[rt].oo=num[l];
            tree[rt].ee=-INF;
        }
        else{
            tree[rt].oo=-INF;
            tree[rt].ee=num[l];
        }
        tree[rt].eo=-INF;
        tree[rt].oe=-INF;
        return;
    }
    int mid=(l+r)/2;
    build(2*rt,l,mid);
    build(2*rt+1,mid+1,r);
    //向上合并
    pushUp(rt);
}

int main()
{
    //freopen("d:\\Test.txt","r",stdin);
    int T;
    int n,m;
    LL ans;
    scanf("%d",&T);
    while(T--){
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++){
            scanf("%I64d",&num[i]);
        }
        build(1,1,n);
        for(int i=1;i<=m;i++){
            int op,a,b;
            scanf("%d%d%d",&op,&a,&b);
            if(op==0){
                Node res=query(1,a,b);
                ans=Max(Max(res.ee,res.oo),Max(res.eo,res.oe));
                printf("%I64d\n",ans);
            }
            else if(op==1){
                update(1,a,b);
            }
        }
    }
    return 0;
}




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值