Wannafly挑战赛10 D:小H的询问(线段树区间合并)

题目传送门

线段树区间合并模板题
代码:

#include<bits/stdc++.h>
using namespace std;

typedef long long ll;
const int maxn=100000+100;

/*
lm:从 l 位置开始的最大的有效子区间的权值和
rm:以 r 位置结束的最大的有效子区间的权值和
m: 区间[l,r]的最大的有效子区间的权值和
sum:区间[l,r]如果是有效区间,则sum是区间[l,r]的权值和,否则是负无穷大 
*/ 

struct Tree{

    int l,r;
    ll lm,rm,m,sum; 
}tree[maxn<<2];
ll val[maxn];

Tree merge(Tree lson,Tree rson){

    Tree fa;

    fa.l=lson.l;fa.r=rson.r;
    fa.lm=lson.lm;fa.rm=rson.rm;
    fa.m=max(lson.m,rson.m);
    fa.sum=(ll)-1e18; 
    if((val[lson.r]+val[rson.l])%2){

        fa.lm=max(fa.lm,lson.sum+rson.lm);
        fa.rm=max(fa.rm,lson.rm+rson.sum);
        fa.m=max(fa.m,lson.rm+rson.lm);
        fa.sum=max(fa.sum,lson.sum+rson.sum);
    }
    return fa;
}

void build(int root,int l,int r){

    if(l==r){

        tree[root].l=tree[root].r=l;
        tree[root].lm=tree[root].rm=tree[root].m=tree[root].sum=val[l];
        return ;
    }
    int mid=(l+r)>>1;
    build(root<<1,l,mid);
    build(root<<1|1,mid+1,r);
    tree[root]=merge(tree[root<<1],tree[root<<1|1]);
} 

void update(int root,int l,int r,int ind,int v){

    if(l==r){

        tree[root].lm=tree[root].rm=tree[root].m=tree[root].sum=val[l]=v;
        return ;
    }
    int mid=(l+r)>>1;
    if(mid>=ind) update(root<<1,l,mid,ind,v);
    else update(root<<1|1,mid+1,r,ind,v);
    tree[root]=merge(tree[root<<1],tree[root<<1|1]);
}

Tree query(int root,int l,int r,int L,int R){

    if(L<=l && R>=r) return tree[root];
    int mid=(l+r)>>1;
    if(mid>=R) return query(root<<1,l,mid,L,R);
    else if(mid<L) return query(root<<1|1,mid+1,r,L,R);
    else return merge(query(root<<1,l,mid,L,R),query(root<<1|1,mid+1,r,L,R));
}

int main(){

    int n,m;
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++) scanf("%lld",&val[i]);
    build(1,1,n);
    while(m--){

        int type,a,b;
        scanf("%d%d%d",&type,&a,&b);
        if(type) update(1,1,n,a,b);
        else printf("%lld\n",query(1,1,n,a,b).m);
    } 
} 

猜你喜欢

转载自blog.csdn.net/qq_37960603/article/details/81382361