首页 > 其他分享 >hdu 1506(dp || 单调栈)

hdu 1506(dp || 单调栈)

时间:2023-05-29 22:38:31浏览次数:48  
标签:__ hdu int int64 hi 1506 ans maxn dp


题意:这题是要找最大的矩形面积。


解题思路:这题的关键是要找每个条形能够往左和往右能够到达的最大长度。我最开始的思路是单调栈去维护,只要入栈的元素比栈顶元素小,栈顶就要出栈,并且知道其最右能够到达的最远距离。当要入栈的元素已经找到了位置,那么它左边的元素所在的位置就是其能到达的最左距离。

这道题比较坑,要用__int64位,而且在当栈为空时,加入的新元素的最左是能够到达1的,这里我开始没发现,结果WA到死。。。

这里还有一个dp版本的,感觉实际上和单调栈差不多,都是找最左和最右的距离。



#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;

const int maxn = 100005;
struct Node
{
	__int64 h;
	int id;
}Stack[maxn];
struct Keep
{
	__int64 l,r,h;
}res[maxn];
__int64 n,top,hi[maxn];

int main()
{
	while(scanf("%I64d",&n)!=EOF && n)
	{
		for(__int64 i = 1; i <= n; i++)
		{
			scanf("%I64d",&hi[i]);
			res[i].l = res[i].r = i;
			res[i].h = hi[i];
		}
		top = 0;
		for(__int64 i = 1; i <= n; i++)
		{
			while(top > 0 && hi[i] <= Stack[top-1].h)
			{
				res[Stack[top-1].id].r = i - 1;
				top--;
			}
			Stack[top].id = i;
			Stack[top].h = hi[i];
			if(top != 0)
				res[i].l = Stack[top-1].id + 1;
			else res[i].l = 1;	//最容易丢掉的条件,一直WA的原因
			top++;
		}
		while(top > 0)
		{
			res[Stack[top-1].id].r = n;
			top--;
		}
		__int64 ans = 0;
		for(int i = 1; i <= n; i++)
		{
			__int64 area = (res[i].r - res[i].l + 1) * res[i].h;
			if(area > ans)
				ans = area;
		}
		printf("%I64d\n",ans);
	}
	return 0;
}






#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;

const int maxn = 100005;
int n,l[maxn],r[maxn];
__int64 hi[maxn];

int main()
{
	while(scanf("%d",&n)!=EOF && n)
	{
		for(int i = 1; i <= n; i++)
			scanf("%I64d",&hi[i]);
		l[1] = 1; r[n] = n;
		int t;
		for(int i = 2; i <= n; i++)	//更新每个l[i]
		{
			t = i;
			while(t > 1 && hi[t-1] >= hi[i]) t = l[t-1];
			l[i] = t;
		}
		for(int i = n - 1; i >= 1; i--) //更新每个r[i]
		{
			t = i;
			while(t < n && hi[t+1] >= hi[i]) t = r[t+1];
			r[i] = t;
		}
		__int64 ans = 0, tmp = 0;
		for(int i = 1; i <= n; i++)
		{
			tmp = (r[i] - l[i] + 1) * hi[i];
			if(tmp > ans)
				ans = tmp;
		}
		printf("%I64d\n",ans);
	}
	return 0;
}




标签:__,hdu,int,int64,hi,1506,ans,maxn,dp
From: https://blog.51cto.com/u_16143128/6374299

相关文章

  • hdu 1516(编辑距离+记录路径)
    最开始把问题搞错了,以为是两个串都可以做修改,无论我怎么想都不通。回到这个题目上,这道题和最长公共子序列很相似,思路可以说是一样的,包括记录路径。其实也就是根据递推数组的结果来判断。#include<iostream>#include<cstdio>#include<cstring>usingnamespacestd;constintma......
  • hdu 2473(并查集+删除操作)
    解题思路:这道题有并查集的删除操作,如果直接对这一棵树进行删除节点操作肯定是很困难的。所以可以建立虚拟节点,只要有一个节点要被删除,就直接把它投影到虚拟节点上,即用这个虚拟节点来代替我们要删除的节点。这样我们就不需要用对已有的树形结构进行改动了。这个想法我在DragonBalls......
  • hdu 3635(并查集+路径压缩变形)
    解题思路:这道题想了我好久,因为我把城市的编号一起考虑进去了,结果想了好久都没A,最后看了别人的题解居然都没有考虑到城市的编号,不考虑城市编号的问题的话就是一个很水的并查集了。#include<iostream>#include<cstdio>#include<cstring>usingnamespacestd;constintMAXN=1000......
  • hdu 2874(LCA + 节点间距离)
    解题思路:Tarjan离线处理一篇介绍LCA的很好的博客:http://www.cppblog.com/menjitianya/archive/2015/12/10/212447.html#include<iostream>#include<cstdio>#include<cstring>usingnamespacestd;constintmaxn=10005;structEdge{ intk,next,cost;}edge[maxn&......
  • hdu 4027(线段树)
    题意:给定100000个数,两种操作,0ij表示将ij这段的数字都开根号(向下取整),1ij表示查询ij之间的所有值的和。。。(所有的和都不超过64位)解题思路:这题要做区间的开平方操作,2^64最多可以做8次开平方操作,所以对于每个节点最多只有8次操作,这道题如果lazy思想的话就要保存每个区间被开平方......
  • hdu 3564(线段树+LIS)
    题意:给出1~n的插入顺序,要求每次插入之后的LIS解题思路:这道题确实挺难想的,我最开始想用树状数组每插入一个数就更新一次,如果这么想,那么你就输了。它这里的想法是先将1-n的最终位置都保存起来,然后再一个个去找LIS。这里有点离线算法的意思,至少了解到更新时可以先别急着处理。还有这里......
  • hdu 3874(树状数组+离线算法)
    解题思路:这道题和之前的题一样,查找[l,r]区间内不重复数字的和。可以利用离线算法,实际上离线算法为了解决在查找时出现的矛盾,因为每次询问的区间大小不同,如果单独处理的话可能会对之后的查询有影响,所以离线算法帮助我们把要查询的区间先按照右端点进行排序,因为在处理更靠右的区间时,......
  • hdu 4101(bfs+博弈)
    题意:题目的意思就是说两个人轮流玩游戏,给你一张地图,这个地图中间有一点-1代表宝藏,AliandBaba轮流走路,如果某一个人能够直接走到宝藏的话,那么他就赢了。地图上其它的点0代表空地,数字代表当前地点的石子当某一人拿石子的时候,他只能拿走一颗。问你谁最后能拿到宝藏;解题思路:宝藏位于-......
  • hdu 1510
    WhiteRectanglesTimeLimit:2000/1000MS(Java/Others)    MemoryLimit:65536/32768K(Java/Others)ProblemDescriptionYouaregivenachessboardmadeupofNsquaresbyNsquareswithequalsize.Someofthesquaresarecoloredblack,andthe......
  • hdu 2821
    题意:n*m的格子上有一些方块放在某些格子上,一个格子可能有几个方块,用'a'-'z'来表示方块数量。初始的时候可以选择任意空地作为Pusher初始点,Pusher选择一个方向,然后向这个方向前进直到遇到有方块的格子,Pusher把这个格子的方块清除一个,并把它向前推一格(向前不能出界),如果前面一格有方......