Luogu4513 小白逛公园

原题链接:https://www.luogu.org/problemnew/show/P4513

小白逛公园

题目背景

小新经常陪小白去公园玩,也就是所谓的遛狗啦…

题目描述

在小新家附近有一条“公园路”,路的一边从南到北依次排着 n 个公园,小白早就看花了眼,自己也不清楚该去哪些公园玩了。

一开始,小白就根据公园的风景给每个公园打了分-.-。小新为了省事,每次遛狗的时候都会事先规定一个范围,小白只可以选择第 a 个和第 b 个公园之间(包括 a b 两个公园)选择连续的一些公园玩。小白当然希望选出的公园的分数总和尽量高咯。同时,由于一些公园的景观会有所改变,所以,小白的打分也可能会有一些变化。

那么,就请你来帮小白选择公园吧。

输入输出格式
输入格式:

第一行,两个整数 N M ,分别表示表示公园的数量和操作(遛狗或者改变打分)总数。

接下来 N 行,每行一个整数,依次给出小白 开始时对公园的打分。

接下来 M 行,每行三个整数。第一个整数 K 1 2

K = 1 表示,小新要带小白出去玩,接下来的两个整数 a b 给出了选择公园的范围( 1 a , b N );

K = 2 表示,小白改变了对某个公园的打分,接下来的两个整数 p s ,表示小白对第 p 个公园的打分变成了 s 1 p N )。
其中, 1 N 500 000 1 M 100 000 ,所有打分都是绝对值不超过 1000 的整数。

输出格式:

小白每出去玩一次,都对应输出一行,只包含一个整数,表示小白可以选出的公园得分和的最大值。

输入输出样例
输入样例#1:

5 3
1 2 -3 4 5
1 2 3
2 2 -1
1 2 3

输出样例#1:

2
-1

题解

对于每个区间,维护它自己最大子段和。

只有最大子段和显然是无法合并的,我们还需要记录对于每个区间,以左/右端点开头的最大子段,以及自己的区间和,这样就可以合并了。

代码

数据给的区间 [ a , b ] 特么居然不保证 a b ,出题人真是 * * 。

#include<bits/stdc++.h>
#define ls v<<1
#define rs v<<1|1
using namespace std;
const int M=2e6+5;
struct sd{
    int lm,mx,rm,sum;
    sd(){lm=mx=rm=sum=-1e9;}
};
sd get(int a,int b,int c,int d){sd x;x.lm=a,x.mx=b,x.rm=c,x.sum=d;return x;}
int lm[M],rm[M],mx[M],sum[M],que[M],n,m;
void in(){scanf("%d%d",&n,&m);for(int i=1;i<=n;++i)scanf("%d",&que[i]);}
void up(int v){sum[v]=sum[ls]+sum[rs],lm[v]=max(lm[ls],sum[ls]+lm[rs]),rm[v]=max(rm[rs],rm[ls]+sum[rs]),mx[v]=max(max(mx[ls],mx[rs]),rm[ls]+lm[rs]);}
void build(int v,int le,int ri)
{
    if(le==ri){sum[v]=lm[v]=rm[v]=mx[v]=que[le];return;}
    int mid=le+ri>>1;build(ls,le,mid);build(rs,mid+1,ri);up(v);
}
sd ask(int v,int le,int ri,int lb,int rb)
{
    if(lb<=le&&ri<=rb){return get(lm[v],mx[v],rm[v],sum[v]);}
    int mid=le+ri>>1;sd ll,rr,ans;
    if(lb<=mid)ll=ask(ls,le,mid,lb,rb);if(mid<rb)rr=ask(rs,mid+1,ri,lb,rb);
    ans.lm=max(ll.lm,ll.sum+rr.lm),ans.rm=max(rr.rm,ll.rm+rr.sum),ans.mx=max(max(ll.mx,rr.mx),ll.rm+rr.lm);
    return ans;
}
void modify(int v,int le,int ri,int pos,int val)
{
    if(le==ri){mx[v]=lm[v]=rm[v]=sum[v]=val;return;}
    int mid=le+ri>>1;if(pos<=mid)modify(ls,le,mid,pos,val);if(mid<pos)modify(rs,mid+1,ri,pos,val);up(v);
}
void ac()
{
    int op,x,y;build(1,1,n);
    while(m--)
    {
        scanf("%d%d%d",&op,&x,&y);
        if(op==1){if(x>y)swap(x,y);printf("%d\n",ask(1,1,n,x,y).mx);}
        else modify(1,1,n,x,y);
    }
}
int main(){in();ac();}

猜你喜欢

转载自blog.csdn.net/ShadyPi/article/details/81173675
今日推荐