【问题描述】

现在有n个宽度为1的矩形按如下图(左边的)所示的方式排在了一起:

用肉眼容易看出,在左图内部面积最大的矩形如右图绿色部分所标注。

现在我们考虑将其中一些宽度为1的矩形取出,按照原顺序再次紧密地靠在一起,比如在原图中,如果我们取出从左往右数的第2、4、5、6个矩形,那么我们得到下面的左图,而该图形内部的最大矩形则如右图黄色部分所示。

现在,你的任务就是从原图中取出若干个宽度为1的矩形并使用上面的方式组成新的图形,使得新的图形中,内部的最大矩形面积最大。

【输入格式】

第一行为一个正整数T,表示数据组数。 接下来T组数据,每组数据第一行为一个正整数n,表示矩形个数,接下来一行n个正整数,第i个数hi表示图形中从左到右第i个矩形的高度。

【输出格式】

对每组数据输出一行一个正整数,表示最大的“最大矩形”面积。

【输入样例】
3
4
1 2 3 4
3
8 1 9
3
8 6 9
【输出样例】
6
16
18
【数据规模与约定】

对于30%的数据,有1<=n<=15,

对于60%的数据,有1<=n<=1000,

对于100%的数据,有1<=T<=10, 1<=n,hi<=100000,每个测试点n的和不超过200000。

题目分析

这是一个裸的单调栈,我转载了别人的代码如下。设第一个比当前数(序号为i)小的左侧数为left[i]。算法的流程是这样的:设现在程序循环到第i个数,如果当前,栈顶的数大于等于第i个数,说明什么?说明序号i以后的数j,它们的left[j]一定不会是栈顶那个数,因为选了j一定能选i。既然这样,直接把j从栈中弹出,然后继续判断……直至第i个数遇到比它小的栈顶的数。这个数就是left[i],因为比i小的数只会被更小更优的数替换。然后,将i入栈。这样就把那些无用的,值大于第i个数,却在第i个数左边的数统统用第i个数替换了。这就去除了冗余状态。

代码实现

#include<bits/stdc++.h>
using namespace std;
#define N 100001
#define int long long
int s[N],a[N],w[N],T,n,top,ans;
signed main(){
freopen("rectangle.in","r",stdin),freopen("rectangle.out","w",stdout);
cin>>T;
while (T--){
cin>>n;
for (register int i=;i<=n;++i) cin>>a[i];
sort(a+,a+n+);
a[n+]=top=ans=;
for (register int i=;i<=n+;++i)
if (s[top]<a[i]&&top)
s[++top]=a[i],w[top]=;
else{int wide=;
while(s[top]>=a[i]&&top){
wide+=w[top];
ans=max(ans,wide*s[top--]);
}s[++top]=a[i],w[top]=wide+;
}cout<<ans<<"\n";
}
return ;
}

代码分析

原来的HDU1506也是很水,这一题也是,唯一的区别在于排序了。我将会认真的讲解一下单调栈问题。

我们要维护的栈是一个单调递增的数列,为什么呢?我们的答案最好是用较高的答案加上去的,所以用递增数列。我们的答案矩阵是长乘宽,我们维护一个队列,当前的数字比栈顶还大,自然是递增的,入栈即可。如果小于等于,我们保存的是栈中比这个数字小(等于)的数字,当然这时候我们把宽度加一下啊。。。因为这时候我们维护的矩形可能是最大的,自然要记录了。我们一边出栈一边更新答案,虽然有可能不会更新掉答案。这里贼骚:原来的宽度是不是被pop掉了?我们再把宽度加回去哈。居然有这种操作,原因是原来的部分被算过一遍了,我们如果有更新ans就更新过了,我们可以把这个部分当做一个小矩形加入栈里面。如果最后还有答案怎么办啊?我们用一个高度为0的矩形入栈,然后你懂得。

当然如果你要压行,我不介意。本来要讲一讲我和小姐姐的故事,下次再说。

