题目背景

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

题目描述

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

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

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

输入输出格式

输入格式:

第一行,两个整数 NNN 和 MMM ,分别表示表示公园的数量和操作(遛狗或者改变打分)总数。
接下来 NNN 行,每行一个整数,依次给出小白 开始时对公园的打分。
接下来 MMM 行,每行三个整数。第一个整数 KKK , 111 或 222 。

  • K=1K=1K=1 表示,小新要带小白出去玩,接下来的两个整数 aaa 和 bbb 给出了选择公园的范围( 1≤a,b≤N1≤a,b≤N1≤a,b≤N );
  • K=2K=2K=2 表示,小白改变了对某个公园的打分,接下来的两个整数 ppp 和 sss ,表示小白对第 ppp 个公园的打分变成了 sss ( 1≤p≤N1≤p≤N1≤p≤N )。
    其中, 1≤N≤5000001≤N≤500 0001≤N≤500000 , 1≤M≤1000001≤M≤100 0001≤M≤100000 ,所有打分都是绝对值不超过 100010001000 的整数。

输出格式:

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

输入输出样例

输入样例#1:

5 3
1 2 -3 4 5
1 2 3
2 2 -1
1 2 3
输出样例#1:

2
-1

Solution:

  本题实在是鬼~~(善用结构体啊!又是调半天不出来的题~)

  经典的带修改的区间最大连续子段和问题,典型的线段树嘛~!

  写了一个数组版线段树,不知道查询怎么去维护了,最后还是借鉴别人的代码,学了一波结构体写线段树的风格。

  建一棵线段树维护一下信息:$lmx$(与左边界相连的最大连续子段和),$rmx$(与右端点相连的最大连续子段和),$all$(整个区间的最大连续子段和),$sum$(整个区间的和)。

  那么还是正常的单点修改,只不过每次$pushup$自下而上维护节点$rt$的信息时,需要这些操作:

  1、当左儿子$ls$的$rmx$和右儿子$rs$的$lmx$均为$<0$时,整个区间的最大连续子段和$rt.all$直接取$Max(rs.lmx,ls.rmx)$。否则$rt.all$加上左右儿子中不为负值的$ls.rmx,rs.lmx$,然后$rt.all$再与单独的$ls.all$和$rs.all$中取最大值。

  2、当前节点$rt$的与左端点相连的最大连续子段和,在左儿子$ls.lmx$和右儿子$rs.lmx+ls.sum$中取最大值。

  3、同理当前节点$rt$的与右端点相连的最大连续子段和,在右儿子$rs.rmx$和左儿子$ls.rmx+rs.sum$中取最大值。

  4、不要忘了维护整个区间的和,$rt.sum=ls.sum+rs.sum$。

  (注意$pushup$函数的变量为结构体,左右儿子定义为$const node &ls$和$const node &rs$,因为查询时不能确定一段区间的最大连续子段和,所以需要想$pushup$函数一样更新一下整个区间的信息,定义变量为结构体能方便后面查询维护区间最大子段和,加$const$是因为$ls,rs$本身也是个变量)

  再讲下写的吐血的查询(注意坑点,区间可能$l>r$),整个递归过程参考了神犇的代码(这个结构体的递归写的太美妙了~!),首先将一段区间分为多个小区间,当区间包含时直接返回当前区间,然后每次递归向上用$pushup$维护整段查询的区间,引入一个结构体变量$a$记录整段区间的值。最后输出的是返回结构体变量的成员$all$(即该区间的最大连续子段和)。

  (写完此题,又“深度”理解了一波线段树~唉~太菜了`~)

代码:

#include<bits/stdc++.h>
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define il inline
#define ll long long
#define For(i,a,b) for(int (i)=(a);(i)<=(b);(i)++)
#define Max(a,b) ((a)>(b)?(a):(b))
using namespace std;
const int N=;
int n,m;
struct node{
ll sum,lmx,rmx,all;
}t[N<<];
il int gi(){
int a=;char x=getchar();bool f=;
while((x<''||x>'')&&x!='-')x=getchar();
if(x=='-')x=getchar(),f=;
while(x>=''&&x<='')a=(a<<)+(a<<)+x-,x=getchar();
return f?-a:a;
}
il void pushup(node &rt,const node &ls,const node &rs){
if(ls.rmx<&&rs.lmx<)rt.all=Max(ls.rmx,rs.lmx);
else {
rt.all=;
if(ls.rmx>)rt.all+=ls.rmx;
if(rs.lmx>)rt.all+=rs.lmx;
}
rt.all=Max(rt.all,Max(ls.all,rs.all));
rt.lmx=Max(ls.lmx,ls.sum+rs.lmx);
rt.rmx=Max(rs.rmx,rs.sum+ls.rmx);
rt.sum=ls.sum+rs.sum;
}
il void build(int l,int r,int rt){
if(l==r){t[rt].all=t[rt].sum=t[rt].lmx=t[rt].rmx=gi();return;}
int m=l+r>>;
build(lson),build(rson);
pushup(t[rt],t[rt<<],t[rt<<|]);
}
il void update(int L,int c,int l,int r,int rt){
if(l==r){t[rt].all=t[rt].sum=t[rt].lmx=t[rt].rmx=c;return;}
int m=l+r>>;
if(L<=m)update(L,c,lson);
else update(L,c,rson);
pushup(t[rt],t[rt<<],t[rt<<|]);
}
il node query(int L,int R,int l,int r,int rt){
if(L<=l&&R>=r)return t[rt];
int m=l+r>>;
if(L<=m&&R>m){node a;pushup(a,query(L,R,lson),query(L,R,rson));return a;}
else if(L<=m)return query(L,R,lson);
return query(L,R,rson);
}
int main(){
n=gi(),m=gi();
build(,n,);
int k,x,y,c;
while(m--){
k=gi();
if(k==){x=gi(),y=gi();if(x>y)swap(x,y);printf("%lld\n",query(x,y,,n,).all);}
else {x=gi(),c=gi(),update(x,c,,n,);}
}
return ;
}

P4513 小白逛公园的更多相关文章

  1. 洛谷 P4513 小白逛公园-区间最大子段和-分治+线段树区间合并(单点更新、区间查询)

    P4513 小白逛公园 题目背景 小新经常陪小白去公园玩,也就是所谓的遛狗啦… 题目描述 在小新家附近有一条“公园路”,路的一边从南到北依次排着nn个公园,小白早就看花了眼,自己也不清楚该去哪些公园玩 ...

  2. 线段树 || BZOJ1756: Vijos1083 小白逛公园 || P4513 小白逛公园

    题面:小白逛公园 题解: 对于线段树的每个节点除了普通线段树该维护的东西以外,额外维护lsum(与左端点相连的最大连续区间和).rsum(同理)和sum……就行了 代码: #include<cs ...

  3. luogu P4513 小白逛公园 (区间合并)

    链接:https://www.luogu.org/problemnew/show/P4513 思路: 很基础的区间合并,开四个数组: num: 区间数字的和 lsum:从左端点起最大连续字段和 rsu ...

  4. P4513 小白逛公园 动态维护最大子段和

    题目链接:https://www.luogu.org/problem/P4513 #include<iostream> #include<cstdio> #include< ...

  5. 洛谷P4513 小白逛公园

    区间最大子段和模板题.. 维护四个数组:prefix, suffix, sum, tree 假设当前访问节点为cur prefix[cur]=max(prefix[lson],sum[lson]+pr ...

  6. 2018.07.23 洛谷P4513 小白逛公园(线段树)

    传送门 线段树常规操作了解一下. 单点修改维护区间最大连续和. 对于一个区间,维护区间从左端点开始的连续最大和,从右端点开始的连续最大和,整个区间最大和,区间和. 代码如下: #include< ...

  7. P4513 小白逛公园 (线段树)

    题目链接 Solution 线段树是一门比较刁钻的手艺... 此题我们需要维护 \(4\) 个变量: \(amx\) 代表当前节点的最大值. \(lmx\) 代表当前节点以左端点为起点的区间最大值. ...

  8. 洛谷P4513 小白逛公园 (线段树)

    这道题看起来像是线段树和最大子段和的结合,但这里求最大子段和不用dp,充分利用线段树递归的优势来处理.个人理解:线段树相当于把求整个区间的最大子段和的问题不断划分为很多个小问题,容易解决小问题,然后递 ...

  9. [vijos P1083] 小白逛公园

    不知怎地竟有种错觉此题最近做过= =目测是类似的?那道题貌似是纯动归? 本来今晚想做两道题的,一道是本题,一道是P1653疯狂的方格取数或NOI08 Employee,看看现在的时间目测这个目标又达不 ...

随机推荐

  1. vuejs计算属性和侦听器

    <div id='root'> 姓:<input v-model='firstName'/> 名:<input v-model='secondName'/> < ...

  2. profix使用过程中遇到的一些问题

    1.(自动 DNS 模式检测) 本地 DNS 服务可用.通过代理服务器的名称解析已禁用. 我当时遇到的问题情况是:本来是可以正常上网的,然后用软件管家进行操作后,具体我也不记得了,反正是改动了 run ...

  3. Luogu [P1334] 瑞瑞的木板(手写堆)

    其实这个题完全不需要用手写堆,只需要一遍遍sort就行了…… 但是! 为了练习手写堆,还是用手写堆做了. 在做本题之前,如果你没有什么思路的话,建议先做Luogu的合并果子. 好,假设你已经做过了合并 ...

  4. 解决使用Application Loader上传ipa提示“上传appstore失败”

    试了好多次使用Application Loader上传ipa,一直提示上传失败,用其他mac电脑却可以,那就是环境有问题,笔者试过重装xcode,都无法解决问题, 查看日志类似是jdk版本问题,换了所 ...

  5. 4396: [Usaco2015 dec]High Card Wins

    Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 275  Solved: 175[Submit][Status][Discuss] Descriptio ...

  6. Python读取内容UnicodeDecodeError错误

    1.错误现象 环境:Python3.7 描述: 用open方法获取文件句柄: 用read/readlines方法一次读取文件所有内容: 尝试了编码GB2312/GBK/GB18030/UTF-8,发现 ...

  7. 684. Redundant Connection

    https://leetcode.com/problems/redundant-connection/description/ Use map to do Union Find. class Solu ...

  8. Java基础知识:Collection接口

    *本文是最近学习到的知识的记录以及分享,算不上原创. *参考文献见文末. 这篇文章主要讲的是java的Collection接口派生的两个子接口List和Set. 目录 Collection框架 Lis ...

  9. OpenCV学习笔记(一) 环境配置

    Visual Studio 2010 VS2010对应的OpenCV的lib文件(build\x86\vc10\lib)分为debug模式和release模式两种:debug模式牺牲速度,但能提供更多 ...

  10. POJ 2771 Guardian of Decency (二分图最大点独立集)

    Guardian of Decency Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 6133   Accepted: 25 ...