地址:http://acm.hdu.edu.cn/showproblem.php?pid=1506
题意:给一些连续的直方柱的高(宽是1),找一个面积最大的矩形。
mark:本来是个单调队列题,但是dp好像可以解。考虑每个柱往两边找能扩展到的最远的边界,乘上自己的高可获得。
往两边扩展边界的时候理论复杂度是O(n),直接做是要TLE的。先考虑往右找边界,假设之前右边所有的直方柱的边界已经被找过,并且被记录下来,假如下一个柱的高度比自己高,则直接可以跳到下一个柱的边界继续找,不断迭代后很快就能找到边界。
不知道这种迭代的方法复杂度如何证明,对于每个柱子,最坏的肯定是要找n次(递减),但是最坏的情况不可能出现在每个柱子上。勉强可以搞。
代码注意long long,另外之前实现的时候想错了,还以为只往一边找,反过来再执行一次就可以了,但是过不了类似3 9 8 9这样的数据。
代码:
# include <stdio.h>
int left[100010], right[100010] ;
int num[100010] ;
typedef long long ll ;
int main()
{
int buff, i, n ;
long long ans ;
while (~scanf ("%d", &n), n)
{
for(i = 0 ; i < n ; i++)
scanf ("%d", &num[i]) ;
for (i = 0 ; buff =i, i < n ; i++)
{
while (buff != 0 && (num[buff-1]>= num[i]))
buff = left[buff-1] ;
left[i] = buff ;
}
for (i = n-1 ; buff = i, i >= 0 ; i--)
{
while ((buff != n-1) && (num[buff+1] >= num[i]))
buff = right[buff+1] ;
right[i] = buff ;
}
ans = 0 ;
for (i = 0 ; i <n ; i++) if (((ll)num[i]) * (right[i]-left[i]+1) > ans)
ans = ((ll)num[i]) * (right[i]-left[i]+1) ;
printf ("%I64d\n", ans) ;
}
return 0 ;
}