热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

P4513小白逛公园

1P4513小白逛公园题目链接:https:www.luogu.com.cnproblemP45132题目描述时间限制\(1s\)|空间限制\(128M\)在小新家附近有一条“公园

1 P4513 小白逛公园



  • 题目链接:https://www.luogu.com.cn/problem/P4513


2 题目描述

时间限制 \(1s\) | 空间限制 \(128M\)

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

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

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

数据范围:\(N\) 和 \(M\),分别表示表示公园的数量和操作(遛狗或者改变打分)总数, \(1≤N≤500000,1≤M≤1000001≤M≤100000\)


3 题解

我们考虑怎么 \(pushup\)。

如果只是纯粹地将两个子区间的最大连续子区间取 \(max\),那么答案是很不完备的。

我们从底层往上考虑:如果只取 \(max\),那么最终的效果就是求出了区间的最大值,显然这是错误的。我们发现:某个区间的最大连续子区间可能跨越两个子区间。

这个时候我们考虑一个贪心:跨越两个子区间的那个最大连续子区间一定是由左子区间的右侧的最大连续子区间和右子区间的左侧的最大连续子区间拼在一起得到的。这个贪心正确性显然,留给读者自己思考。

此时设 \(lsum\) 表示左侧的最大连续的子区间和,\(rsum\) 表示右侧的最大的连续的子区间和,\(ans\) 为区间的最大连续的区间和,则有

\(p.ans = max(max(p_{lc}.ans, p_{rc}.ans), p_{lc}.rsum + p_{rc}.lsum)\)

我们再来考虑怎么维护区间左侧和右侧的最大连续子区间和。

显然,我们不能只简单地把这个最大子区间和赋值为左子区间的左侧的最大子区间和或者右子区间的右侧的最大子区间和,因为这样我们就没有将另一个区间联系上。我们发现,如果右子区间的左侧的最大子区间和足够大,那么将左子区间和加上右子区间的左侧的最大子区间和很有可能比左子区间左侧的最大子区间和大,答案就应该更新为左子区间和加上右子区间的左侧的最大子区间和。右侧的最大连续子区间和同理。

形象化地说,再设 \(sum\) 表示某区间的区间和。

\(p.lsum = max(p_{lc}.lsum, p_{lc}.sum + p_{rc}.lsum)\)

\(p.rsum = max(p_{rc}.rsum, p_{rc}.sum + p_{lc}.rsum)\)

至于查询时,我们的函数类型为 \(node\),也就是线段树的类型。这样,当目标区间跨越左右两个子区间的时候,我们可以用类似于 \(pushup\) 的方法对答案进行维护,这样一来,我们就可以通过线段树处理复杂的信息了。


4 代码(空格警告):

