单调栈,单调队列 C++

单调栈是一种特殊的数据结构,用于解决一些关于求解最大值、最小值或满足特定条件的问题。它的特点是元素在栈内的顺序是单调的,通常为单调递增或单调递减。

单调栈的基本思想是利用栈的特性,在元素入栈时进行一些操作,以保持栈内元素的单调性。在入栈过程中,如果新元素比栈顶元素更小,那么栈顶元素就不可能成为后续元素的最大值或满足特定条件的值,因此可以将其出栈。这样,在栈内的元素就是按照一定的规则排序的。根据问题的要求,我们可以在适当的时候入栈、出栈或者查询栈内的元素。

单调栈可以应用于很多问题,比如求解数组中每个元素的下一个更大元素、下一个更小元素,或者是找到数组中每个元素的第一个满足特定条件的元素等。通过单调栈可以提高问题的求解效率,通常能够将时间复杂度降低到O(n)。

#include <bits/stdc++.h>
#define ll long long
#define endl "\n"
#define KUI ios::sync_with_stdio(0), cin.tie(0), cout.tie(0)
using namespace std;
const int con = 2e5 + 4;
const int mod = 998244353;
int n, m, k;
void take()
{
    cin >> n;
    int a[n + 1];
    for (int i = 1; i <= n; i++)
    {
        cin >> a[i];
    }
    stack<int> s;
    int ans[n + 1];
    memset(ans, 0, sizeof ans);
    for (int i = 1; i <= n; i++)
    {
        while (s.size() > 0 && a[i] > a[s.top()])
        {
            ans[s.top()] = i;
            s.pop();
        }
        s.push(i);
    }
    for (int i = 1; i <= n; i++)
    {
        cout << ans[i] << " ";
    }
    cout << endl;
}
int main()
{
    KUI;
    int t1 = 1;
    while (t1--)
    {
        take();
    }
    return 0;
}

单调队列(Monotonic Queue)是一种特殊的数据结构,它能够在常数时间内获取队列中的最大值或最小值。

单调队列主要用于解决滑动窗口问题,即在一个固定大小的窗口中,每次移动窗口并计算窗口中的某个值(如最大值、最小值等)。

单调队列的特点是,队列中的元素保持递增或递减的顺序。在每次窗口滑动时,要保持队列的单调性。当新元素进入队列时,首先将队列中比新元素小(或大)的元素移除,然后将新元素插入队列。

通过维护单调队列,在每次窗口滑动时,可以通过队列的头部元素即可获取窗口中的最大值或最小值。

单调队列的基本操作有:
- push:将新元素加入队列
- pop:将队列中的首部元素移除
- front:返回队列中的首部元素
- empty:判断队列是否为空

单调队列的时间复杂度为O(N),其中N为窗口大小。因为每个元素只会进入队列一次,并且最多出队一次。因此,单调队列是一种高效解决滑动窗口问题的数据结构。

#include <bits/stdc++.h>
#define ll long long
#define endl "\n"
#define KUI ios::sync_with_stdio(0), cin.tie(0), cout.tie(0)
using namespace std;
const int con = 2e5 + 4;
const int mod = 998244353;
int n, m, k;
void take()
{
    cin >> n >> k;
    int a[n + 1];
    for (int i = 1; i <= n; i++)
    {
        cin >> a[i];
    }
    deque<int> dq;
    for (int i = 1; i <= n; i++)
    {
        while (dq.size() > 0 && a[i] <= a[dq.back()])
        {
            dq.pop_back();
        }
        dq.push_back(i);
        if (dq.front() < i - k + 1)
        {
            dq.pop_front();
        }
        if (i >= k)
        {
            cout << a[dq.front()] << " ";
        }
    }
    cout << endl;
    dq.clear();
    for (int i = 1; i <= n; i++)
    {
        while (dq.size() > 0 && a[i] >= a[dq.back()])
        {
            dq.pop_back();
        }
        dq.push_back(i);
        if (dq.front() < i - k + 1)
        {
            dq.pop_front();
        }
        if (i >= k)
        {
            cout << a[dq.front()] << " ";
        }
    }
    cout << endl;
}
int main()
{
    KUI;
    int t1 = 1;
    while (t1--)
    {
        take();
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值