栈和队列

栈:先进后出

队列:先进先出

栈:是一种特殊的线性表,只允许在固定的一端插入或者删除元素,一个栈包含了栈顶和栈底。只能在栈顶插入或者删除元素。栈的底层是由数组实现的。

栈遵循先入后出原则,也就是先插入的元素得到后面才能删除,后面插入的元素比先插入的元素要更早的删除。可以理解成:后进先出

入栈:在栈顶插入元素。

出栈:在栈顶删除元素。

队列

队列(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;
}
posted @ 2024-10-12 19:11  ZhangDT  阅读(18)  评论(0编辑  收藏  举报