文章目录

  • 单调栈 解题报告
    • PKU 2082 Terrible Sets
    • HDU 2430 Beans
    • HDU 4252 A Famous City
    • PKU 2796 Feel Good
    • HDU 3410 Passing the Message
    • HDU 6759 Leading Robots
    • HDU 5033 Building
    • HDU 4923 Room and Moor
    • PKU 3250 Bad Hair Day


单调栈 解题报告

PKU 2082 Terrible Sets

链接:PKU 2082 Terrible Sets
题意:把矩形在x轴上排列好以后就是求最大内接子矩形的问题了。

HDU 2430 Beans

链接:HDU 2430 Beans
题意:给定 n(n<=106)n(n <=10^6)n(n<=106) 个数字 a[i]a[i]a[i] 和两个数字 KKK 和 P(0<=P<K)P(0 <= P < K)P(0<=P<K),要求求一个区间 (i,j)(i,j)(i,j),使得区间和最大,并且区间里的数对 K 取模小于等于 P。求最大的 sum(i,j)/Ksum(i,j) / Ksum(i,j)/K。

  • 题解:前缀和 + 单调栈
  • 1)首先把所有的数求出前缀和以后对 KKK 取模。得到前缀和数组 sum[i]sum[i]sum[i] 代表前 iii 项的和(为了方便,下标从1开始)。
  • 2)令区间 (i,j)(i,j)(i,j) 的和模上 KKK 的值是:M(i,j)=(sum[j]−sum[i−1])modKM(i,j) = (sum[j] - sum[i-1])\mod KM(i,j)=(sum[j]−sum[i−1])modK 我们需要做的就是对于任意一个 jjj,要让 iii 的值尽量小(这样区间才能尽量长),并且 M(i,j)<=PM(i,j) <= PM(i,j)<=P。
  • 3)枚举 jjj,然后转化成线段树找区间最值问题。

HDU 4252 A Famous City

链接:HDU 4252 A Famous City
题意:给定一个直方图区域,问最少用多少的矩形能把这些区域填满。直方图的每个高度按照 h[i](1<=i<=n)h[i] (1 <= i <= n)h[i](1<=i<=n) 的形式给出。 一种解决方案如下:答案为 8 。

  • 题解:考虑如下三种情况:
  • 1)如果整个图是单调递增的,即h[i−1]<h[i]h[i-1] < h[i]h[i−1]<h[i],那么需要的矩形数就是不同高度的数目;
  • 2)如果中间有一次出现 h[i−1]>h[i]h[i-1] > h[i]h[i−1]>h[i],那么就要考虑 h[i]h[i]h[i] 能否和之前出现过的相同高度合并(如上图橙色方柱所示);
  • 3)如果 h[i−1]==h[i]h[i-1] == h[i]h[i−1]==h[i],那么 h[i]h[i]h[i] 没有任何作用;
  • 基于以上性质,用一个单调栈来维护一个单调递增序列,对 栈顶元素 toptoptop 和 当前元素 iii 进行高度判定如下:
  • 1)栈为空或者 h[top]<h[i]h[top] < h[i]h[top]<h[i],如果 h[i]>0h[i] > 0h[i]>0 则入栈;
  • 2)栈非空并且 h[top]==h[i]h[top] == h[i]h[top]==h[i],不作处理;
  • 3)栈非空并且 h[top]>h[i]h[top] > h[i]h[top]>h[i],不断弹出元素,并且计数器累加;当栈为空或者出现 h[top]<h[i]h[top] < h[i]h[top]<h[i],和 1)判定类似,h[i]>0h[i] > 0h[i]>0 则入栈;
  • [ 注意:为了让所有元素都能出栈,元素末尾加入一个 -1]

PKU 2796 Feel Good

链接:PKU 2796 Feel Good
题意:给定 nnn 个数 a[i](0<=a[i]<=106)a[i] (0 <= a[i] <= 10^6)a[i](0<=a[i]<=106),令 sum(i,j)=∑k=ija[k]sum(i,j) = \sum_{k=i}^j a[k]sum(i,j)=∑k=ij​a[k],求 sum(i,j)∗mina(i,j)sum(i,j)*min_a(i,j)sum(i,j)∗mina​(i,j) 的最大值。

  • 沿用 HDU 1506 Largest Rectangle in a Histogram 的思想,用单调栈维护一个单调不降序列,预处理前缀和。注意有 0 的情况,所以最先的候选最大值不能设定为 0,要定为小于零的数。

