Terrible Sets(单调栈,一开始还被题目描述吓到了,理解样例后发现就是纸老虎题。。。)

181 篇文章 0 订阅
173 篇文章 3 订阅

Link:http://poj.org/problem?id=2082


Terrible Sets
Time Limit: 1000MS Memory Limit: 30000K
Total Submissions: 3686 Accepted: 1923

Description

Let N be the set of all natural numbers {0 , 1 , 2 , . . . }, and R be the set of all real numbers. wi, hi for i = 1 . . . n are some elements in N, and w0 = 0. 
Define set B = {< x, y > | x, y ∈ R and there exists an index i > 0 such that 0 <= y <= hi ,∑ 0<=j<=i-1wj <= x <= ∑ 0<=j<=iwj} 
Again, define set S = {A| A = WH for some W , H ∈ R + and there exists x0, y0 in N such that the set T = { < x , y > | x, y ∈ R and x0 <= x <= x0 +W and y0 <= y <= y0 + H} is contained in set B}. 
Your mission now. What is Max(S)? 
Wow, it looks like a terrible problem. Problems that appear to be terrible are sometimes actually easy. 
But for this one, believe me, it's difficult.

Input

The input consists of several test cases. For each case, n is given in a single line, and then followed by n lines, each containing wi and hi separated by a single space. The last line of the input is an single integer -1, indicating the end of input. You may assume that 1 <= n <= 50000 and w 1h 1+w 2h 2+...+w nh n < 10 9.

Output

Simply output Max(S) in a single line for each case.

Sample Input

3
1 2
3 4
1 2
3
3 4
1 2
3 4
-1

Sample Output

12
14

Source


题意:直接讲样例给定意思就好了,万恶的出题人,简简单单的意思,把题目绕来绕去,说得如此复杂(ps:可能是自己的读题能力或对集合部分的内容表述不理解才会这样说,出题人不喜勿喷哦)。就是从左到右依次给你一个矩形的宽和高,问在这从左到右的矩形连成的图形中,能够找到的最大矩形面积是多少。


编程思想:类似我之前做过的一道题,这题不同之处只是给出的矩形的宽不是固定为1,其他一样。详细讲解见http://blog.csdn.net/enjoying_science/article/details/47904621


AC code:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <set>
#include <map>
#include <queue>
#define PI acos(-1.0)
#define LINF 1000000000000000000LL
#define eps 1e-8
#define LL long long
#define MAXN 1000010 
using namespace std;
const int INF=0x3f3f3f3f;
struct Rec{
	LL h;
	LL w;
	int id;
}r[MAXN];//r[i]表示以第i条柱状图能向左向右扩展的最大矩形 
Rec  st[MAXN];//单调递增栈 
LL ans;
int main()
{
	int i,j,n,hi,wi,top;
	while(scanf("%d",&n)!=EOF)
	{
		if(n==-1)
			break;
		top=0;//栈顶指针(栈的大小) 
		for(i=1;i<=n;i++)
		{
			scanf("%d%d",&wi,&hi);
			r[i].h=hi;
			r[i].w=wi;
			r[i].id=i;
			j=0;
			while(top!=0&&r[i].h<=st[top].h)//要入栈的元素不满足单调栈严格递增,删除栈中元素直到满足,
			{								//同时这些出栈的元素能向右扩展的宽度也确定下来了,可以直接更新 
				r[st[top].id].w+=j;//j表示能向右扩展的宽度 
				j=r[st[top].id].w;
				top--;//出栈 
			}
			r[i].w+=j;//更新当前矩形能向左扩展的宽度(因为是一直向右走,所以每次都能更新向左扩展的宽度) 
			st[++top]=r[i];//入栈 
		}
		j=0;
		while(top!=0)
		{
			r[st[top].id].w+=j;//j表示能向右扩展的宽度 
			j=r[st[top].id].w;
			top--;//出栈 
		}
		ans=-INF;
		for(i=1;i<=n;i++)
		{
			//printf("%lld %lld %lld\n",r[i].h,r[i].w,r[i].h*r[i].w);
			ans=max(ans,r[i].h*r[i].w);
		}
		printf("%lld\n",ans);
	}
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

林下的码路

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值