当前位置: 首页 > news >正文

单调栈与单调队列

单调栈与单调队列

单调栈

单调栈,顾名思义就是一种具备单调性质(内部元素满足单调性)的栈结构

现在来看一道例题:

向右看齐

\(n\) 个人从左到右站成一排,每个人都有一个身高,现要求所有人向右看齐,问每个人可以看到的最远的人是哪一个?(一个人右边第一个身高大于等于他的人会挡住这个人的视线 )。没有则输出 \(-1\)

数据范围:\(1\le n\le 10^6\)

简化题意:

给定含有 \(n\) 个数的连续序列 \(h\),对于每一个 \(i\) 找到一个最小的 \(j\in [i+1,n]\),使得 \(h[i]<h[j]\),若不存在则输出 \(-1\)

分析:

先考虑暴力,对于每一个位置 \(i\) 都向右寻找一个 \(j\),此时极限复杂度大约为 \(O(n^2)\)无法通过本题

为什么会超时呢?

假设序列 \(h = \{5,4,3,2,1\}\),从右到左计算,步骤如下:

  1. \(h_5\) 时直接得出答案 \(-1\)
  2. \(h_4\) 时查询 \(h_5\),得出答案 \(-1\)
  3. \(h_3\) 时查询 \(h_4,h_5\),得出答案 \(-1\)
  4. \(h_2\) 时查询 \(h_3,h_4,h_5\),得出答案 \(-1\)
  5. \(h_1\) 时查询 \(h_2,h_3,h_4,h_5\),得出答案 \(-1\)

可以发现每一个数都被查询了很多遍,这就是超时的原因

这时需要用一个栈来维护可能存在的解,维护步骤如下:

在从右到左扫描的过程中,若当前的值大于栈顶,则栈顶一定不优(永远也不会用到,因为有更优的解),出栈并放入新的解。

可以发现,这样维护的栈满足单调性,且栈顶元素是最大的。

时间复杂度见底部

代码:

代码使用STL栈,计算方式是从右至左

#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e6;
int n;
int a[maxn + 5];
stack<int> st;
int ans[maxn + 5];
int main() {scanf("%d",&n);for (int i = 1;i <= n;i ++) scanf("%d",&a[i]);for (int i = n;i >= 1;i --) {while (!st.empty() && a[st.top()] < a[i]) st.pop();ans[i] = st.empty() ? -1 : st.top();st.push(i);}for (int i = 1;i <= n;i ++) printf("%d\n",ans[i]);return 0;
}

单调队列

单调队列,本质上就是在单调栈的底部开一个口,用于排出非法解

经典例题:

滑动窗口

给定一个长度为 \(n\) 的数字序列 \(a\) 和一个正整数 \(k\),对于每一个 \(i\in[1,n-k+1]\) ,求区间 \([i,i+k-1]\) 的最大值与最小值

数据范围:\(1\le n \le 10^7\)

分析:

如果数据再小一点(\(n\le10^6\))就可以用ST表用通法解决。但显然,这道题并不是普通的区间最值查询,它固定了查询区间长度。也就是说在区间向右滑动时,一个元素有且可能被加入(删除)区间 \(1\) 次,这满足上面对单调栈”永远不会用到的元素“的分析。

与单调栈思路相同,只是增加了一个条件,若栈底(队头)元素的坐标小于给定区间的开头,出队

代码:

#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e7;
int n,k;
int a[maxn + 5];
deque<int> qmax,qmin;
int mx[maxn + 5],mn[maxn + 5];
int main() {scanf("%d %d",&n,&k);for (int i = 1;i <= n;i ++) scanf("%d",&a[i]);for (int i = n;i >= 1;i --) {while (!qmax.empty() && a[qmax.back()] < a[i]) qmax.pop_back(); // 删除不优解while (!qmax.empty() && qmax.front() > i + k - 1) qmax.pop_front(); // 排除在边界外的答案qmax.push_back(i);if (i <= n - k + 1) mx[i] = a[qmax.front()];while (!qmin.empty() && a[qmin.back()] > a[i]) qmin.pop_back();while (!qmin.empty() && qmin.front() > i + k - 1) qmin.pop_front();qmin.push_back(i);if (i <= n - k + 1) mn[i] = a[qmin.front()];}for (int i = 1;i <= n - k + 1;i ++) printf("%d ",mn[i]);printf("\n");for (int i = 1;i <= n - k + 1;i ++) printf("%d ",mx[i]);printf("\n");return 0;
}

时间复杂度

每个元素仅入栈出栈(出队入队) \(1\) 次,时间复杂度为\(O(n)\)

http://www.sczhlp.com/news/38202/

相关文章:

  • 网站如何做下一页seo网站排名优化案例
  • 西安专业网站建设公司排名steam交易链接怎么用
  • html5手机网站教程外包公司是什么意思
  • dw网站站点建立后怎么做北京推广服务
  • 个人怎么做公司网站销售培训课程一般有哪些
  • 网站打不开原因seo外包软件
  • 在wordpress主题后台安装了多说插件但网站上显示不出评论模块东莞搜索优化十年乐云seo
  • 回龙观做网站产品互联网营销推广
  • 媒易网络网站建设培训西安网站seo推广
  • 东营高端网站建设临汾网络推广
  • 网站草图设计关键词推广操作
  • 石家庄网站建设推广报价百度客服人工在线咨询
  • wordpress 主题设置中文优化seo设置
  • 公司门户网站制作需要多少钱seo门户网价格是多少钱
  • 成视频app下无限看ios7怎么关键词优化网站
  • 乔托运智能建站石家庄网络推广
  • 莆田网站建设方法新品推广策划方案
  • app大全免费软件下载安装温州seo优化公司
  • 网站开发价格表南宁网站优化
  • 临淄网站制作首选公司百度提交网站收录入口
  • 611 有效三角形个数
  • 2824 统计和小于目标的下标对数目
  • C++默认构造函数
  • 16 最接近的三数和
  • 如何在windows下,关闭release打包后,启动出现的黑框,以及保留debug模式的console
  • 网站后门清除企业产品推广策划方案
  • 新闻网页制作教程seo千享科技
  • 设计网站页面特效怎么做快速建网站
  • 怎么做才能发布网站免费发布广告
  • 0108_迪米特法则