【FZSZ2017暑假提高组Day1】最大矩形的更多相关文章

  1. 【FZSZ2017暑假提高组Day1】华容道游戏

    [问题描述] 华容道是一种有趣的滑块游戏,大概是下面这个样子的. 游戏局面由一个2*2的曹操滑块,五个2*1的蜀将滑块(横竖是不定的).四个1*1的小兵滑块以及两个空的位置构成,玩家需要利用空的位子移 ...

  2. 【FZSZ2017暑假提高组Day1】确定小组

    [问题描述] 有n个人坐成一排,这n个人都在某一个小组中,同一个小组的所有人所坐的位置一定是连续的. 有一个记者在现场进行采访,他每次采访都会询问一个人其所在的小组有多少人,被询问的每个人都给出了正确 ...

  3. 【FZSZ2017暑假提高组Day2】圆盘时钟

    [问题描述] 作为出题人的小Z相信大家对上图这样的圆盘时钟都不会陌生——在理想圆盘时钟上,秒针每一分钟转一圈,分针每一小时转一圈,时针每12小时转一圈,它们均是匀速转动的,在0点时三条针均指向表盘上的 ...

  4. luogu1003铺地毯[noip2011 提高组 Day1 T1]

    题目描述 为了准备一个独特的颁奖典礼,组织者在会场的一片矩形区域(可看做是平面直角坐标系的第一象限)铺上一些矩形地毯.一共有 n 张地毯,编号从 1 到n .现在将这些地毯按照编号从小到大的顺序平行于 ...

  5. Noip2011 提高组 Day1 T1 铺地毯 + Day2 T1 计算系数

    Day1 T1 题目描述 为了准备一个独特的颁奖典礼,组织者在会场的一片矩形区域(可看做是平面直角坐标系的第一象限)铺上一些矩形地毯.一共有 n 张地毯,编号从 1 到n .现在将这些地毯按照编号从小 ...

  6. 18/9/9牛客网提高组Day1

    牛客网提高组Day1 T1 中位数 这好像是主席树??听说过,不会啊... 最后只打了个暴力,可能是n2logn? 只过了前30%  qwq #include<algorithm> #in ...

  7. Noip2011 提高组 Day1 T3 Mayan游戏

    题目描述 Mayan puzzle是最近流行起来的一个游戏.游戏界面是一个 7 行5 列的棋盘,上面堆放着一些方块,方块不能悬空堆放,即方块必须放在最下面一行,或者放在其他方块之上.游戏通关是指在规定 ...

  8. GZOJ 1361. 国王游戏【NOIP2012提高组DAY1】

    国王游戏[NOIP2012提高组DAY1] Time Limit:1000MS Memory Limit:128000K Description 国王游戏(game.cpp/c/pas) [问题描述] ...

  9. 暑假提高组集训Day1 T1

    说实话,今天的题真的有点难! ~备受打击~ 我们先来看一看第一题吧 看起来好像不太简单,其实并不难 下面来提供两种方法吧 1.做法一 //签到题 /* 那么这一题就是告诉你n个点的坐标,把它们分别放到 ...

随机推荐

  1. linux系统转换root权限

    有时候我们用普通用户的权限没办法完成有关权限,这时候我们就需要拿到root权限才可以,拿到root权限有两种方式 方式一: su - 或者su 此时就会提示你输入密码,输入密码成功以后就能以root权 ...

  2. Python 实现简易 Shell

    什么是shell? (1)shell是一个系统软件,负责用户和操作系统内核之间的交互,是产生进程的进程(通过linux系统调用fork,exec),主要负责解释用户的命令,进而实现用户对进程的控制. ...

  3. requests模块的使用

    requests模块 什么是request模块:requests是python原生一个基于网络请求的模块,模拟浏览器发起请求. requests-get请求 # get请求 import reques ...

  4. Windows CMD 支持ls命令

    /********************************************************************** * Windows CMD 支持ls命令 * 说明: * ...

  5. mount: mounting proc on /proc failed: Device or resource busy

    /********************************************************************** * mount: mounting proc on /p ...

  6. Dubbo的Filter实战--整合Oval校验框架

    前言: 其实很早之前就想写一篇关于oval和具体服务相整合的常见做法, 并以此作为一篇笔记. 趁现在项目中间空闲期, 刚好对dubbo的filter有一些了解. 因此想结合两者, 写一下既结合校验框架 ...

  7. Linux系统-禁ping

    1) Add the following line to your /etc/sysctl.conf net.ipv4.icmp_echo_ignore_all=1 Then : sysctl -p ...

  8. nodeJS网络操作

    var http = require('http'); http.createServer(function (request, response) { response.writeHead(200, ...

  9. C++调用ffmpeg.exe提取视频帧

    有时候,我们获得一段视频,需要将其中的每一帧都提取出来,来进行一些相关的处理,这时候我们就可以需要用到ffmpeg.exe来进行视频帧的提取. ffmpeg简介:FFmpeg是一套可以用来记录.转换数 ...

  10. MySQL Error--The Table is full

    问题描述 在MySQL 错误日志中发下以下错误信息:[ERROR] /export/servers/mysql/bin/mysqld: The table '#sql-xxxx-xxx' is ful ...