HDU 3410 Passing the Message

链接:HDU 3410 Passing the Message
题意:给定 nnn 个数 a[i](0<=a[i]<=105)a[i] (0 <= a[i] <= 10^5)a[i](0<=a[i]<=105),求每个数左边比它小最大的数,以及每个数右边比它小最大的数。

  • 题解:单调递减栈
  • 两边分别扫描,然后维护一个单调递减的栈即可;

HDU 6759 Leading Robots

链接:HDU 6759 Leading Robots
题意:给定 n(n<=50000)n( n <= 50000)n(n<=50000) 个人的起始位置 sss 和加速度 aaa,每个人都做匀加速运动,问有多少个人能在某个时刻成为 “领头羊” (即没有任何人能与之比肩)。

  • 需要考虑的几个思路:
  • 1)每个人的位移曲线是一条相对于 yyy 轴对称的抛物线,且只在第一象限;
  • 2)任意两条抛物线要么重合,要么只可能存在一个交点,换言之,如果起始位置一开始落后,那么超越的唯一机会就是加速度比起始位置大于他的人都大;
  • 3)起始位置相同的两个人,加速度小的那个永远没有机会成为 “领头羊”;
  • 4)起始位置相同,加速度也相同的两个人都没有机会成为 “领头羊”;
  • 对于两个人 RiR_iRi​ 和 RjR_jRj​,满足 (si>sj且ai<aj)(s_i > s_j 且 a_i < a_j)(si​>sj​且ai​<aj​),则 aja_jaj​ 追上 aia_iai​ 的时间为:t>=2(si−sj)aj−ait >= \sqrt {\frac {2(s_i - s_j)}{a_j - a_i}}t>=aj​−ai​2(si​−sj​)​​
  • 考虑三个人,R1=(s1,a1),R2=(s2,a2),R3=(s3,a3)R_1 = (s_1, a_1),R_2 = (s_2, a_2),R_3 = (s_3, a_3)R1​=(s1​,a1​),R2​=(s2​,a2​),R3​=(s3​,a3​),并且满足(s1>s2>s3)(s_1 > s_2 > s_3)(s1​>s2​>s3​),R2R_2R2​ 想要追上来的必要条件是 (a2>a1)(a_2 > a_1)(a2​>a1​),R3R_3R3​ 想要追上来的条件是 (a3>max(a1,a2))(a_3 > max(a_1,a_2))(a3​>max(a1​,a2​))。但是这样还不够,试想一下,如果 R3R_3R3​ 追上 R2R_2R2​ 的时间早于 R2R_2R2​ 追上 R1R_1R1​ 的时间,那么 R2R_2R2​ 就再也没有机会成为第一了。
  • 那么,我们对于一个位置递减,加速度递增的序列,我们需要维护一个 “追上时间” 单调递增的序列;
  • 算法设计如下:
  • 1)首先对数据进行排序,按照起始位置作为第一关键字递减,位置相同则加速度递减;
  • 2)对位置相同,加速度小元素直接去掉;对两个关键字都相同的元素进行哈希标记,不作为 “领头羊” 候选人;
  • 3)对数据进行从前往后的扫描,记录当前加速度最大值为 MaxaMax_aMaxa​,对于所有扫描到的加速度小于等于 MaxaMax_aMaxa​ 的进行跳过处理,每次扫描完毕更新加速度最大值:
  • 3.a)如果栈中小于两个元素,则入栈当前元素;
  • 3.b)否则计算栈顶两个元素的 “追上时间” ttopt_{top}ttop​,以及栈顶元素和当前元素的 “追上时间” tcurt_{cur}tcur​,如果 ttop>=tcurt_{top} >= t_{cur}ttop​>=tcur​,则弹出栈顶元素, 计算完毕将当前元素入栈;
  • 扫描完毕后,将所有栈顶元素出栈,并且没有被 哈希标记 的人就是能够在某个时刻成为 “领头羊” 的人;
  • [ 注意:计算时间的时候 开方 + 除法 会引起精度误差,比较的时候可以转换成乘法来操作]

HDU 5033 Building

