0
点赞
收藏
分享

微信扫一扫

单调栈与单调队列

单调栈与单调队列_数据结构

​单调栈板子题​

​​https://www.luogu.com.cn/problem/P5788​​

#include <iostream>
#include <stack>

using namespace std;

typedef long long ll;

int a[3000100], f[3000100];
stack<ll> st;

int main(){

ll n;

scanf("%lld", &n);

for (int i = 1; i <= n; ++i) {
scanf("%lld", &a[i]);
}

for (int i = n; i >= 1; i--) {

// 将栈中小于等于当前数的数弹出
while (!st.empty()&&a[st.top()]<=a[i]){
st.pop();
}

if(st.empty()){
f[i] = 0;
}else{
// 记录第一个大于当前数的数的下标
f[i] = st.top();
}

// 将当前数的下标入栈
st.push(i);
}

for (int i = 1; i <= n; ++i) {
cout << f[i] << (i == n? '\n':' ');
}

return 0;
}

​单调队列​

​​https://www.luogu.com.cn/problem/P1886​​

单调栈与单调队列_单调栈_02

#include <iostream>

using namespace std;

typedef long long ll;

ll n, m;
ll minn[1000100], maxx[1000100], a[1000100];

struct Node{
// x元素值,y是下标
ll val,ind;
};

Node v[1000100];

void get_min(){
// 维护一个递增序列

ll tail = 0, head = 1;
// 1 3 -1 -3 5 3 6 7
// 1 3
// 1 2
// 先求第一个区间除了最后一个元素之外的增序列
for (int i = 1; i < m; ++i) {
// 将队尾元素大于等于当前元素的值弹出
while (head <= tail && v[tail].val >= a[i]){
tail--;
}
// 此时队尾元素小于当前元素

// 将当前元素和当前元素的下标添加到队尾
v[++tail].val = a[i];
v[tail].ind = i;
}
// 1 3 -1 -3 5 3 6 7
// 1 3
// 1 2
// (-1, 3)
// 从第一个区间开始
for (int i = m; i <= n; ++i) {
// 将队尾元素大于等于当前元素的值弹出
while (head <= tail && v[tail].val >= a[i]){
tail--;
}
// 此时队尾元素小于当前元素

// 将当前元素和当前元素的下标添加到队尾(确保此时的最小值是此区间的最小值)
v[++tail].val = a[i];
v[tail].ind = i;

// 当队列头部元素的下标小于当前m长度区间的头部索引时
while (v[head].ind < (i - m + 1)){
head++;
}

// 当前区间的最小值是队列头部元素
minn[i-m+1] = v[head].val;
}
}

void get_max(){

// 维护一个递减序列
ll tail = 0, head = 1;

for (int i = 1; i < m; ++i) {
while (head <= tail && v[tail].val <= a[i]){
tail--;
}

v[++tail].val = a[i];
v[tail].ind = i;
}

for (int i = m; i <= n; ++i) {
while (head <= tail && v[tail].val <= a[i]){
tail--;
}

v[++tail].val = a[i];
v[tail].ind = i;

while (v[head].ind < (i - m + 1)){
head++;
}

maxx[i-m+1] = v[head].val;
}
}




int main(){

scanf("%lld%lld", &n, &m);

for (int i = 1; i <= n; i++) {
scanf("%lld", &a[i]);
}

get_min();
get_max();

for (int i = 1; i <= n-m+1; ++i) {
printf("%lld%c",minn[i], i==n-m+1?'\n':' ');
}

for (int i = 1; i <= n-m+1; ++i) {
printf("%lld%c",maxx[i], i==n-m+1?'\n':' ');
}

return 0;
}


举报

相关推荐

0 条评论