首页 > 其他 > 详细

Can you answer these queries III(线段树)

时间:2020-01-31 12:57:33      阅读:63      评论:0      收藏:0      [点我收藏+]

Can you answer these queries III(luogu)

Description

维护一个长度为n的序列A,进行q次询问或操作

0 x y:把Ax改为y

1 x y:询问区间【l,r】的最大子段和

 数据范围:n,q<=5e4,-1e4<=Ai<=1e4;

Solution

线段树处理区间最大子段和

  • res为区间最大子串和
  • sum为区间和
  • prel和prer分别为从区间左端点和右端点开始的最大子串和

Code

 

#include <cstdio>
#include <cstdlib>
#include <algorithm>
#define ll long long
using namespace std;
const int N=5e4+10;
struct node
{
    ll sum,res,prel,prer;
    int l,r,lc,rc;
}f[N*2],t;
int opt,tot,rt,n,q,x,y;
ll d[N];
void push_up(int g)
{
    int lc=f[g].lc,rc=f[g].rc;
    if(!lc) return ;
    f[g].sum=f[lc].sum+f[rc].sum;
    f[g].prel=max(f[lc].prel,f[lc].sum+f[rc].prel);
    f[g].prer=max(f[rc].prer,f[rc].sum+f[lc].prer);
    f[g].res=max(max(f[lc].res,f[rc].res),f[lc].prer+f[rc].prel);
}
void build(int &g,int l,int r)
{
    g=++tot;
    f[g].l=l,f[g].r=r;
    if(l==r)
    {
        f[g].sum=f[g].prel=f[g].prer=f[g].res=d[l];
        return ;
    }
    int mid=(l+r)>>1;
    build(f[g].lc,l,mid),build(f[g].rc,mid+1,r);
    push_up(g);
}
void change(int g,int x,int y)
{
    if(f[g].l==f[g].r)
        f[g].sum=f[g].res=f[g].prel=f[g].prer=y;
    else
    {
        int mid=(f[g].l+f[g].r)>>1;
        if(x<=mid) change(f[g].lc,x,y);
        else change(f[g].rc,x,y);
        push_up(g);
    }
}
ll get(int g,int l,int r,node &a)
{
    if(f[g].l==l && f[g].r==r)
    {
        a=f[g];
        return a.res;
    }
    else
    {
        int mid=(f[g].l+f[g].r)>>1;
        if(r<=mid) return get(f[g].lc,l,r,a);
        else if(l>mid) return get(f[g].rc,l,r,a);
        else
        {
            node b,c;
            get(f[g].lc,l,mid,b);
            get(f[g].rc,mid+1,r,c);
            a.sum=b.sum+c.sum;
            a.prel=max(b.prel,b.sum+c.prel);
            a.prer=max(c.prer,c.sum+b.prer);
            a.res=max(max(b.res,c.res),b.prer+c.prel);
            return a.res;
        }
    }
}
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
        scanf("%lld",&d[i]);
    build(rt,1,n);
    scanf("%d",&q);
    while(q--)
    {
        scanf("%d%d%d",&opt,&x,&y);
        if(!opt) change(rt,x,y);
        else printf("%lld\n",get(rt,x,y,t));
    }
    return 0;
}

 

 

 

维护一个长度为 nn 的序列 AA,进行 mm 次询问或操作:

  • 0 x y:将 A_xAx? 单调修改为 yy
  • 1 x y:求出 \max\{\sum_{k=i}^j A_k\}(x\le i\le j\le y)max{k=ij?Ak?}(xijy)

数据范围:N,M\le 5\times 10^4N,M5×104|A_i|\le 10^4Ai?104

Can you answer these queries III(线段树)

原文:https://www.cnblogs.com/hsez-cyx/p/12244948.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!