0.题目大意

给出一个序列,每次查询一个区间的最大子段和的端点和值。序列长度 \(n \le 10^{5}\) 。

1.思路

显然应该使用线段树。题目要求每次求一个区间的最大子段和,那么在线段树节点中应该维护这个节点的最大子段和。然而,只维护最大子段和是无法从子节点合并出父节点的。

考虑一个节点,它的最大子段和可能有以下几个来源:

  1. |_____________________________| <-节点
  2. |_________| <-最大子段和
  3. |_______________ |_____________| <-左右子节点
  1. |_____________________________| <-节点
  2. |_________| <-最大子段和
  3. |_______________ |_____________| <-左右子节点
  1. |_____________________________| <-节点
  2. |_________________| <-最大子段和
  3. |_______________ |_____________| <-左右子节点

情况1、2比较容易处理(直接照搬子节点的最大子段和),下面主要考虑情况3(最大子段和跨过中点)。

注意到可以把情况3拆分成这样:

  1. |_____________________________| <-节点
  2. |__________| |_____| <-最大子段和
  3. |______________| |_____________| <-左右子节点

即拆分成左子节点的后缀和右子节点的前缀,所以考虑维护每个节点的 最大前缀和最大后缀和 ,情况3就可以表示为左子节点的最大后缀和和右子节点的最大前缀和的并,然后就可以愉快地合并了。

解决了如何合并的问题,剩下的几乎就是模板了

2.坑点与吐槽

  1. 题目要求按照字典序输出,这莫名其妙地增加了许多难度
  2. 需要输出端点,这莫名其妙地增加了许多要维护的变量,又莫名其妙地增加了许多难度
  3. 综上所述,出题人是一个大毒瘤,建议枪毙

