解题报告 (十) 单调栈
文章目录
- 单调栈 解题报告
- 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=ija[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−ai2(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=1ns[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],绿色方柱均为本次处理要出栈的元素,蓝色方柱为处理完还在栈中的元素,栈中元素始终保持单调递减。
解题报告 (十) 单调栈相关推荐
- 解题报告 (十四) 数位DP
文章目录 数位DP 解题报告 HDU 4722 Good Numbers HDU 2089 不要62 HDU 3555 Bomb HDU 3652 B-number PKU 3252 Round Nu ...
- 解题报告 (十五) 扩展欧拉定理
- *【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 ...
- P2947-[USACO09MAR]向右看齐Look Up【单调栈】
正题 评测记录:https://www.luogu.org/recordnew/lists?uid=52918&pid=P2947 题目大意 有n头牛,高度不同,求每头牛右边第一头比他高的人. ...
- LeetCode 1124. 表现良好的最长时间段(单调栈/哈希)
文章目录 1. 题目 2. 解题 2.1 单调栈 2.2 哈希 1. 题目 给你一份工作时间表 hours,上面记录着某一位员工每天的工作小时数. 我们认为当员工一天中的工作小时数大于 8 小时的时候 ...
- 剑指Offer30-包含min函数的栈(单调栈)
问题描述 定义栈的数据结构,请在该类型中实现一个能够得到栈的最小元素的 min 函数在该栈中,调用 min.push 及 pop 的时间复杂度都是 O(1). 示例: MinStack minStac ...
- 7月算法训练------第十四天(栈)解题报告
7月算法训练------第十四天(栈)解题报告 题目类型:栈 题目难度:简单 第一题.1614. 括号的最大嵌套深度 题目链接:1614. 括号的最大嵌套深度 思路分析: 遍历整个字符串,如果是'(' ...
- POJ 3250 解题报告 Bad Hair Day (单调栈)
传送门:http://poj.org/problem?id=3250 这题--水题啊,单调栈可解. 上一波C艹实现 #include <iostream> #include <cst ...
- HDU 1506 解题报告 Largest Rectangle in a Histogram (单调栈)
看题传送门:http://acm.hdu.edu.cn/showproblem.php?pid=1506 题意比较明显,就是找以某一个矩形为高的最大的矩形.这个题可以用单调栈来求解,需要注意的是如果从 ...
最新文章
- 请不要将抛出异常作为业务逻辑使用!!!
- 动态添加方法 并且动态的执行 有类方法 对象方法
- dubbo Trace 日志追踪
- 如何分割合并ISO文件
- angelajs中ajax,Fabric.js Triangle angle属性用法及代码示例
- 多种云资源管理用什么软件好?你知道吗?
- HTTP代理原理探索
- html调用矢量小图标的方法,Web 前端矢量小图标的使用方法
- 上传文件到云服务器一般用什么软件?
- Linux下点阵汉字的字模读取与显示
- Lesson 5英语句子成分
- Ceisum 计算向量夹角及垂足
- C# 博思得 POSTEK 打印机 打码机 SDK 二次开发 指令打印
- 【前端大屏可视化项目适配方案】
- 高考失利后选择出国留学,一年至少20万人民币到底值不值?
- 智能优化算法之灰狼优化算法(GWO)的实现(Python附源码)
- handsontable的核心方法
- 开源爬虫神器,Playwright vs Puppeteer 对比,你应该选择哪个?
- (一)图像文字检测论文:CTPN方法
- windows 7系统安装