背景
2019年8月17日上午,yzy开启了懒人出题模式,办起了一场全是原题的 欢乐赛。
而看似稳如老狗的我,在考场上是慌的一批,乱搞满分之后更加感觉我思路的清(混)奇(乱),意图将思路整合梳理,故有此文。
T1:积木大赛
传送门
来自NOIp2013/2018提高组以及USACO13MAR_Poker Hands。(这三道题居然一毛一样)
虽说我在很久之前做过原题,但是在考场上我还是经过了一番思(乱)考(搞)。
对于题目要求的形状,我先考虑一种脑残情况:
根据明显的贪心原则,正常人一定会选择最大的宽度堆积木,这样可以使得总次数最小,为高度h(相当容易证明)。
考场上的我仔细分析了一波这种情况,发现其过于脑残以至于没有任何有价值的信息,我开始陷入绝望。
如果情况并不是这么简单呢?像这样
根据贪心原则,可以看出最小操作数依然为h,只不过选择的最大宽度会改变而已。
从这种情况里,还可以得到一个有用的信息:在矩形高度递增的情况下,最小操作数就是最高矩形的高度。
如果利用这种具有单调性的思想,将题目里的目标条件强制转化为一个单调递增(指高度)的矩形序列,那么就可以轻而易举地得到答案。
当时面如死灰的我已经无法思考别的情况,只想用这种性质骗分。
那么如何将一般化的情形转化为单调情形呢,我YY了类似单调栈的思想。
从左到右依次扫描题目给的每个矩形,并且假定当前的矩形序列是单调的。
如果当前遇到的矩形高度大于等于上一个的话,什么也不用做,因为此时矩形序列满足单调性。
当遇到一个矩形,其高度比上一个小,那么把这个矩形抬起来,使其和上一个矩形一样高,来维护这个序列。
就像这样:
根据题意,进行“抬高矩形”的操作的操作步数显然是(上一个矩形的高度-当前矩形的高度)。
当扫描完成之后,我们自然得到了当前序列的最小操作步数,但是不要忘了累计上用来维护矩形序列花费的步数。
所以我的核心代码是这样子的:
long long int height, cur_height, n, ans = 0;
cin >> n