单调栈和单调队列

单调栈:

用于解决求出距离当前值最近的满足某个性质的值

 1 给定一个长度为N的整数数列,输出每个数左边第一个比它小的数,如果不存在则输出-1。
 2
 3 输入格式
 4 第一行包含整数N,表示数列长度。
 5
 6 第二行包含N个整数,表示整数数列。
 7
 8 输出格式
 9 共一行,包含N个整数,其中第i个数表示第i个数的左边第一个比它小的数,如果不存在则输出-1。
10
11 数据范围
12 1≤N≤105
13 1≤数列中元素≤109
14 输入样例:
15 5
16 3 4 2 7 5
17 输出样例:
18 -1 3 -1 2 2
19
20
21 ########################
22
23 #include <iostream>
24
25 using namespace std;
26
27 const int N = 1e5+10;
28
29 int arr[N];
30 int stk[N], top = -1;
31
32 int main(){
33     int n;
34     cin >> n;
35     for(int i = 0;i < n;++i){
36         cin >> arr[i];
37     }
38     for(int i = 0;i < n;++i){
39         //stack存下标和值都可以
40         while(top >= 0 && stk[top] >= arr[i])--top;
41         if(top >= 0)printf("%d ",stk[top]);
42         else printf("-1 ");
43         stk[++top] = arr[i];
44     }
45     return 0;
46 }

单调队列:

用于解决当前窗口中的最值也可以说是满足条件的唯一解

 1 给定一个大小为n≤106的数组。
 2
 3 有一个大小为k的滑动窗口,它从数组的最左边移动到最右边。
 4
 5 您只能在窗口中看到k个数字。
 6
 7 每次滑动窗口向右移动一个位置。
 8
 9 以下是一个例子:
10
11 该数组为[1 3 -1 -3 5 3 6 7],k为3。
12
13 窗口位置    最小值    最大值
14 [1 3 -1] -3 5 3 6 7    -1    3
15 1 [3 -1 -3] 5 3 6 7    -3    3
16 1 3 [-1 -3 5] 3 6 7    -3    5
17 1 3 -1 [-3 5 3] 6 7    -3    5
18 1 3 -1 -3 [5 3 6] 7    3    6
19 1 3 -1 -3 5 [3 6 7]    3    7
20 您的任务是确定滑动窗口位于每个位置时,窗口中的最大值和最小值。
21
22 输入格式
23 输入包含两行。
24
25 第一行包含两个整数n和k,分别代表数组长度和滑动窗口的长度。
26
27 第二行有n个整数,代表数组的具体数值。
28
29 同行数据之间用空格隔开。
30
31 输出格式
32 输出包含两个。
33
34 第一行输出,从左至右,每个位置滑动窗口中的最小值。
35
36 第二行输出,从左至右,每个位置滑动窗口中的最大值。
37
38 输入样例:
39 8 3
40 1 3 -1 -3 5 3 6 7
41 输出样例:
42 -1 -3 -3 -3 3 3
43 3 3 5 5 6 7
44
45 ##########################
46
47 #include <iostream>
48
49 using namespace std;
50
51 const int N = 1e6+10;
52
53 int arr[N];
54 int q[N];
55 int head = 0, tail = -1;
56
57 int main(){
58     int n, k;
59     cin >> n >> k;
60     for(int i = 0;i < n;++i) cin >> arr[i];
61     for(int i = 0;i < n;++i){
62         while(head <= tail && i - q[head] + 1 > k)++head;
63         while(head <= tail && arr[i] <= arr[q[tail]])--tail;
64         q[++tail] = i;
65         if(i >= k-1)printf("%d ",arr[q[head]]);
66     }
67     cout << endl;
68     head = 0, tail = -1;
69     for(int i = 0;i < n;++i){
70         while(head <= tail && i - q[head] + 1 > k)++head;
71         while(head <= tail && arr[i] >= arr[q[tail]])--tail;
72         q[++tail] = i;
73         if(i >= k-1)printf("%d ",arr[q[head]]);
74     }
75     return 0;
76 }

end

原文地址:https://www.cnblogs.com/sxq-study/p/12083093.html

时间: 2024-07-31 04:30:04

单调栈和单调队列的相关文章

单调栈与单调队列

单调栈 特点 栈内的元素单调递增或者单调递减,可以在\(O(n)\)的时间内求出数列中所有数的左边或右边第一个比其大或小的元素,总时间复杂度为\(O(n)\) 例子 单调栈中一般存索引 一个单调递增栈s = [0, 10, 20 ,t]代表栈中a[1]~a[9]的元素大于a[10]的元素,索引为a[11]~a[19]的元素大于a[20]的元素... 这样我们可以发现在a[10]左边第一个比a[10]的数为a[0],在a[20]左边第一个比a[20]的数为a[10]... 如何实现呢? 每次有元素

单调栈以及单调队列

