西安段素的取件最大只问题模板

西安段素线段树的连续取件最大只连续区间最大值问题模板

#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
struct node
{
    int sum;//总和
    int lv;//左起最大值
    int rv;//右起最大值
    int mv;//中间的最大值
};
node t[100000];
node null;
int base[100000];
void push_up(int root,int l,int m,int r)
{
    int _mv=0;
    t[root].sum=t[root<<1].sum+t[root<<1|1].sum;//合并总和,至于为什么要记录介个值,下面会用到
    t[root].lv=t[root].rv=t[root].mv=0;//归零
    t[root].lv=max(t[root<<1].lv,t[root<<1].sum+t[root<<1|1].lv);//从左起的最大值要么是左区间的左起最大,或者是左区间的全部加上右区间的左起最大值,这里就用到了sum
    t[root].rv=max(t[root<<1|1].rv,t[root<<1|1].sum+t[root<<1].rv);
    t[root].mv=max(t[root<<1].mv,max(t[root<<1|1].mv,t[root<<1].rv+t[root<<1|1].lv));//中间的最大值有三种情况,1.左区间的中间最大,2.右区间的中间最大,3.将左右区间拼起来的中间前左右拓展的最大值。
    return ;
}
void build(int root,int l,int r)
{
    if(l==r)
    {
        t[root].lv=t[root].mv=t[root].rv=t[root].sum=base[l];
        return ;
    }
    int mid=(l+r)>>1;
    build(root<<1,l,mid);
    build(root<<1|1,mid+1,r);
    push_up(root,l,mid,r);
}
void change(int root,int l,int r,int al,int ar,int k)//单点修改,只不过是强迫症写成立类似区间修改额样子
{
    if(l>ar||r<al)
        return ;
    if(l>=al&&r<=ar)
    {
        t[root].sum=t[root].lv=t[root].rv=t[root].mv=k;
        return ;
    }
    int mid=(l+r)>>1;
    change(root<<1,l,mid,al,ar,k);
    change(root<<1|1,mid+1,r,al,ar,k);
    push_up(root,l,mid,r);
    return ;
}
node check(int root,int l,int r,int al,int ar)
{
    if(l>ar||r<al)
        return null;//自定义的空
    if(l>=al&&r<=ar)
        return t[root];
    int mid=(l+r)>>1;
    node t1=check(root<<1,l,mid,al,ar);//对于询问的合并跟push_up是一样的。
    node t2=check(root<<1|1,mid+1,r,al,ar);
    node res;
    res.sum=t1.sum+t2.sum;
    res.lv=max(t1.lv,t1.sum+t2.lv);
    res.rv=max(t2.rv,t2.sum+t1.rv);
    res.mv=max(t1.rv+t2.lv,max(t1.mv,t2.mv));
    return res;
}
void init()
{
    null.sum=-0x7fffffff;
    null.mv=-0x7fffffff;
    null.lv=-0x7fffffff;
    null.rv=-0x7fffffff;//不影响答案的无限小
    return ;
}
int main()
{
    init();
    int n,m;
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)
        scanf("%d",&base[i]);
    build(1,1,n);
    int a,b,c;
    for(int i=1;i<=m;i++)
    {
        scanf("%d%d%d",&a,&b,&c);
        if(a==1)
            change(1,1,n,b,b,c);
        else
        {
            node res=check(1,1,n,b,c);          
            printf("%d\n",max(res.lv,max(res.mv,res.rv)));
        }
    }
    return 0;
}
//ps:因为没有数据测评,所以可能会有一些小bug,但大体框架就是介样的辣

猜你喜欢

转载自www.cnblogs.com/Lance1ot/p/9130220.html