栈和队列
栈:先进后出
队列:先进先出
栈
栈:是一种特殊的线性表,只允许在固定的一端插入或者删除元素,一个栈包含了栈顶和栈底。只能在栈顶插入或者删除元素。栈的底层是由数组实现的。
栈遵循先入后出原则,也就是先插入的元素得到后面才能删除,后面插入的元素比先插入的元素要更早的删除。可以理解成:后进先出
入栈:在栈顶插入元素。
出栈:在栈顶删除元素。
队列
队列(queue)是一种具有「先进入队列的元素一定先出队列」性质的表。由于该性质,队列通常也被称为先进先出(first in first out)表,简称 FIFO 表。
#include<bits/stdc++.h>
using namespace std;
int main() {
stack<int> st; //栈
queue<int> q; //队列
deque<int> de; //双端队列
}
相关STL函数介绍
P5788 【模板】单调栈
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N = 5e6 + 100;
int cnt, sum;
int a[N];
stack<int>st; // 定义一个整数栈st
int s[N];
int n;
signed main() {
cin >> n; // 从标准输入读取n的值,即数组的长度
for (int i = 1; i <= n; i++) { // 循环读取数组的元素
cin >> a[i]; // 从标准输入读取一个整数并存入数组a的第i个位置
}
for (int i = 1; i <= n; i++) { // 循环处理数组中的每个元素
while (!st.empty() && a[i] > a[st.top()]) { // 如果栈不为空且当前元素大于栈顶元素
s[st.top()] = i; // 将栈顶元素的插入位置存储到数组s中
st.pop(); // 弹出栈顶元素
}
st.push(i); // 将当前元素的索引i压入栈中
}
for (int i = 1; i <= n; i++) // 输出每个元素的插入位置
cout << s[i] << " "; // 在每个位置后面加一个空格并换行
}
H - 阮梅女士的世纪难题
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N=1e6+10;
int n;
int a[N];
signed main() {
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
cin>>n;
for(int i=1; i<=n; i++) {
cin>>a[i];
}
stack<int> st;
int mx=0;
for(int i=1; i<=n; i++) {
while(st.size()&&a[i]>=st.top()) {
st.pop();
}
cout<<st.size()<<' ';
mx=max(mx,(int)(st.size()));
st.push(a[i]);
}
cout<<'\n'<<mx<<'\n';
}
P1090 [NOIP2004 提高组] 合并果子 / [USACO06NOV] Fence Repair G
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N = 1e6 + 10;
int cnt, sum;
int n, m;
deque<int> de;
int q[N];
priority_queue<int, vector<int>, greater<int>> t;
signed main() {
cin >> n;
int i;
for (i = 1; i <= n; i++) {
int x;
cin >> x;
t.push(x);
}
for (i = 1; i < n; i++) {
int a, b;
a = t.top();
t.pop();
b = t.top();
t.pop();
sum += a + b;
t.push(a + b);
}
cout << sum << endl;
}
P1886 滑动窗口 /【模板】单调队列
#include<bits/stdc++.h>
using namespace std;
const int N = 5e6 + 100;
const int M = 10100;
int cnt, sum;
int a[N];
deque<int>q;
signed main() {
int n, k;
cin >> n >> k;
for (int i = 1; i <= n; i++)
scanf("%lld", &a[i]);
for (int i = 1; i <= n; i++) {
if (!q.empty() && i - q.front() + 1 > k)
q.pop_front();
while (q.size() && a[i] <= a[q.back()])
q.pop_back();
q.push_back(i);
if (i >= k)
cout << a[q.front()] << " ";
}
cout << endl;
q.clear();
for (int i = 1; i <= n; i++) {
if (!q.empty() && i - q.front() + 1 > k)
q.pop_front();
while (q.size() && a[i] >= a[q.back()])
q.pop_back();
q.push_back(i);
if (i >= k)
cout << a[q.front()] << " ";
}
cout << endl;
}
[ABC372D] Buildings
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N = 1e6 + 10;
int n, m, k;
int a[N], res[N], b[N];
map<int, int> ans;
signed main() {
ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
cin >> n;
for (int i = 1; i <= n; i++) {
cin >> a[i];
}
stack<int> st;
int cnt = 0;
for (int i = n; i >= 1; i--) {
while (!st.empty() && a[i] > a[st.top()]) {
ans[st.top()] = i;
st.pop();
}
st.push(i);
}
// for (int i = 1; i <= n; i++) cout << ans[i] << " \n"[i == n];
for (int i = 2; i <= n; i++) {
int l = ans[i], r = i - 1;
if (l == 0) l = 1;
b[l] += 1; //将序列中[l, r]之间的每个数都加上c
b[r + 1] -= 1;
}
for (int i = 1; i <= n; i++) {
res[i] = b[i] + res[i - 1]; //前缀和运算
cout << res[i] << " \n"[i == n];
}
}
课后练习
P2251 质量检测
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N = 5e6 + 100;
int sum, cnt;
int a[N];
deque<int> q;
signed main() {
int n, k;
cin >> n >> k;
for (int i = 1; i <= n; i++) {
scanf("%lld", &a[i]);
}
for (int i = 1; i <= n; i++) {
if (!q.empty() && i - q.front() + 1 > k) {
q.pop_front();
}
while (!q.empty() && a[i] <= a[q.back()]) {
q.pop_back();
}
q.push_back(i);
if (i >= k)
cout << a[q.front()] << endl;
}
return 0;
}
P1440 求m区间内的最小值
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N = 5e6 + 100;
const int M = 10100;
int cnt, sum;
deque<int> q;
int a[N];
signed main() {
int n, m;
cin >> n >> m;
for (int i = 1; i <= n; i++) {
scanf("%lld", &a[i]);
}
cout << 0 << endl;
for (int i = 1; i < n; i++) {
if (!q.empty() && i - q.front() + 1 > m)
q.pop_front();
while (q.size() && a[i] <= a[q.back()])
q.pop_back();
q.push_back(i);
cout << a[q.front()] << endl;
}
}
P1714 切蛋糕
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N = 1e8 + 10;
int cnt;
int q[N], a[N];
deque<int>de;
int n, m;
signed main() {
cin >> n >> m;
int maxx = -1e18;
for (int i = 1; i <= n; i++) {
scanf("%lld", &a[i]);
q[i] = q[i - 1] + a[i];
}
de.push_back(0);
for (int i = 1; i <= n; i++) {
while (de.front() + m < i)
de.pop_front();
maxx = max(maxx, q[i] - q[de.front()]);
while (!de.empty() && q[de.back()] >= q[i]) de.pop_back();
de.push_back(i);
}
cout << maxx << endl;
}