栈应用 o(n)实现
有时候利用栈可以降低时间复杂度
对于一些右前后关系的 且 暴力要遍历多次的 可以考虑栈优化
例题:
题意:
给你一串长度为n的数 如果一个数前面有比他大的数那么这个数就可以和前面那个大的数连通 求连通块的个数
思路:
看似像并查集 其实可以用栈 O(1)实现
现将第一个数作为一个元素 记录这个元素最大值和最小值(就是a[1])然后逐个遍历后面的数 如果a[i]比栈顶元素的最大值小就将其并入栈顶元素中更新栈的最大值和最小值
否则 就往栈中push一个新的元素 每次判断 栈顶前两个元素 判断是否可以合并 若是则更新合并后元素的最大值和最小值
最后栈中元素的个数即答案
#include <bits/stdc++.h> #include <queue> #define ll long long #define pi acos(-1) #define FF ios::sync_with_stdio(false), cin.tie(0) using namespace std; const int mod = 1e9 + 7; const int maxn = 1e3 + 10; const int N = 1e5 + 10; const int inf = 0x3f3f3f3f; int n, m, k, ans; int a[N]; struct node{ int mx, mi; }pre[N]; stack<node>st; void solve(){ // 栈清空 while(!st.empty()){ st.pop(); } cin >> n; for(int i = 1; i <= n; i++){ cin >> a[i]; } ans = 1; //先push第一个元素 st.push({a[1], a[1]}); for(int i = 2; i <= n; i++){ node tp = st.top(); if(a[i] < tp.mx) { if(a[i] < tp.mi){ st.pop(); st.push({tp.mx, a[i]}); } } else st.push({a[i], a[i]}); //栈往下判断能否合并 while(st.size() >= 2){ node t1 = st.top(); st.pop(); node t2 = st.top(); if(t2.mx > t1.mi){ //注意栈中的元素不能直接更新 必须先出栈然后再把更新后的放入栈中 t2.mx = max(t1.mx, t2.mx); t2.mi = min(t1.mi, t2.mi); st.pop(); st.push(t2); } else { st.push(t1); break; } } } cout << st.size() << "\n"; } int main() { FF; int t = 1; cin >> t; while(t --){ solve(); } return 0; }
分类:
单调队列单调栈
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 25岁的心里话