Can you answer these queries III(线段树维护最大子段和)

题目传送门

题意
给一个原序列,有两种操作,第一种,单点修改:把原来下标为A的数修改为B,第二种:给出区间A到B中,最大连续子段和。

思路
这个题我们需要去维护四个东西,1、区间和,2、最大前缀和 3、最大后缀和 4、最大连续子段和
那么,pushup函数的写法如下

void pushup(int p)
{
    t[p].sum=t[ls].sum+t[rs].sum;
    t[p].x=max(t[ls].mar+t[rs].mal,max(t[ls].x,t[rs].x));
    t[p].mal=max(t[ls].sum+t[rs].mal,t[ls].mal);
    t[p].mar=max(t[rs].sum+t[ls].mar,t[rs].mar);
    return ;
}

总代码

//#include<bits/stdc++.h>
#include<iostream>
#include<algorithm>
#include<cstdio>
using namespace std;
typedef long long ll;
const int N=5e4+5;
const int mod=1e9+7;
const int INF=0x7fffffff;
//const ll LLINF=0x7fffffffffffffff;
const double EPS=1e-10;
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define pb push_back
#define pii pair<int,int>
#define pll pair<ll,ll>
#define debug cout<<"debug"<<endl;
#define ls p<<1
#define rs p<<1|1
//#define int long long
int a[N];
struct tree
{
    int l,r;
    int mal,mar,x,sum;
    tree()
    {
        mal=mar=x=sum=0;
    }
}t[N<<2];
void pushup(int p)
{
    t[p].sum=t[ls].sum+t[rs].sum;
    t[p].x=max(t[ls].mar+t[rs].mal,max(t[ls].x,t[rs].x));
    t[p].mal=max(t[ls].sum+t[rs].mal,t[ls].mal);
    t[p].mar=max(t[rs].sum+t[ls].mar,t[rs].mar);
    return ;
}
void build(int p,int x,int y)
{
    t[p].l=x;t[p].r=y;
    if(x==y)
    {
        t[p].sum=t[p].mal=t[p].mar=t[p].x=a[x];
        return ;
    }
    int mid=x+y>>1;
    build(ls,x,mid);
    build(rs,mid+1,y);
    pushup(p);
    return ;
}
void change(int p,int x,int y)
{
    if(t[p].l==x&&t[p].r==x)
    {
        t[p].sum=t[p].mal=t[p].mar=t[p].x=y;
        return ;
    }
    int mid=t[p].l+t[p].r>>1;
    if(x<=mid)
        change(ls,x,y);
    else
        change(rs,x,y);
    pushup(p);
    return ;
}
tree ask(int p,int x,int y)
{
    if(x==t[p].l&&t[p].r==y)
    {
        return t[p];
    }
    int mid=t[p].l+t[p].r>>1;
    tree a,b;
    if(y<=mid)
        return ask(ls,x,y);
    if(x>mid)
        return ask(rs,x,y);
    a=ask(ls,x,mid);
    b=ask(rs,mid+1,y);
    tree c;
    c.sum=a.sum+b.sum;
    c.x=max(a.mar+b.mal,max(a.x,b.x));
    c.mal=max(a.mal,a.sum+b.mal);
    c.mar=max(b.mar,a.mar+b.sum);
    return c;
}
signed main()
{
    IOS;
    //freopen("","r",stdin);
    //freopen("","w",stdout);
    int n;
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
    {
        scanf("%d",a+i);
    }
    build(1,1,n);
    int m;
    scanf("%d",&m);
    while(m--)
    {
        int oo,x,y;
        scanf("%d%d%d",&oo,&x,&y);
        if(oo==0)
        {
            change(1,x,y);
        }
        else
        {
            printf("%d\n",ask(1,x,y).x);
        }
    }

}
发布了93 篇原创文章 · 获赞 9 · 访问量 4204

猜你喜欢

转载自blog.csdn.net/Joker_He/article/details/104433324