首页 > 其他分享 >单调栈

单调栈

时间:2024-01-20 10:46:07浏览次数:23  
标签:int top 栈顶 st vector ans 单调

概述

栈中元素满足单调性的线性数据结构

板子题

P5788 【模板】单调栈 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

题意

即求每一个数的下一个更大数的下标。

思路

  • 维护一个单调递减的栈。
  • 每次插入元素与栈顶进行比较
    • 大于等于栈顶
      • 栈顶不停出栈,直到该元素小于栈顶或栈为空。
      • 出栈的每一个栈顶,对应的答案都是该元素。
    • 小于栈顶
      • 入栈

时间复杂度

从出栈入栈的角度切入分析,所有元素都只会出栈一次,入栈一次,所以复杂度就是 \(\operatorname O(n)\)

代码

#include <bits/stdc++.h>

using namespace std;

int main() {
    int n;
    cin >> n;
    vector<int> a(n + 1);
    stack<int> st;
    vector<int> ans(n + 1);
    for (int i = 1; i <= n; i++) cin >> a[i];
    for (int i = 1; i <= n; i++) {
        while(!st.empty() && a[i] > a[st.top()]) {
            ans[st.top()] = i;
            st.pop();
        }
        st.push(i);
    }
    while(!st.empty()) {
        ans[st.top()] = 0;
        st.pop();
    }
    for (int i = 1; i <= n; i++) {
        cout << ans[i] << ' ';
    }
    cout << endl;
    return 0;
}

最大矩形面积

D-Largest Rectangle in a Histogram_0x11 基本数据结构-栈 (nowcoder.com)

思路

考虑维护每一个元素 \(i\) 左端第一个比它小的下标 \(l_i\) 及右端第一个比它小的下标 \(r_i\)。

显然可能的面积就是 \(a_i \times (r_i - l_i - 1)\)

代码

#include <bits/stdc++.h>

using namespace std;

int main() {
    int n;
    while(cin >> n && n) {
        vector<int> a(n + 2);
        vector<int> l(n + 2), r(n + 2);
        for (int i = 1; i <= n; i++) cin >> a[i];
        a[n + 1] = 0;
        long long ans = 0;
        stack<int> st;
        for (int i = 1; i <= n; i++) {
            while(!st.empty() && a[i] <= a[st.top()]) {
                st.pop();
            }
            if (!st.empty()) l[i] = st.top();
            else l[i] = 0;
            st.push(i);
        }
        while(!st.empty()) st.pop();
        for (int i = n; i; i--) {
            while(!st.empty() && a[i] <= a[st.top()]) {
                st.pop();
            }
            if (!st.empty()) r[i] = st.top();
            else r[i] = n + 1;
            st.push(i);
        }
        for (int i = 1; i <= n; i++) {
            ans = max(ans, 1LL * a[i] * (r[i] - l[i] - 1));
        }
        cout << ans << endl;
    }
    return 0;
}

CF1730C

Minimum Notation - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

题意

给定一个仅包含 \(0\) 到 \(9\) 这几个数字的字符串,你可以执行以下操作任意次:

选择字符串中的一个数字 \(d\),将 \(d\) 删除后,向字符串任意位置插入一个数字 \(\min(d+1,9)\)

求能够得到的字典序最小的字符串。

思路

想要让字典序最小,就要尽可能将小的数放在前面。每次执行一次操作后,我们都会让一个数变大,只有变大后把它放在字符串后面,让一个更小的数能到前面来,他才能更优。

维护一个单调栈,将弹出的元素 \(d=\min(d+1,9)\) 全部存入一个 vector 中,将所有元素排序。最后输出答案,在输出单调栈中元素的同时,输出 vector 中与之相等的元素,因为已经排完序了,直接从前向后扫即可。

void solve() {
    string s;
    stack<char> st;
    vector<char> els,ans;
    cin >> s;
	int len = s.length();
	for(int i = 0;i < len;i++) {
		while(!st.empty() && st.top() > s[i]) {
			els.push_back(min((char)(st.top() + 1),'9'));
			st.pop();
		}
		st.push(s[i]);
	}
	while(!st.empty()) {
		ans.push_back(st.top());
		st.pop();
	}
	sort(els.begin(),els.end());
	int pos = 0;
	for(int i = ans.size() - 1;i >= 0;i--) {
		cout << ans[i];
		while(pos < els.size() && els[pos] >= ans[i] 
        && els[pos] <= ans[i-1] && i > 0) cout << els[pos++];
	}
	for(int i = pos;i < els.size();i++) cout << els[i];
	cout << endl;
	return;
}