#include
#include
using namespace std;
const int N = 5e5+10;
int n, m, opt, x, y;
struct node
{
int l, r, lsum, rsum, ans, sum;
}t[N*4];
void pushup(int p)
{
t[p].sum = t[p*2].sum + t[p*2+1].sum;
t[p].ans = max(max(t[p*2].ans, t[p*2+1].ans), t[p*2].rsum + t[p*2+1].lsum);
t[p].lsum = max(t[p*2].lsum, t[p*2].sum + t[p*2+1].lsum);
t[p].rsum = max(t[p*2+1].rsum, t[p*2+1].sum + t[p*2].rsum);
}
void build(int p, int l, int r)
{
t[p].l = l;
t[p].r = r;
if (l == r)
{
scanf("%d", &t[p].sum);
t[p].lsum = t[p].sum;
t[p].rsum = t[p].sum;
t[p].ans = t[p].sum;
return ;
}
int mid = (l+r)/2;
build(p*2, l, mid);
build(p*2+1, mid+1, r);
pushup(p);
}
void modify(int p, int pos, int d)
{
if (t[p].l == t[p].r)
{
t[p].sum = t[p].lsum = t[p].rsum = t[p].ans = d;
return ;
}
int mid = (t[p].l + t[p].r) / 2;
if (pos <= mid) modify(p*2, pos, d);
else modify(p*2+1, pos, d);
pushup(p);
}
node query(int p, int l, int r)
{
if (t[p].l >= l && t[p].r <= r) return t[p];
int mid = (t[p].l + t[p].r) / 2, cnt = 0;
node ans;
cnt += (l <= mid) + (r > mid);
if (l <= mid && cnt == 1) return query(p*2, l, r);
if (r > mid && cnt == 1) return query(p*2+1, l, r);
node cur, a, b;
a = query(p*2, l, r);
b = query(p*2+1, l, r);
cur.sum = a.sum + b.sum;
cur.ans = max(max(a.ans, b.ans), a.rsum + b.lsum);
cur.lsum = max(a.lsum, a.sum + b.lsum);
cur.rsum = max(b.rsum, b.sum + a.rsum);
return cur;
}
int main()
{
scanf("%d %d", &n, &m);
build(1, 1, n);
for (int i = 1; i <= m; i++)
{
scanf("%d %d %d", &opt, &x, &y);
if (opt == 1)
{
if (x > y) swap(x, y);
node cur = query(1, x, y);
printf("%d\n", cur.ans);
}
else modify(1, x, y);
}
return 0;
}

欢迎关注我的微信公众号:智子笔记