3.Code

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. #define MAXN 100000
  4. #define INF 0x3fffffff
  5. struct answ{
  6. int i,j,k;
  7. answ(){i=j=k=0;}
  8. answ(int _i,int _j,int _k){i=_i;j=_j;k=_k;}
  9. };
  10. struct segment_tree{
  11. int lp,rp;
  12. segment_tree *ls,*rs;
  13. int sum,max_qz_sum,max_qz_sum_rp,max_hz_sum,max_hz_sum_lp,max_sum,max_sum_lp,max_sum_rp;
  14. segment_tree(int a[],int l,int r){
  15. lp=l;
  16. rp=r;
  17. if(l==r){
  18. ls=rs=NULL;
  19. sum=max_qz_sum=max_hz_sum=max_sum=a[l];
  20. max_qz_sum_rp=max_hz_sum_lp=max_sum_lp=max_sum_rp=l;
  21. }else{
  22. int mid=(l+r)/2;
  23. ls=new segment_tree(a,l,mid);
  24. rs=new segment_tree(a,mid+1,r);
  25. sum=ls->sum+rs->sum;
  26. if(ls->max_qz_sum >= ls->sum+rs->max_qz_sum){//情况1
  27. max_qz_sum=ls->max_qz_sum;
  28. max_qz_sum_rp=ls->max_qz_sum_rp;
  29. }else{
  30. max_qz_sum=ls->sum+rs->max_qz_sum;
  31. max_qz_sum_rp=rs->max_qz_sum_rp;
  32. }
  33. if(rs->max_hz_sum >= rs->sum+ls->max_hz_sum){//情况2
  34. max_hz_sum=rs->max_hz_sum;
  35. max_hz_sum_lp=rs->max_hz_sum_lp;
  36. }else{
  37. max_hz_sum=rs->sum+ls->max_hz_sum;
  38. max_hz_sum_lp=ls->max_hz_sum_lp;
  39. }
  40. if(ls->max_sum >= rs->max_sum){//情况3
  41. max_sum=ls->max_sum;
  42. max_sum_lp=ls->max_sum_lp;
  43. max_sum_rp=ls->max_sum_rp;
  44. }else{
  45. max_sum=rs->max_sum;
  46. max_sum_lp=rs->max_sum_lp;
  47. max_sum_rp=rs->max_sum_rp;
  48. }
  49. if(max_sum<ls->max_hz_sum+rs->max_qz_sum){
  50. max_sum=ls->max_hz_sum+rs->max_qz_sum;
  51. max_sum_lp=ls->max_hz_sum_lp;
  52. max_sum_rp=rs->max_qz_sum_rp;
  53. }else if(max_sum==ls->max_hz_sum+rs->max_qz_sum){
  54. if(max_sum_lp>ls->max_hz_sum_lp){
  55. max_sum=ls->max_hz_sum+rs->max_qz_sum;
  56. max_sum_lp=ls->max_hz_sum_lp;
  57. max_sum_rp=rs->max_qz_sum_rp;
  58. }else if(max_sum_lp==ls->max_hz_sum_lp){
  59. if(max_sum_rp>rs->max_qz_sum_rp){
  60. max_sum=ls->max_hz_sum+rs->max_qz_sum;
  61. max_sum_lp=ls->max_hz_sum_lp;
  62. max_sum_rp=rs->max_qz_sum_rp;
  63. }
  64. }
  65. }//如您所见,由于愚蠢的“按字典序输出”存在,代码莫名其妙地增加了许多
  66. }
  67. }
  68. answ query_qz(int r){//查询最大前缀和
  69. if(r>=rp){
  70. return answ(0,max_qz_sum_rp,max_qz_sum);
  71. }else{
  72. answ res=ls->query_qz(r);
  73. if(r>=rs->lp){
  74. answ R=rs->query_qz(r);
  75. if(res.k<R.k+ls->sum){
  76. res=answ(0,R.j,R.k+ls->sum);
  77. }
  78. }
  79. return res;
  80. }
  81. }
  82. answ query_hz(int l){//查询最大后缀和
  83. if(l<=lp){
  84. return answ(max_hz_sum_lp,0,max_hz_sum);
  85. }else{
  86. answ res=rs->query_hz(l);
  87. if(l<=ls->rp){
  88. answ L=ls->query_hz(l);
  89. if(res.k<L.k+rs->sum){
  90. res=answ(L.i,0,L.k+rs->sum);
  91. }
  92. }
  93. return res;
  94. }
  95. }
  96. answ query(int l,int r){//查询最大字段和
  97. if(l<=lp&&rp<=r){
  98. return answ(max_sum_lp,max_sum_rp,max_sum);
  99. }else{
  100. answ res(0,0,-INF),L,R;
  101. if(l<=ls->rp){
  102. L=ls->query(l,r);
  103. if(L.k>res.k){
  104. res=L;
  105. }
  106. }
  107. if(r>=rs->lp){
  108. R=rs->query(l,r);
  109. if(R.k>res.k){
  110. res=R;
  111. }
  112. }
  113. if(l<=ls->rp&&r>=rs->lp){
  114. L=ls->query_hz(l);
  115. R=rs->query_qz(r);
  116. if(L.k+R.k>res.k){
  117. res=answ(L.i,R.j,L.k+R.k);
  118. }
  119. }
  120. return res;
  121. }
  122. }
  123. };
  124. int n,m,a[MAXN+5],sum[MAXN+5];
  125. int main(){
  126. ios::sync_with_stdio(false);
  127. cin>>n>>m;
  128. for(int i=1;i<=n;i++){
  129. cin>>a[i];
  130. sum[i]=sum[i-1]+a[i];
  131. }
  132. segment_tree data(a,1,n);
  133. for(int i=1;i<=m;i++){
  134. int l,r;
  135. cin>>l>>r;
  136. if(r-l+1>33){//在数据量较小时使用暴力可以提高效率
  137. answ ans=data.query(l,r);
  138. cout<<ans.i<<" "<<ans.j<<" "<<ans.k<<endl;
  139. }else{
  140. int ansl=0,ansr=0,ans=-INF;
  141. for(int j=l;j<=r;j++){
  142. for(int k=j;k<=r;k++){
  143. if(ans<sum[k]-sum[j-1]){
  144. ansl=j;
  145. ansr=k;
  146. ans=sum[k]-sum[j-1];
  147. }
  148. }
  149. }
  150. cout<<ansl<<" "<<ansr<<" "<<ans<<endl;
  151. }
  152. }
  153. return 0;
  154. }
4.点一个赞罢QwQ

