当前位置:网站首页>单调栈及其应用
单调栈及其应用
2022-08-03 19:30:00 【*大祺】
目录
1.糟糕的一天(洛谷P2866, USACO 2006 月赛)
一、极简概念
单调栈是一种内部元素具有单调性的栈,可以解决“以某个值为最值的最大区间”等问题。
能以O(n)的时间复杂度找到每一个元素右边或左边第一个比它大或小的数。(超级好用艾~ 不然可能就得用(毒瘤的)二分+RMQ惹QAQ)
来看几道题就会用了
二、几个栗子
1.糟糕的一天(洛谷P2866, USACO 2006 月赛)

转变思路:与其求一头牛能看见几头牛, 不如反过来 ,计算一头牛能被几头牛看见,因为它们的总和是相等的。一只牛能被哪些牛看到呢?左边比它高的牛,再左边更高的牛……只需要维护一个数组,满足这个数组里面存的都是对于第 i 头牛来说,身高一次递增的牛的身高(这个数组是单调递减的)。可以使用栈来进行维护。
假设有6头牛,高度分别为 10,3,7,4,12,2,那么它们分别可以看到 3,0 ,1,0,1,0头牛的头发,其总和为5;栈的实现:最开始栈是空的,原来栈里没有牛,那么答案增加0;身高为3的牛来了,从栈顶开始,把所有身高小于等于3的牛都出栈(这里暂时没有这样的牛),然后自己入栈,自己左边有一头牛,答案增加1;身高为7的牛来了,从栈顶开始,把所有小于等于7的牛都出栈(3就出栈),然后自己入栈,自己左边有一头牛,答案增加1……以此类推。
#include<iostream>
#include<stack>
using namespace std;
long long ans;
stack<int> s;
int main(){
ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
int n;cin>>n;
for(int i=1,x;i<=n;i++){
cin>>x;
while(!s.empty()&&s.top()<=x)s.pop();
ans+=s.size();
s.push(x);
}
cout<<ans;
return 0;
}2.天气变化

#include<iostream>
#include<stack>
using namespace std;
const int M=1e6+6;
int n,a[M];
struct nt{
int v,id;
}p[M];
stack<nt> s;
int main(){
ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
int n;cin>>n;
for(int i=1;i<=n;i++)cin>>p[i].v,p[i].id=i;
a[n]=0;
s.push(p[n]);
for(int i=n-1;i;i--){
while(!s.empty()&&s.top().v<=p[i].v)s.pop();
if(!s.empty())a[i]=s.top().id-i;
else a[i]=0;
s.push(p[i]);
}
for(int i=1;i<=n;i++)cout<<a[i]<<' ';
return 0;
}3.长方形(洛谷P1950)
P1950 长方形 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
题目描述
小明今天突发奇想,想从一张用过的纸中剪出一个长方形。
为了简化问题,小明做出如下规定:
(1)这张纸的长宽分别为 $n,m$。小明讲这张纸看成是由$n\times m$个格子组成,在剪的时候,只能沿着格子的边缘剪。
(2)这张纸有些地方小明以前在上面画过,剪出来的长方形不能含有以前画过的地方。
(3)剪出来的长方形的大小没有限制。
小明看着这张纸,想了好多种剪的方法,可是到底有几种呢?小明数不过来,你能帮帮他吗?
输入格式
第一行两个正整数 n,m,表示这张纸的长度和宽度。
接下来有 n 行,每行 m$个字符,每个字符为 `*` 或者 `.`。
字符 `*` 表示以前在这个格子上画过,字符 `.` 表示以前在这个格子上没画过。
输出格式
仅一个整数,表示方案数。
样例 1
样例输入 1
6 4
....
.***
.*..
.***
...*
.***
样例输出 1
38



书上咋又是数组模拟栈。。看着晕qwq。为啥不直接用stack啊
#include<iostream>
#include<stack>
using namespace std;
const int M=1e3+6;
int n,m,l[M],r[M];
struct nt{
int h,id;
}p[M];
stack<nt> s;
long long ans;
int main(){
ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
cin>>n>>m;
char x;
for(int i=1;i<=m;i++)p[i].id=i;
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
cin>>x;
p[j].h=(x=='*'?0:p[j].h+1);
}
while(!s.empty())s.pop();
for(int j=1;j<=m;j++){
while(!s.empty()&&s.top().h>p[j].h)s.pop();
if(!s.empty())l[j]=s.top().id;
else l[j]=0;
s.push(p[j]);
}
while(!s.empty())s.pop();
for(int j=m;j;j--){
while(!s.empty()&&s.top().h>=p[j].h)s.pop();
if(!s.empty())r[j]=s.top().id;
else r[j]=m+1;
s.push(p[j]);
}
for(int j=1;j<=m;j++)
ans+=(j-l[j])*(r[j]-j)*p[j].h;
}
cout<<ans;
return 0;
}emmmm记得清空栈那里别落了感叹号(非空啊)QAQ晚上捣鼓半天没发现www感谢pbrjjOrzzz
边栏推荐
- 国产虚拟化云宏CNware WinStack安装体验-5 开启集群HA
- Unity gets the actual coordinates of the ui on the screen under the canvas
- 不要再用if-else
- MySQL超详细安装教程 手把手教你安装MySQL到使用MySQL 最简单的MySQL安装方式,这种方式装,卸载也简单
- 要想成为黑客,离不开这十大基础知识
- Radondb mysql installation problems
- Reveal how the five operational management level of hundreds of millions of easily flow system
- 力扣刷题之求两数之和
- mysql跨库关联查询(dblink)
- Postgresql source code (65) analysis of the working principle of the new snapshot system Globalvis
猜你喜欢
随机推荐
Line the last time the JVM FullGC make didn't sleep all night, collapse
MySQL超详细安装教程 手把手教你安装MySQL到使用MySQL 最简单的MySQL安装方式,这种方式装,卸载也简单
Handler source code analysis
ECCV 2022 Oral | 满分论文!视频实例分割新SOTA: IDOL
OneNote 教程,如何在 OneNote 中设置页面格式?
阿洛的反思
盘点在线帮助中心对企业能够起到的作用
CC2530_ZigBee+华为云IOT:设计一套属于自己的冷链采集系统
阿里巴巴政委体系-第六章、阿里政委体系运作
APT级全面免杀与企业纵深防御体系的红蓝对抗
Handler 源码解析
Interview Blitz: What Are Sticky Packs and Half Packs?How to deal with it?
MYSQL误删数据恢复
net-snmp私有mib动态加载到snmpd
【C语言学习笔记(六)】分支与跳转(if、else、continue、break、switch)
高效目标检测:动态候选较大程度提升检测精度(附论文下载)
Postgresql源码(65)新快照体系Globalvis工作原理分析
Postgresql-xl全局快照与GTM代码走读(支线)
「游戏建模干货」建模大师几步操作,学习经典,赶紧脑补一下吧
MySQL master-slave, 6 minutes you master!









