栈应用 o(n)实现

有时候利用栈可以降低时间复杂度 

对于一些右前后关系的 且 暴力要遍历多次的 可以考虑栈优化

例题:

1638C - Inversion Graph

题意:

给你一串长度为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; 
}
复制代码

 

posted @   Yaqu  阅读(61)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 25岁的心里话
点击右上角即可分享
微信分享提示