[HZOI] 山海经 题解的更多相关文章

  1. COGS 2416.[HZOI 2016]公路修建 & COGS 2419.[HZOI 2016]公路修建2 题解

    大意: [HZOI 2016]公路修建 给定一个有n个点和m-1组边的无向连通图,其中每组边都包含一条一级边和一条二级边(连接的顶点相同),同一组边中的一级边权值一定大于等于二级边,另外给出一个数k( ...

  2. COGS 2188. [HZOI 2015] Math 题解

      题目描述: 给定n个数X1-Xn,求下面式子的值(整数部分): n<=107,xi<=109且互不相同. 分析: 其实一开始看见这道题我也吓傻了,k这么大,再说我又是数论鶸渣,打死也不 ...

  3. cogs 2320. [HZOI 2015]聪聪的世界题解

    2320. [HZOI 2015]聪聪的世界 时间限制:6 s   内存限制:512 MB [题目描述] 背景: 聪聪的性取向有问题. 题目描述: 聪聪遇到了一个难题: 给出一个序列a1…an,完成以 ...

  4. COGS 2421.[HZOI 2016]简单的Treap 题解

    题目大意: 给定n个数及其优先级,求对应的符合最小堆性质的Treap的先序遍历. n<=500000. 解法: 目前为止我只想到了三种解法,其中第三种是正解. 1.暴力1 以优先级为关键字排序, ...

  5. COGS 2387.[HZOI 2016]2387题解

    题目大意: 给定一个有n个元素的数组,有m个操作,分为两种,分别是询问第k个x的下标和把下标为x的数修改为k. 题目设置了强制在线,故无法预先得知所有操作数. 思路: 有三种思路. 第一种:平衡树 b ...

  6. 【COGS】2287:[HZOI 2015]疯狂的机器人 FFT+卡特兰数+排列组合

    [题意][COGS 2287][HZOI 2015]疯狂的机器人 [算法]FFT+卡特兰数+排列组合 [题解]先考虑一维的情况,支持+1和-1,前缀和不能为负数,就是卡特兰数的形式. 设C(n)表示第 ...

  7. [cogs2314][HZOI 2015] Persistable Editor - 可持久化平衡树

    [cogs2314][HZOI 2015]Persistable Editor - 可持久化平衡树 题目链接 首先吐槽扯淡几句 [题目描述] 维护一种可持久化的文本编辑器,支持下列操作: 1 p st ...

  8. [HZOI 2016]我们爱数数

    [HZOI 2016]我们爱数数 题目大意: 一张圆桌,每个位置按顺时针从\(1\)到\(n\)编号.有\(n\)个人,编号从\(1\)到\(n\).如果编号为\(i\)的人坐到了编号为\(i\)的位 ...

  9. CSP-S 模拟测试57题解

    人生第一次A,B层一块考rank2,虽然说分差没几分,但还是值得纪念. 题解: T1 天空龙: 大神题,因为我从不写快读也没有写考场注释的习惯,所以不会做,全hzoi就kx会做,kx真大神级人物. T ...

随机推荐

  1. 【LeetCode】7. Reverse Integer 整数反转

    作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 公众号:负雪明烛 本文关键词:整数,反转,题解,Leetcode, 力扣,Python, ...

  2. 【LeetCode】109. Convert Sorted List to Binary Search Tree 解题报告(Python)

    [LeetCode]109. Convert Sorted List to Binary Search Tree 解题报告(Python) 标签(空格分隔): LeetCode 作者: 负雪明烛 id ...

  3. Jenkins安装教程:Windows环境通过jenkins.war安装

    1.Windows操作系统下,安装jdk.tomcat.maven.git,并配置好对应的环境变量,安装教程请自行查询资料 2.将下载的jenkins.war放入到tomcat的webapp文件夹下, ...

  4. Electron 使用 Tray设置图标的路径问题

    问题报错信息如图 上面的代码在dev模式下不报错,但是在build后,安装后,运行会提示错误,错误信息的大意是参数错误,原因应该是安装后的图片文件路径有问题,这块没有详细研究解决上面的问题的方法,是使 ...

  5. element 表格只展开一行(点击下一行上一行关闭)

    源码:第一步 <el-table :data="tableData" border :row-class-name="tableRowClassName" ...

  6. 基于Java swing+mysql+eclipse的【图书管理系统】

    本项目为Java swing项目,在工作环境中基本使用不到,但是很多学校把这个当做编程入门的项目来做,故分享出本项目供初学者参考. CSDN赞助下载:https://download.csdn.net ...

  7. 集合不安全之 ArrayList及其三种解决方案【CopyOnWriteArrayList 、synchronizedList、Vector 】

    @ 目录 一.前言 二.为什么线程不安全 三.解决方案一CopyOnWriteArrayList (推荐,读多写少场景) 四.Collections.synchronizedList(加锁) 五.Ve ...

  8. DGHV同态库

    DGHV DGHV全同态方案的实现 这是具有压缩公钥的DGHV的全同态加密方案的实现,参考文章: [1] J.S. Coron, D. Naccache and M. Tibouchi, " ...

  9. frp + nginx 配置多人共用的http 内网穿透服务

    来源:简书   https://www.jianshu.com/p/c9d7527d607b 一. 前言 frp 是一个用Go语言开发的,可用于内网穿透的高性能的反向代理应用,支持 tcp, udp ...

  10. Java实现163邮箱发送邮件到QQ邮箱

    注:图片如果损坏,点击文章链接:https://www.toutiao.com/i6812973124141711876/ 先创建一个maven的普通项目 添加依赖,附在文档末尾 其中几个注意的地方 ...