【挖坑】【GSS系列】GSS1:区间最大子段和

2023-10-27 14:59

本文主要是介绍【挖坑】【GSS系列】GSS1:区间最大子段和,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

Can you answer these queries?

​ GSS系列是spoj出品的一套数据结构好毒瘤题,主要以线段树、平衡树和树链剖分为背景,进行了一些操作的魔改,使得难度远超模板题,但对于思维有极大的提升。

​ 所以我会选择一些在我能力范围内的题挖坑选讲,构成一个GSS系列。至于剩下那些,等我成为巨佬弄懂了再说吧。

GSS1:区间最大子段和

原题传送门(洛谷)

题意

给定一个序列,无修改操作,查询某一段区间的最大子段和。

口胡

​ 首先,题目要求区间查询,那么第一感觉就是使用线段树维护。那么如何维护一个区间的最大子段和呢?在线段树中,push_up和push_down操作永远是最关键的,但由于本题无修改操作,所以只需要关心push_up操作。于是考虑两个相邻区间如何合并成为一个更大的区间。(随便瞎搞一下就好了)

​ 我们设一个区间的从左端点开始的最大子段和为 l s ls ls,同理从右端点开始为 r s rs rs,整段区间和为 s u m sum sum,区间最大子段和为 m x mx mx

​ 那么一个大区间的 l s ls ls就可以由左半区间的 l s ls ls或左区间的 s u m sum sum加上右区间的 l s ls ls,同理求得 r s rs rs m x mx mx可以由左右区间的 m x mx mx和合并后中间的最大子段和(左区间的 r s rs rs和右区间的 l s ls ls)合并而来。

图解

GSS1 1.PNG

​ 如图,对于一个大区间,它的 l s ls ls可以是上图的两条黄色线段,即

ls[p] = max(ls[lc(p)], sum[lc(p)]+ls[rc(p)]),同理可求得 r s rs rs

​ 对于区间的 m x ​ mx​ mx,显然可以是上图的三条红色线段,即

mx[p] = max(mx[lc(p)], mx[rc(p)], rs[lc(p)]+ls[rc(p)])


​ 讲完了维护,接下来就是一些查询的套路了。由于我们查询的最大子段和不能仅依靠自己进行合并。所以即使我们知道了左右区间的最大子段和,也不能立马得出当前区间的最大子段和。所以我们选择在查询的时候直接返回一个节点。这样就可以获取到所有子区间的信息,再通过上述方法合并就可得到最后的答案。

代码:

#include <bits/stdc++.h>
#define MAXN 50005
#define lc(x) (x<<1)
#define rc(x) (x<<1|1)
#define mid ((l+r)>>1)
using namespace std;struct node{int sum, ls, rs, ms;		//区间和,分别从左右端点开始的最大子段和,区间最大子段和 
};int n, m, val[MAXN];
node a[MAXN*4];void push_up(int p){			//将子区间合并到父亲区间a[p].sum = a[lc(p)].sum + a[rc(p)].sum;a[p].ls = max(a[lc(p)].ls, a[lc(p)].sum+a[rc(p)].ls);a[p].rs = max(a[rc(p)].rs, a[rc(p)].sum+a[lc(p)].rs);a[p].ms = max(max(a[lc(p)].ms, a[rc(p)].ms), a[lc(p)].rs + a[rc(p)].ls);
}void build(int p, int l, int r){if(l == r){a[p].sum = a[p].ls = a[p].rs = a[p].ms = val[l];return;}build(lc(p), l, mid);build(rc(p), mid+1, r);push_up(p);
}node query(int p, int l, int r, int ul, int ur){	//返回节点所有信息if(l>=ul && r<=ur){return a[p];}if(ul > mid){		//两个特判,判断所查询的区间被当前的左或右区间包含,直接去相应子区间查询return query(rc(p), mid+1, r, ul, ur);}if(ur <= mid){return query(lc(p), l, mid, ul, ur);}node res, tl, tr;			//合并答案,具体原理看图解分析tl = query(lc(p), l, mid, ul, ur);tr = query(rc(p), mid+1, r, ul, ur);res.sum = tl.sum + tr.sum;res.ls = max(tl.ls, tl.sum+tr.ls);res.rs = max(tr.rs, tr.sum+tl.rs);res.ms = max(max(tl.ms, tr.ms), tl.rs+tr.ls);return res;
}int main()
{cin >> n;for(int i = 1; i <= n; i++){scanf("%d", &val[i]);}build(1, 1, n);cin >> m;int x, y;while(m--){scanf("%d%d", &x, &y);printf("%d\n", query(1,1,n, x, y).ms);}return 0;
}

What to do next?

GSS3: 带单点修改的最大子段和