推荐阅读
  • 本文主要解析了Open judge C16H问题中涉及到的Magical Balls的快速幂和逆元算法,并给出了问题的解析和解决方法。详细介绍了问题的背景和规则,并给出了相应的算法解析和实现步骤。通过本文的解析,读者可以更好地理解和解决Open judge C16H问题中的Magical Balls部分。 ... [详细]
  • 本文讨论了使用差分约束系统求解House Man跳跃问题的思路与方法。给定一组不同高度,要求从最低点跳跃到最高点,每次跳跃的距离不超过D,并且不能改变给定的顺序。通过建立差分约束系统,将问题转化为图的建立和查询距离的问题。文章详细介绍了建立约束条件的方法,并使用SPFA算法判环并输出结果。同时还讨论了建边方向和跳跃顺序的关系。 ... [详细]
  • 本文介绍了P1651题目的描述和要求,以及计算能搭建的塔的最大高度的方法。通过动态规划和状压技术,将问题转化为求解差值的问题,并定义了相应的状态。最终得出了计算最大高度的解法。 ... [详细]
  • 本文讨论了一个数列求和问题,该数列按照一定规律生成。通过观察数列的规律,我们可以得出求解该问题的算法。具体算法为计算前n项i*f[i]的和,其中f[i]表示数列中有i个数字。根据参考的思路,我们可以将算法的时间复杂度控制在O(n),即计算到5e5即可满足1e9的要求。 ... [详细]
  • 李逍遥寻找仙药的迷阵之旅
    本文讲述了少年李逍遥为了救治婶婶的病情,前往仙灵岛寻找仙药的故事。他需要穿越一个由M×N个方格组成的迷阵,有些方格内有怪物,有些方格是安全的。李逍遥需要避开有怪物的方格,并经过最少的方格,找到仙药。在寻找的过程中,他还会遇到神秘人物。本文提供了一个迷阵样例及李逍遥找到仙药的路线。 ... [详细]
  • 本文介绍了Codeforces Round #321 (Div. 2)比赛中的问题Kefa and Dishes,通过状压和spfa算法解决了这个问题。给定一个有向图,求在不超过m步的情况下,能获得的最大权值和。点不能重复走。文章详细介绍了问题的题意、解题思路和代码实现。 ... [详细]
  • 云原生边缘计算之KubeEdge简介及功能特点
    本文介绍了云原生边缘计算中的KubeEdge系统,该系统是一个开源系统,用于将容器化应用程序编排功能扩展到Edge的主机。它基于Kubernetes构建,并为网络应用程序提供基础架构支持。同时,KubeEdge具有离线模式、基于Kubernetes的节点、群集、应用程序和设备管理、资源优化等特点。此外,KubeEdge还支持跨平台工作,在私有、公共和混合云中都可以运行。同时,KubeEdge还提供数据管理和数据分析管道引擎的支持。最后,本文还介绍了KubeEdge系统生成证书的方法。 ... [详细]
  • 本文介绍了设计师伊振华受邀参与沈阳市智慧城市运行管理中心项目的整体设计,并以数字赋能和创新驱动高质量发展的理念,建设了集成、智慧、高效的一体化城市综合管理平台,促进了城市的数字化转型。该中心被称为当代城市的智能心脏,为沈阳市的智慧城市建设做出了重要贡献。 ... [详细]
  • 向QTextEdit拖放文件的方法及实现步骤
    本文介绍了在使用QTextEdit时如何实现拖放文件的功能,包括相关的方法和实现步骤。通过重写dragEnterEvent和dropEvent函数,并结合QMimeData和QUrl等类,可以轻松实现向QTextEdit拖放文件的功能。详细的代码实现和说明可以参考本文提供的示例代码。 ... [详细]
  • 本文介绍了使用哈夫曼树实现文件压缩和解压的方法。首先对数据结构课程设计中的代码进行了分析,包括使用时间调用、常量定义和统计文件中各个字符时相关的结构体。然后讨论了哈夫曼树的实现原理和算法。最后介绍了文件压缩和解压的具体步骤,包括字符统计、构建哈夫曼树、生成编码表、编码和解码过程。通过实例演示了文件压缩和解压的效果。本文的内容对于理解哈夫曼树的实现原理和应用具有一定的参考价值。 ... [详细]
  • HDU 2372 El Dorado(DP)的最长上升子序列长度求解方法
    本文介绍了解决HDU 2372 El Dorado问题的一种动态规划方法,通过循环k的方式求解最长上升子序列的长度。具体实现过程包括初始化dp数组、读取数列、计算最长上升子序列长度等步骤。 ... [详细]
  • 本文介绍了UVALive6575题目Odd and Even Zeroes的解法,使用了数位dp和找规律的方法。阶乘的定义和性质被介绍,并给出了一些例子。其中,部分阶乘的尾零个数为奇数,部分为偶数。 ... [详细]
  • 本文讨论了clone的fork与pthread_create创建线程的不同之处。进程是一个指令执行流及其执行环境,其执行环境是一个系统资源的集合。在调用系统调用fork创建一个进程时,子进程只是完全复制父进程的资源,这样得到的子进程独立于父进程,具有良好的并发性。但是二者之间的通讯需要通过专门的通讯机制,另外通过fork创建子进程系统开销很大。因此,在某些情况下,使用clone或pthread_create创建线程可能更加高效。 ... [详细]
  • 浏览器中的异常检测算法及其在深度学习中的应用
    本文介绍了在浏览器中进行异常检测的算法,包括统计学方法和机器学习方法,并探讨了异常检测在深度学习中的应用。异常检测在金融领域的信用卡欺诈、企业安全领域的非法入侵、IT运维中的设备维护时间点预测等方面具有广泛的应用。通过使用TensorFlow.js进行异常检测,可以实现对单变量和多变量异常的检测。统计学方法通过估计数据的分布概率来计算数据点的异常概率,而机器学习方法则通过训练数据来建立异常检测模型。 ... [详细]
  • 本文介绍了一道网络流题目hdu4888 Redraw Beautiful Drawings的解题思路。题目要求以行和列作为结点建图,并通过最大流算法判断是否有解以及是否唯一。文章详细介绍了建图和算法的过程,并强调在dfs过程中要进行回溯。 ... [详细]
author-avatar
CCTV2财经2677
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有