首页 > 代码库 > 每日一dp(1)——Largest Rectangle in a Histogram(poj 2559)使用单调队列优化

每日一dp(1)——Largest Rectangle in a Histogram(poj 2559)使用单调队列优化

Largest Rectangle in a Histogram

题目大意:

有数个宽为1,长不定的连续方格,求构成的矩形中最大面积


/************************************************************************/
/* 

思路1.
当前为n的面积如何与n-1相联系,dp[i][j]=max(dp[i-1][k]) , 0<k<=j
描述:i为方块个数,j为高度
但是此题目的数据对于高度太变态,h,1000000000 ,n,100000
所以不可行(一般计算机为Ghz 相当于1S十几亿运算)

思路2.
此题目寻找的最大面积,对于一个方块来说则是以自己为中心左右两端比自己高
的方块累计和与自己面积的乘积,取最大值。状态转移则可看作已知前面n-1个左边比自己
高的的位置l[i],则如果该下标对应的数据比自己还高,继续往下找。利用了n-1的l[i]中
数值

优化:
使用单调队列
1. 即每次插入都从后往前找,找到不小于自己的,插入并抛弃该位置后面的数据
2. 每次都从队头取元素,并及时淘汰过期数据
此队列具有单调性,最大的永远在队头,对于没用的数据及时删除,过期数据也及时更新

对应到此题目:
q中存放的则是1.2.3.....i-1 的位置,更新的是比[i-1]大的元素,即比[i-1]大的元素都
被更新
                                                                     
*/
/************************************************************************/
#include <iostream>
using namespace std;
const int maxn=5+100000;
int a[maxn];
int q[maxn],l[maxn],r[maxn];
int N,tail,front;
__int64 ans,tmp;
int main()
{
    int i;
	while(scanf("%d",&N),N)
	{
		for(i=1;i<=N;i++)
			scanf("%d",a+i);
		tail=1;front=0;q[1]=1;
		for(i=2;i<=N;i++)
		{
			while( front<tail && a[q[tail]]>a[i] )
				r[q[tail]]=i-1,tail--;
			q[++tail]=i;
		}
		while(front<tail)
			r[q[tail]]=N,tail--;

		tail=1;q[1]=N;
		for(i=N-1;i;i--)
		{
			while( front<tail && a[q[tail]]>a[i] )
				l[q[tail]]=i+1,tail--;
			q[++tail]=i;
		}
		while(front<tail)
			l[q[tail]]=1,tail--;
		ans=0;
		for(i=1;i<=N;i++)
		{
			tmp=r[i]-l[i]+1;
			tmp*=a[i];
			ans=ans>tmp?ans:tmp;
		}
		printf("%I64d\n",ans);



	}
    return 0;
}