题解 P5019 【铺设道路】
这题目就我一个人模拟吗?
普及蒟蒻,不会好算法,就来说一发模拟吧
首先一个贪心:
每次选一个连续正深度的坑的区间去填
为什么呢?因为只有这样,才能保证我每次填坑的数量最多,不会造成浪费(即可以一天解决的问题我2天解决),也就是保证填的天数最少
于是得到了$ O(n^2* sum(a[1…n])) $,嗯,超时成什么样我就不说了
于是优化:
观察下面的表:
d[1] | d[2] | d[3] | d[4] | d[5] | d[6] | d[7] |
---|---|---|---|---|---|---|
1 | 4 | 3 | 3 | 4 | 3 | 3 |
0 | 3 | 2 | 2 | 3 | 2 | 2 |
0 | 2 | 1 | 1 | 2 | 1 | 1 |
0 | 1 | 0 | 0 | 1 | 0 | 1 |
0 | 0 | 0 | 0 | 0 | 0 | 0 |
可以发现,第2行与第3行实际上是重复的
在本例中,只重了2行;
如果重个10000,100000行呢?
那么你的程序就会T。
如何优化?
不难发现,我们填坑的过程是有规律的;
于是就有了优化:
每次循环必然要彻底填掉至少1个坑
那么,实现就很简单了:
在找连续整数的时候,顺便查找最小值,然后区间减最小值,完成目标。
到此为止,你已经拿到80分了
还有两个点什么情况?
因为,尽管我们优化了,整个复杂度还是$ O(n^{2}) $,是会T的
再优化!
我们可以发现,当我们找区间的开始的时候,其实是有单调性的
即:我下一次填坑的起始点一定在本次填坑的范围中
那么在模拟减的时候就可以顺便找下一次的开始了。
你也许发现了一个问题:
一遍坑全部填平了怎么办?
没事,设定一个极值,最后判一下,如果没变的话就从本次的结束点往后找啦~
于是复杂度降到了$ O(n+\text{常数}) $,就AC了
代码:
1 |
|