链接:HDU 5033 Building
题意:给定 n(n<=105)n(n <= 10^5)n(n<=105) 个建筑的 x[i]x[i]x[i] 坐标和高度 h[i]h[i]h[i],然后 Q(Q<=105)Q(Q <= 10^5)Q(Q<=105) 次询问,问在某个位置 ppp 需要多少的仰角才能看到天空;

  • 题解:离线算法 + 单调栈的斜率优化
  • 对于任何一个 ppp 都要考虑左右两边的情况,但是左右两边的情况处理起来是一样的,所以这里只考虑左边;然后进行逆序以后再算一次,再把两个和 x 轴的角度相加,用 180度 去减就行。那么有以下几个注意点:
  • 1)对于某个 ppp 位置,位于它左边的建筑,随着 xxx 递增,hhh 一定是单调递减的,不然肯定不会成为阻碍视角的最高仰角的那个建筑。
  • 2)一旦出现三个高度单调递减的建筑,它们的形状组成一个下凹的形状,那么中间的那个建筑,一定是不可能成为阻碍视角的建筑,所以可以认为中间的建筑不存在(可以随便找个的坐标轴上的点往中间的建筑做连线,一定是交在第一个建筑或者第三个建筑上);
  • 3)于是对于建筑序列,我们只需要维护一个相邻建筑逐渐变陡峭的序列(表现在数值上就是斜率逐渐往负的方向越来越大),可以用单调栈来维护这个序列;
  • 4)对于任意一个位置 ppp,现在要找到那个影响它视野的建筑,可以检查栈中的建筑,令栈顶两个建筑组成的斜率为 KtopK_{top}Ktop​,栈顶建筑和 ppp 位置组成的斜率为 KpK_pKp​,如果 Ktop<=KpK_{top} <= K_pKtop​<=Kp​(注意斜率恒为负) ,则出栈,继续判断;否则,即找到了那个阻碍它视野的建筑;

HDU 4923 Room and Moor

链接:HDU 4923 Room and Moor
题意:给定 n(n<=100000)n(n <= 100000)n(n<=100000) 个元素的序列 A,只由 0 和 1 组成,求一个非递减序列 B,满足如下条件:

  • 题意:单调栈
  • 首先把所有数分段拆成如下这样的段:111000, 11100, 110, 1111110,即都是有 1 开头, 0结尾,那么对于某一段,假设 1 的个数为 aaa,0 的个数为 bbb,令选择的的 Bi=xB_i = xBi​=x,则有差的平方和为:a(x−1)2+bx2a(x-1)^2 + bx^2a(x−1)2+bx2 利用抛物线的极值可以知道,当 x=aa+bx = \frac {a} {a + b}x=a+ba​ 时取得最小值。
  • 如果这样求出来的 BiB_iBi​ 都能够单调不降,那么问题的解也就出来了;
  • 当出现 Bi>Bi+1B_i > B_{i+1}Bi​>Bi+1​ 的时候,我们可以选择将 BiB_iBi​ 和 Bi+1B_{i+1}Bi+1​ 进行合并,用单调递增的栈来维护这个序列,知道栈中的元素都是单调递增位置。

PKU 3250 Bad Hair Day

链接:PKU 3250 Bad Hair Day
题意:n(n<=105)n(n <= 10^5)n(n<=105) 个人从左往右顺序排列,给定他们的高度 h[i]h[i]h[i],,第 iii 个人往右看能够看到比他高度低的人的个数记为 s[i]s[i]s[i],求 ∑i=1ns[i]\sum_{i=1}^{n} s[i]∑i=1n​s[i]。

  • 我们考虑下图的两种情况:
  • 1)如下图所示,当前的人编号为 ccc,aaa 和 bbb 呈逆序排列,那么 aaa 和 bbb 的解都是 ccc;
  • 2)如下图所示,当前的人编号为 ccc,aaa 和 bbb 呈顺序排列(或者 a 和 b 高度相等),那么只有 bbb 的解是 ccc;在这个问题中我们发现, 当求bbb 的解时,aaa 的解已经求出来了,不再需要;
  • 把 aaa 和 bbb 理解成栈中的元素,我们首先在序列末尾插入一个无限大的数,然后维护一个单调递减的栈,从左往右枚举每个人的高度 h[i]h[i]h[i],然后取 栈顶元素高度 和 当前高度 比较,如果 栈顶元素高度 <= 当前高度,代表栈顶的那个人能够看到的最远的人就是当前第 iii 个人,则累加答案,并且出栈,迭代循环处理,直到 栈顶元素高度 > 当前高度 或者 栈空,再将 iii 入栈;
  • 如图,红色方柱为 h[i]h[i]h[i],绿色方柱均为本次处理要出栈的元素,蓝色方柱为处理完还在栈中的元素,栈中元素始终保持单调递减。

