• 博客园logo
  • 会员
  • 众包
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • HarmonyOS
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录
jacklee404
Never Stop!
博客园    首页    新随笔    联系   管理    订阅  订阅
单调栈与单调队列复习

单调栈与单调队列复习

单调队列

解决问题

对于给定序列\(a\), 求固定长度区间\(k\), 关系运算最大或最小的问题.

最朴素的做法是\(O(nk)\), 利用单调队列可以将复杂度降为\(O(n)\).

思路

以求区间最大为例:

​ 假设存在一个长度为\(k\)的队列,从\(1 \to n\)枚举,若\(a_i \ge a_j (a_j \in queue \and j \le i)\) , 那么\(a_j\)对答案的贡献变为0,此时我们可以将该元素移出队列。

​ 所以做法可以简化维护一个严格单调递减的队列。

Code

#include <iostream>
#define rep(i, j, k) for(int i = j; i <= k; i ++)

const int N = 1e6 + 10;

int q[N], hh = 0, tt = -1;

int a[N];

int main() {
	int n, k;
	std::cin >> n >> k;

	for(int i = 1; i <= n; i ++) {
		std::cin >> a[i];
	}

	for(int i = 1; i <= n; i ++) {
    // 每次检查队头是否不在窗口内
		if(hh <= tt && q[hh] < i - k + 1) hh ++; 

    // 维护单调递减队列
		while(hh <= tt && a[q[tt]] >= a[i]) tt --;
		
		q[++ tt] = i;
		
     if(i >= k)
		    std::cout << a[q[hh]] << " \n"[i == n];
	}

	hh = 0, tt = -1;

	for(int i = 1; i <= n; i ++) {
		if(hh <= tt && q[hh] < i - k + 1) hh ++;

		while(hh <= tt && a[q[tt]] <= a[i]) tt --;

		q[++ tt] = i;
        
     if(i >= k)
       std::cout << a[q[hh]] << " \n"[i == n];
	}
}

单调栈

解决问题

​ 对于给定序列\(a\), 求其与其最近的满足可比较关系的问题。

以求每个数\(a_i\)右侧的第一个小于它的数为例:

​ 朴素做法:\(\Theta(n^2)\), 单调队列做法:\(O(nlogn)\), 单调栈做法\(O(n)\)

思路

​ 假定求\(a_i\)右侧的第一个小于它的数,对于\(1 \le k_1, k_2 < i\) , 若\(k_1 < k_2, \space a_{k_1} \ge a_{k_2}\), 则\(a_{k_1}\) 对答案的贡献为0。

​ 所以对于每个\(i\) ,我们可以维护一个严格单调递增的序列来保证对答案的贡献,由于每次只对序列尾端操作,所以我们可以用栈来解决该问题,并且由于单调递增, 并且对于每个数在维护中可以求得栈尾端元素即为答案。

Code

#include <iostream>

const int N = 1e5 + 10;

int a[N], stk[N], tt = 0;

int main() {
	int n;
	std::cin >> n;

	for(int i = 1; i <= n; i ++) {
		std::cin >> a[i];

		while(tt && a[stk[tt]] >= a[i]) tt --;

		if(tt) {
			std::cout << a[stk[tt]];
		} else {
			std::cout << "-1";
		}

		std::cout << " \n"[i == n];

		stk[++ tt] = i;
	}
}
posted on 2023-02-03 09:48  Jack404  阅读(7)  评论(0)    收藏  举报
刷新页面返回顶部
博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3