单调栈是一种特殊的数据结构,用于解决一些关于求解最大值、最小值或满足特定条件的问题。它的特点是元素在栈内的顺序是单调的,通常为单调递增或单调递减。
单调栈的基本思想是利用栈的特性,在元素入栈时进行一些操作,以保持栈内元素的单调性。在入栈过程中,如果新元素比栈顶元素更小,那么栈顶元素就不可能成为后续元素的最大值或满足特定条件的值,因此可以将其出栈。这样,在栈内的元素就是按照一定的规则排序的。根据问题的要求,我们可以在适当的时候入栈、出栈或者查询栈内的元素。
单调栈可以应用于很多问题,比如求解数组中每个元素的下一个更大元素、下一个更小元素,或者是找到数组中每个元素的第一个满足特定条件的元素等。通过单调栈可以提高问题的求解效率,通常能够将时间复杂度降低到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;
}