单调栈: 定义: 栈内的元素,按照某种方式排列下(单调递增或者单调递减),如果新入栈的元素破坏了单调性,就弹出栈内元素,直至满足单调性. 作用:单调栈可以找到从左/右遍历第一个比它大/小的元素的位置.时间复杂度为O(N): 实现方式:(以维护单调递增栈为例) 进栈操作:每次进入栈时,先检验栈顶元素和进栈元素的大小,如果小于,那么直接入栈:否则,大于等于进栈元素的出栈,直到栈空或者栈顶元素小于入栈元素. 例如:3 8 2 3 1 初始时刻栈为空,3入栈.......................

POJ 2559 Largest Rectangle in a Histogram(单调栈) &amp;&amp; 单调栈

嗯... 题目链接:http://poj.org/problem?id=2559 一.单调栈: 1.性质: 单调栈是一种特殊的栈,特殊之处在于栈内的元素都保持一个单调性,可能为单调递增,也可能为单调递减. 2.模样: 这是一个单调递增的栈,如果我们插入的元素大于栈顶元素,则直接入栈: 如果我们插入的元素小于栈顶,则需要把栈内所有大于它的元素暂时出栈,将这个元素入栈后,再将暂时出栈的元素入栈,维护单调性. 二.模板: 这道题是单调栈的一道模板题: 先思考一个问题,如果题目中的矩形的高度都是单调递增

小结:单调栈 &amp; 单调队列

概要: 对于维护信息具有单调性的性质或者问题可以转化为具有单调性质的模型的题,我们可以考虑用单调栈或单调队列. 技巧及注意: 技巧很多,只要能将问题转化为单调性问题,就好解决了. 当维护固定长度的单调区间,我们考虑用单调队列,如[BZOJ]3314: [Usaco2013 Nov]Crowded Cows(单调队列) 单调栈维护长度时要进行及时更新,例如:[BZOJ]3039: 玉蟾宫(DP/单调栈) 假设完美状态后再进行减法原理,例如:[BZOJ]1628 && 1683: [Usaco

单调栈&amp;单调队列入门

单调队列是什么呢?可以直接从问题开始来展开. Poj 2823 给定一个数列,从左至右输出每个长度为m的数列段内的最小数和最大数. 数列长度:\(N <=10^6 ,m<=N\) 解法① 很直观的一种解法,那就是从数列的开头,将窗放上去,然后找到这最开始的k个数的最大值,然后窗最后移一个单元,继续找到k个数中的最大值. 这种方法每求一个f(i),都要进行k-1次的比较,复杂度为$ O(Nk) $. 显然,如果暴力时间复杂度为 $ O(Nm) $ 不超时就怪了. 解法② 还有一种想法是维护一个B

单调队列&amp;单调栈归纳

单调队列 求长度为M的区间内的最大(小)值 单调队列的基本操作,也就是经典的滑动窗口问题. 求长度为M的区间内最大值和最小值的最大差值 两个单调队列,求出长度为M的区间最大最小值的数组,分别求最大最小值. 求边长为a的正方形内最大值和最小值的最大差值([HAOI2007]理想的正方形) 一个大体的思路是先分别求出以i,j为左上端点的边长为a的矩形中的最大值和最小值.那么该怎么做?,先用单调队列求出一个点右边a个单位的最大值,形成一个新矩阵,再求出新矩阵下边a个单位的最大值.然后最小值再求一边,最

单调队列 单调栈

建议不了解STL的读者先了解几个基本的队列的STL.这也是单调队列和单调栈一般都会用到的. 单调队列:建立一个队列,使队列一直具有单调性(满足单调递增或者单调递减),时间复杂度O(N). 那么我们应该如何做到"使队列一直具有单调性"呢? 以单调递增为例,我们O(N)扫描整个序列,每扫描到一个元素: 1 如果该元素大于等于队列末尾元素,则直接入队; 2 而如果该元素小于已有队列的末尾元素,即不满足单调递增,则使队列中的末尾元素出队,直到该元素符合入队条件,然后入队. 如果只到这里,那么我

7.14 单调栈 单调队列 +dp优化

单调栈和单调队列的定义具体看ppt了 模板: 单调队列 head =1; tail = 0; rep( i ,1 ,n ){ while( head <= tail && a[i] < dq[tail].first)tail--; while( head <= tail && dq[head].second < i-k+1) head++; dq[ ++tail ]={a[i] ,i}; 例题:https://vjudge.net/contest/3

单调栈&amp;单调队列

最近打了三场比赛疯狂碰到单调栈和单调队列的题目,第一,二两场每场各一个单调栈,第三场就碰到单调队列了.于是乎就查各种博客,找单调栈,单调队列的模板题去做,搞着搞着发现其实这两个其实是一回事,只不过利用了容器内元素单调的不同特性,用来加速处理不同的问题. 单调栈解决的是以某个值为最小(最大)值的最大区间,维护的是左右两边第一个比当前位大或者小的数 单调队列解决的是区间最小(最大)值,维护的是区间内的最值 举个栗子,a[i] = { 1,6,3,5,1,2,4 } 如果容器内数字是单调递减的,最后得