解题报告 (十) 单调栈相关推荐

  1. 解题报告 (十四) 数位DP

    文章目录 数位DP 解题报告 HDU 4722 Good Numbers HDU 2089 不要62 HDU 3555 Bomb HDU 3652 B-number PKU 3252 Round Nu ...

  2. 解题报告 (十五) 扩展欧拉定理

  3. *【HDU - 1506】【POJ - 2559】Largest Rectangle in a Histogram(单调栈或动态规划)

    题干: Description A histogram is a polygon composed of a sequence of rectangles aligned at a common ba ...

  4. P2947-[USACO09MAR]向右看齐Look Up【单调栈】

    正题 评测记录:https://www.luogu.org/recordnew/lists?uid=52918&pid=P2947 题目大意 有n头牛,高度不同,求每头牛右边第一头比他高的人. ...

  5. LeetCode 1124. 表现良好的最长时间段(单调栈/哈希)

    文章目录 1. 题目 2. 解题 2.1 单调栈 2.2 哈希 1. 题目 给你一份工作时间表 hours,上面记录着某一位员工每天的工作小时数. 我们认为当员工一天中的工作小时数大于 8 小时的时候 ...

  6. 剑指Offer30-包含min函数的栈(单调栈)

    问题描述 定义栈的数据结构,请在该类型中实现一个能够得到栈的最小元素的 min 函数在该栈中,调用 min.push 及 pop 的时间复杂度都是 O(1). 示例: MinStack minStac ...

  7. 7月算法训练------第十四天(栈)解题报告

    7月算法训练------第十四天(栈)解题报告 题目类型:栈 题目难度:简单 第一题.1614. 括号的最大嵌套深度 题目链接:1614. 括号的最大嵌套深度 思路分析: 遍历整个字符串,如果是'(' ...

  8. POJ 3250 解题报告 Bad Hair Day (单调栈)

    传送门:http://poj.org/problem?id=3250 这题--水题啊,单调栈可解. 上一波C艹实现 #include <iostream> #include <cst ...

  9. HDU 1506 解题报告 Largest Rectangle in a Histogram (单调栈)

    看题传送门:http://acm.hdu.edu.cn/showproblem.php?pid=1506 题意比较明显,就是找以某一个矩形为高的最大的矩形.这个题可以用单调栈来求解,需要注意的是如果从 ...

最新文章

  1. 请不要将抛出异常作为业务逻辑使用!!!
  2. 动态添加方法 并且动态的执行 有类方法 对象方法
  3. dubbo Trace 日志追踪
  4. 如何分割合并ISO文件
  5. angelajs中ajax,Fabric.js Triangle angle属性用法及代码示例
  6. 多种云资源管理用什么软件好?你知道吗?
  7. HTTP代理原理探索
  8. html调用矢量小图标的方法,Web 前端矢量小图标的使用方法
  9. 上传文件到云服务器一般用什么软件?
  10. Linux下点阵汉字的字模读取与显示
  11. Lesson 5英语句子成分
  12. Ceisum 计算向量夹角及垂足
  13. C# 博思得 POSTEK 打印机 打码机 SDK 二次开发 指令打印
  14. 【前端大屏可视化项目适配方案】
  15. 高考失利后选择出国留学,一年至少20万人民币到底值不值?
  16. 智能优化算法之灰狼优化算法(GWO)的实现(Python附源码)
  17. handsontable的核心方法
  18. 开源爬虫神器,Playwright vs Puppeteer 对比,你应该选择哪个?
  19. (一)图像文字检测论文:CTPN方法
  20. windows 7系统安装

热门文章

  1. 5G 流量单价两年降 46% 热议背后,5G 如何解锁商业新模式?
  2. Python近期练习小案例
  3. windows 安装汽车之家falcon插件 采集数据
  4. 全国信息化和软件服务业工作座谈会召开
  5. Jenkins使用时间插件Date Parameter
  6. OpenStack物理资源虚拟化比率设置
  7. 五分钟you-get入门
  8. 分数拆分(简单数学)
  9. woo 10到任意进制,任意数值到十进制 之间转换
  10. [Kaggle Classify-Leaves] 树叶分类 score0.950