​ 其实在真正了解了区间最大子段和求法之后,即使是带修改,也并没有增加任何难度,因为实际上修改并不影响任何最大子段和的性质,无非多加一个普通的修改函数而已。

这篇关于【挖坑】【GSS系列】GSS1:区间最大子段和的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/286437

相关文章

如何提高Redis服务器的最大打开文件数限制

《如何提高Redis服务器的最大打开文件数限制》文章讨论了如何提高Redis服务器的最大打开文件数限制,以支持高并发服务,本文给大家介绍的非常详细,感兴趣的朋友跟随小编一起看看吧... 目录如何提高Redis服务器的最大打开文件数限制问题诊断解决步骤1. 修改系统级别的限制2. 为Redis进程特别设置限制

Spring Security 从入门到进阶系列教程

Spring Security 入门系列 《保护 Web 应用的安全》 《Spring-Security-入门(一):登录与退出》 《Spring-Security-入门(二):基于数据库验证》 《Spring-Security-入门(三):密码加密》 《Spring-Security-入门(四):自定义-Filter》 《Spring-Security-入门(五):在 Sprin

科研绘图系列:R语言扩展物种堆积图(Extended Stacked Barplot)

介绍 R语言的扩展物种堆积图是一种数据可视化工具,它不仅展示了物种的堆积结果,还整合了不同样本分组之间的差异性分析结果。这种图形表示方法能够直观地比较不同物种在各个分组中的显著性差异,为研究者提供了一种有效的数据解读方式。 加载R包 knitr::opts_chunk$set(warning = F, message = F)library(tidyverse)library(phyl

hdu 1754 I Hate It(线段树,单点更新,区间最值)

题意是求一个线段中的最大数。 线段树的模板题,试用了一下交大的模板。效率有点略低。 代码: #include <stdio.h>#include <string.h>#define TREE_SIZE (1 << (20))//const int TREE_SIZE = 200000 + 10;int max(int a, int b){return a > b ? a :

【生成模型系列(初级)】嵌入(Embedding)方程——自然语言处理的数学灵魂【通俗理解】

【通俗理解】嵌入(Embedding)方程——自然语言处理的数学灵魂 关键词提炼 #嵌入方程 #自然语言处理 #词向量 #机器学习 #神经网络 #向量空间模型 #Siri #Google翻译 #AlexNet 第一节:嵌入方程的类比与核心概念【尽可能通俗】 嵌入方程可以被看作是自然语言处理中的“翻译机”,它将文本中的单词或短语转换成计算机能够理解的数学形式,即向量。 正如翻译机将一种语言

poj 3723 kruscal,反边取最大生成树。

题意: 需要征募女兵N人,男兵M人。 每征募一个人需要花费10000美元,但是如果已经招募的人中有一些关系亲密的人,那么可以少花一些钱。 给出若干的男女之间的1~9999之间的亲密关系度,征募某个人的费用是10000 - (已经征募的人中和自己的亲密度的最大值)。 要求通过适当的招募顺序使得征募所有人的费用最小。 解析: 先设想无向图,在征募某个人a时,如果使用了a和b之间的关系

poj 3258 二分最小值最大

题意: 有一些石头排成一条线,第一个和最后一个不能去掉。 其余的共可以去掉m块,要使去掉后石头间距的最小值最大。 解析: 二分石头,最小值最大。 代码: #include <iostream>#include <cstdio>#include <cstdlib>#include <algorithm>#include <cstring>#include <c

poj 2175 最小费用最大流TLE

题意: 一条街上有n个大楼,坐标为xi,yi,bi个人在里面工作。 然后防空洞的坐标为pj,qj,可以容纳cj个人。 从大楼i中的人到防空洞j去避难所需的时间为 abs(xi - pi) + (yi - qi) + 1。 现在设计了一个避难计划,指定从大楼i到防空洞j避难的人数 eij。 判断如果按照原计划进行,所有人避难所用的时间总和是不是最小的。 若是,输出“OPETIMAL",若

poj 2135 有流量限制的最小费用最大流

题意: 农场里有n块地,其中约翰的家在1号地,二n号地有个很大的仓库。 农场有M条道路(双向),道路i连接着ai号地和bi号地,长度为ci。 约翰希望按照从家里出发,经过若干块地后到达仓库,然后再返回家中的顺序带朋友参观。 如果要求往返不能经过同一条路两次,求参观路线总长度的最小值。 解析: 如果只考虑去或者回的情况,问题只不过是无向图中两点之间的最短路问题。 但是现在要去要回

poj 2594 二分图最大独立集

题意: 求一张图的最大独立集,这题不同的地方在于,间接相邻的点也可以有一条边,所以用floyd来把间接相邻的边也连起来。 代码: #include <iostream>#include <cstdio>#include <cstdlib>#include <algorithm>#include <cstring>#include <cmath>#include <sta