标签:int,top,栈顶,st,vector,ans,单调
From: https://www.cnblogs.com/kdlyh/p/17976128

相关文章

  • 滑动窗口的最大值 239 单调队列初识
    最开始做的时候,暴力解法结果不管怎么剪枝,还是超时了。后来看到了卡哥的方法,学到了单调队列,其实就是自定义队列。用deque来实现。有三个关键点:pop,push,front.pop,如果遍历的元素等于队头元素,则头删。push,把比遍历元素小的都进行尾部删。front,就是普通的查找队头。循环遍历的时......
  • CF-514-D-单调队列
    514-D题目大意给定\(n\)个人,每个人有\(m\)个属性,第\(i\)个人的第\(j\)个属性值为\(a[i][j]\)。最多可以执行\(k\)次操作,每次操作选定一个属性,把所有人的该属性减\(1\),求一段最长的区间,满足执行所有操作之后该区间中所有人的所有属性全部为\(0\)。Solution转换一下思考方向,求......
  • dp优化-决策单调性 / 四边形不等式
    前言这种优化我以前“听”过了很多次,但是好像都没学会qwq。四边形不等式:对于二元组\(w_{x,y}\),如果在定义域上任取四个点\(a\leb\lec\led\),满足:\[w_{a,b}+w_{c,d}\gew_{a,c}+w_{b,d}\]则称\(w_{x,y}\)满足四边形不等式。你会想这鬼东西怎么记?反正我也不想记。......
  • elixir erlang 简单调用学习
    实际上基于elixir的mix进行erlang以及elixir的互调用开发处理是很方便的,mix直接就包含了构建erlang代码同时对于代码的互调用,只要使用符合语言格式要求就行了,以下是一个简单的互调用学习项目准备项目结构 ├──README.md├──lib│├──a.ex│└──er_app......
  • elixir erlang 简单调用学习
    实际上基于elixir的mix进行erlang以及elixir的互调用开发处理是很方便的,mix直接就包含了构建erlang代码同时对于代码的互调用,只要使用符合语言格式要求就行了,以下是一个简单的互调用学习项目准备项目结构 ├──README.md├──lib│├──a.e......
  • 单调栈
    单调栈是一种下标单调、元素单调的栈使用场景若干区间内找最值,转化为枚举每个最值找区间寻找每个元素\(a[i]\)向右(左)第一个比\(a[i]\)大(小)的位置如何寻找\(a[i]\)右边第一个大于\(a[i]\)的位置?枚举下标\(i\),\(a[i]\)与栈顶循环比较,若a[i]>a[stk.top()],则R[stk.top()]=i,stk......
  • 单调栈分类、封装和总结
    作者推荐map|动态规划|单调栈|LeetCode975:奇偶跳通过枚举最小(最大)值不重复、不遗漏枚举所有子数组C++算法:美丽塔O(n)解法单调栈左右寻找第一个小于maxHeight[i]的left,right,[left,right]直接的高度都是maxHeight[i]可以用封装的类,可以理解为枚举山顶这个子数组【单调栈]LeetCode8......
  • map|动态规划|单调栈|LeetCode975:奇偶跳
    作者推荐【贪心算法】【中位贪心】.执行操作使频率分数最大涉及知识点单调栈动态规划map题目给定一个整数数组A,你可以从某一起始索引出发,跳跃一定次数。在你跳跃的过程中,第1、3、5…次跳跃称为奇数跳跃,而第2、4、6…次跳跃称为偶数跳跃。你可以按以下方式从索引i向后跳转......
  • 浅谈单调栈
    单调栈,顾名思义,具有单调性的栈。单调,指满足一个序列是一个从小到大的序列或从大到小的序列。栈(\(stack\))是以一种线性存储结构,它具有以下特点:栈中的数据元素遵守“先进后出(\(First\in\Last\out\))”的原则,简称FILO结构;限定只能在栈顶进行插入和删除操作。所以,何为单......
  • 单调栈求解算法
    例题:503. 下一个更大元素II给定一个循环数组 nums ( nums[nums.length-1] 的下一个元素是 nums[0] ),返回 nums 中每个元素的 下一个更大元素 。数字 x 的 下一个更大的元素 是按数组遍历顺序,这个数字之后的第一个比它更大的数,这意味着你应该循环地搜索它的下一......