51nod 1102 面积最大的矩形 && 新疆大学OJ 1387: B.HUAWEI's billboard 【单调栈】+【拼凑段】(o(n) 或 o(nlog(n))
题面1:

题面2:

两道题除了数据范围不同,没有任何差异,两道题都可以o(n)(单调栈),o(nlog(n))(我自己的做法)解决。
解题思路1:(单调栈)
- 对于每个点找到右边第一个比它小的位置con1,并且找到左边第一个比它小的位置con2。
- 对于每个点更新答案为ans = max(ans, (con2-con1-1)*value[i])。
- 1的做法是两次裸的单调栈,时间复杂度为o(n)。
代码1:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
//在新疆大学OJ提交需要将此处三个数组改为500010,否则会运行超时
ll a[50010];
int l[50010],r[50010];
int main(){
ios::sync_with_stdio(false);
int n;
cin >> n;
ll ans = 0;
for(int i = 1;i <= n; ++i){
cin >> a[i];
}
a[0] = a[n+1] = -1;
stack<int> s;
s.push(1);
for(int i = 2;i <= n+1; ++i){
while(s.size() and a[i] < a[s.top()]){
r[s.top()] = i;
s.pop();
}
s.push(i);
}
while(s.size()) s.pop();
s.push(n);
for(int i = n-1;i >= 0; --i){
while(s.size() and a[i] < a[s.top()]){
l[s.top()] = i;
s.pop();
}
s.push(i);
}
for(int i = 1;i <= n; ++i){
ans = max(ans, (a[i]*(r[i]-l[i]-1)));
}
cout << ans << endl;
return 0;
}
解题思路2:(拼凑段)
这是我自己瞎搞的写法,不知道算什么方法,不过大家可以看一看思路,可能什么时候就能用到了。
首先,记下输入的数字的位置,然后对这个结构体按数字从打到小排序。
遍历这个结构体数组(这时数字是从大到下的),段(一个结构体,有l,r,used三个成员变量,l指这个段的左端位置,r指这个段的右端位置)
a. 若这个数字的原位置的左右边两个数字都已形成段,则将这两段拼成一段,具体做法是将左边段的r延长至右端,当前数字为这一段的最小值,更新ans。
b. 若这个数字的原位置的左边形成段,右边没有形成段,则把这个数字加入到左边的段,当前数字为这一段的最小值,更新ans。
c. 若这个数字的原位置的右边形成段,左边没有形成段,则把这个数字加入到右边的段,当前位置为这一段的最小值,更新ans。
d. 若这个数字的原位置的左边和右边都没有形成段,则把这个数字加入到一个新的段,新的段的l和r都等于这个数字的原先位置,更新ans。可能会想到查找左边位置所处的段和右边所处的段需要o(n)处理起来会变成o(n^2),这时候我们加一个索引数组index,index[i]表示位置为i的数字所处的段。
可能还会想到更新index需要花费o(n),处理起来会变成o(n^2),但是仔细想想我们会发现不需要更新这个段所有的index,只用更新index[l]和index[r],因为中间的在后面将不会用到。
这样算下来排序的时间复杂度是o(nlogn),处理的时间是o(n),总时间复杂度就是o(nlogn)。
可能还有人问为什么正确?排序之后先插入大的,后插入小的,会发现当前插入的这个点一定是这个点的最优情况。
代码2:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
//在新疆大学OJ提交需要将此处的50010全部改为500010
//输入的数组,val为这个点的数字,idx表示原下标。
struct node{
ll val;
int idx;
}a[50010];
//段,l表示左端,r表示右端 ,k表示段的个数。
struct segment{
int l;int r;
}seg[50010];
int k = 1;
//index[i]表示第i个位置数字所处的段。
int index[50010];
int n;
bool cmp(node x,node y){
return x.val > y.val;
}
int main(){
ios::sync_with_stdio(false);
int n;
cin >> n;
ll ans = 0;
for(int i = 1;i <= n; ++i){
cin >> a[i].val;
a[i].idx = i;
ans = max(ans , a[i].val);
}
sort(a+1, a+1+n, cmp);
for(int i = 1;i <= n; ++i){
int idxl = index[a[i].idx-1];
int idxr = index[a[i].idx+1];
if(idxl != 0 and idxr != 0){ //左右边都形成一段。
seg[idxl].r = seg[idxr].r;
index[seg[idxr].r] = idxl;
ans = max(ans, a[i].val*(seg[idxl].r-seg[idxl].l+1));
}else if(idxl != 0 and idxr == 0){ //左边形成段,右边未形成。
seg[idxl].r++;
index[a[i].idx] = idxl;
ans = max(ans, a[i].val*(seg[idxl].r-seg[idxl].l+1));
}else if(idxl == 0 and idxr != 0){ //右边形成段,左边未形成。
seg[idxr].l--;
index[a[i].idx] = idxr;
ans = max(ans, a[i].val*(seg[idxr].r-seg[idxr].l+1));
}else if(idxl == 0 and idxr == 0){ //左右边均未形成段。
seg[k].l = a[i].idx;
seg[k].r = a[i].idx;
index[a[i].idx] = k;
k++;
}
}
cout << ans << endl;
return 0;
}
51nod 1102 面积最大的矩形 && 新疆大学OJ 1387: B.HUAWEI's billboard 【单调栈】+【拼凑段】(o(n) 或 o(nlog(n))的更多相关文章
- 51nod 1102 面积最大的矩形 (单调栈)
链接:https://www.51nod.com/onlineJudge/questionCode.html#!problemId=1102 思路: 首先介绍下单调栈的功能:利用单调栈,可以找到从左/ ...
- 51nod 1102 面积最大的矩形(单调栈)
http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1102 题意: 思路: 做法就是求出每个长方形向左向右所能延伸的最大距离. ...
- 51nod 1102 面积最大的矩形
题目地址在这儿 求取:以某矩形g[i]为最小值的区间的左右端点,得到一个临时解.所有临时解中的最大值即为解. 求取区间的方法可以用单调栈,也可以用下面这种十分简洁的类似于递归的方法.下面这种解法求出来 ...
- SUST OJ 1675: Fehead的项目(单调栈)
1675: Fehead的项目 时间限制: 1 Sec 内存限制: 128 MB提交: 41 解决: 27[提交][状态][讨论版] 题目描述 Fehead俱乐部接手了一个项目,为了统计数据,他们 ...
- 51nod 1158 全是1的最大子矩阵(单调栈 ,o(n*m))
前置问题:51nod 1102 面积最大的矩形 附上链接: 51nod 1102 面积最大的矩形 这题的题解博客 需要了解的知识:单调栈,在前置问题中已经讲解. 解题思路 对每行求左边连续1的个数,得 ...
- 51nod 1102 单调栈
http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1102 1102 面积最大的矩形 基准时间限制:1 秒 空间限制:1310 ...
- hdu1506 直方图中最大的矩形 单调栈入门
hdu1506 直方图中最大的矩形 单调栈入门 直方图是由在公共基线对齐的矩形序列组成的多边形.矩形具有相同的宽度,但可能具有不同的高度.例如,左侧的数字显示了由高度为2,1,4,5,1,3,3的矩形 ...
- LeetCode 84 | 单调栈解决最大矩形问题
本文始发于个人公众号:TechFlow,原创不易,求个关注 今天是LeetCode专题第52篇文章,我们一起来看LeetCode第84题,Largest Rectangle in Histogram( ...
- XJOI 3606 最大子矩形面积/LightOJ 1083 Histogram(单调栈/笛卡尔树)
A histogram is a polygon composed of a sequence of rectangles aligned at a common base line. The rec ...
随机推荐
- struts2学习之基础笔记7
第十二章 Struts 2的标记库 1 OGNL简介 Object-Grephic Navigtor Language 图对象导航语言 作用:图对象导航语言是Struts 2标记库中为其相应标记属性进 ...
- js判断传入时间和当前时间大小
//判断时间是否过期 function judgeTime(time){ var strtime = time.replace("/-/g", "/");//时 ...
- 五分钟DBA:浅谈伪分布式数据库架构
[IT168 技术]12月25日消息,2010互联网行业技术研讨峰会今日在上海华东理工大学召开.本次峰会以“互联网行业应用最佳实践”为主题,定位于互联网架构设计.应用开发.应用运维管理,同时,峰会邀请 ...
- JAVA-mysql读写分离插件介绍
kingshard是一个由Go开发高性能MySQL Proxy项目,kingshard在满足基本的读写分离的功能上,致力于简化MySQL分库分表操作:能够让DBA通过kingshard轻松平滑地实现M ...
- oracle数据库 sqlplus
- Unity 三维软件单位导入资源单位比例
三维软件 内部米制尺寸/m 默认设置导入unity中的尺寸/m 与unity单位比例 Maya 1 100 1:100 3DS MAX 1 0.01 100:1 Cinema 4D 1 100 1:1 ...
- 速学JavaScript!
什么是JavaScript? JavaScript是一种轻量级的脚本语言,也是一种嵌入式语言,是一种对象模型语言,简称JS:JavaScript的核心语法部分(语言本身)很精简,只包括两个部分: 基本 ...
- Vue文件封装日历组件
封装就是要具有灵活性,样式自适应,调用的时候传入props就可以变成自己想要的样式. 效果展示网址:https://1963331542.github.io/ 源代码: <template> ...
- elastic学习笔记
要点 不同工具之间版本匹配很重要由点及面,先实践起来再学细节的原理和使用 技术栈 laravel5.5框架+scout组件+elasticsearch6.3.0搜索引擎 辅助 elasticsearc ...
- 常用js方法封装
常用js方法封装 var myJs = { /* * 格式化日期 * @param dt 日期对象 * @returns {string} 返回值是格式化的字符串日期 */ getDates: fun ...