你能回答这些问题吗

题目链接

题意:

给定长度为N的数列A,以及M条指令,每条指令可能是以下两种之一:

1、“1 x y”,查询区间 [x,y] 中的最大连续子段和,即 MAXxlry{r,i=A[i]}。

2、“2 x y”,把 A[x] 改成 y。

对于每个查询指令,输出一个整数表示答案。

思路:

用线段树维护一个区间和sum以及区间最大连续子段和dat,前缀最大连续子段和lmax,后缀最大连续子段和rmax。

容易推出pushup为

t[p].sum=t[p<<1].sum+t[p*2+1].sum;
t[p].lmax=max(t[p<<1].lmax,t[p<<1].sum+t[p*2+1].lmax);
t[p].rmax=max(t[p*2+1].rmax,t[p*2+1].sum+t[p<<1].rmax);
t[p].dat=max(max(t[p<<1].dat,t[p*2+1].dat),t[p<<1].rmax+t[p*2+1].lmax);

最后上代码

#include<cstdio>
#include<cstring>
#include<queue>
#include<cmath>
#include<algorithm>
#include<map>
#include<vector>
#include<string>
#include<set>
#define ll long long
using namespace std;
const int N=500000<<2;
int a[N>>2];
struct tree
{
    int sum,l,r,lmax,rmax,dat;
}t[N];
void pushup(int p)
{
    t[p].sum=t[p<<1].sum+t[p*2+1].sum;
    t[p].lmax=max(t[p<<1].lmax,t[p<<1].sum+t[p*2+1].lmax);
    t[p].rmax=max(t[p*2+1].rmax,t[p*2+1].sum+t[p<<1].rmax);
    t[p].dat=max(max(t[p<<1].dat,t[p*2+1].dat),t[p<<1].rmax+t[p*2+1].lmax);
}
void build(int p,int l,int r)
{
    t[p].l=l;
    t[p].r=r;
    if(l==r)
    {
        t[p].sum=t[p].lmax=t[p].rmax=t[p].dat=a[l];
        return;
    }
    int mid=(l+r)>>1;
    build(p<<1,l,mid);
    build(p*2+1,mid+1,r);
    pushup(p);
}
void change(int p,int x,int v)
{
    if (t[p].l==t[p].r)
    {
        t[p].dat=v;
        t[p].sum=v;
        t[p].lmax=v;
        t[p].rmax=v;
        return;
    }
    int mid=(t[p].l+t[p].r)>>1;
    if (x<=mid)
        change(p<<1,x,v);
    else
        change(p*2+1,x,v);
    pushup(p);
}
tree ask(int p,int l,int r)
{
    if (l<=t[p].l && r>=t[p].r)
        return t[p];
    int mid=(t[p].l+t[p].r)>>1,val=-(1<<30);
    tree a,b,c;
    a.dat=a.sum=a.lmax=a.rmax=val;
    b.dat=b.sum=b.lmax=b.rmax=val;
    c.sum=0;
    if(l<=mid)
    {
        a=ask(p<<1,l,r);
        c.sum+=a.sum;
    }
    if(r>mid)
    {
        b=ask(p*2+1,l,r);
        c.sum+=b.sum;
    }
    c.dat=max(max(a.dat,b.dat),a.rmax+b.lmax);
    c.lmax=max(a.lmax,b.lmax+a.sum);
    if(l>mid)
        c.lmax=max(c.lmax,b.lmax);
    c.rmax=max(b.rmax,b.sum+a.rmax);
    if(r<=mid)
        c.rmax=max(c.rmax,a.rmax);
    return c;
}
int main()
{
    int n,m;
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)
        scanf("%d",&a[i]);
    build(1,1,n);
    while(m--)
    {
        int k,x,y;
        scanf("%d%d%d",&k,&x,&y);
        
        if(k==1)
        {
            if(x>y)
            swap(x,y);
            tree r=ask(1,x,y);
            printf("%d\n",r.dat);
        }
        if(k==2)
        {
            change(1,x,y);
        }
    }
}

 

posted @ 2019-08-17 15:24  Ldler  Views(195)  Comments(0Edit  收藏  举报