堆栈、队列、单调栈、单调队列
Stack和Queue——栈和队列
- 栈的定义:栈是限定仅在表头进行插入和删除操作的线性表(先进后出)
- 队列的定义:队列是一种特殊的线性表,特殊之处在于它只允许在表的前端(front)进行删除操作,而在表的后端(rear)进行插入操作,和栈一样,队列是一种操作受限制的线性表。进行插入操作的端称为队尾,进行删除操作的端称为队头。(先进先出)
stack常用函数: - push()——向栈顶压入元素
- pop()——弹出栈顶元素
- top()——访问栈顶元素
queue常用函数: - front()——访问队首元素
- back()——访问队尾元素
- push()——向队尾插入元素
- pop()——弹出队首元素
出栈顺序
题目描述:
有n个人,按照1,2,3...n的顺序依次进栈,判读能否以题目所给序列出栈。(n <= 100000)
eg:
- 4 3 2 1
- 1 2 3 4
- 1 3 2 4
- 1 4 2 3
#include<bits/stdc++.h>
#define ios ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
using namespace std;
typedef long long LL;
const int N = 1e5 + 10;
int a[N];
int n;
stack<int> stk;
int main() {
ios;
cin >> n;
for (int i = 1; i <= n; i++) {
cin >> a[i];
}
int j = 1;
for (int i = 1; i <= n; i++) {
stk.push(i);
while (!stk.empty() && a[j] == stk.top()) {
stk.pop();
j++;
}
}
if (!stk.empty()) cout << "No";
else cout << "Yes";
return 0;
}
栈和排序
思路:
如果栈顶元素比后面没入栈的元素都大,那么它就应该出栈
#include<bits/stdc++.h>
#define ios ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
using namespace std;
typedef long long LL;
const int N = 1e6 + 10;
int a[N], maxn[N]; //maxn数组预处理后缀最大值
int n;
stack<int> stk;
int main() {
ios;
cin >> n;
for (int i = 1; i <= n; i++) {
cin >> a[i];
}
//预处理
for (int i = n; i >= 1; i--) {
maxn[i] = max(a[i], maxn[i + 1]);
}
for (int i = 1; i <= n; i++) {
stk.push(a[i]);
while (!stk.empty() && stk.top() > maxn[i + 1]) { //还没进栈的元素是否没有比栈顶元素大的
printf("%d ", stk.top());
stk.pop();
}
}
//如果栈内还有元素,就直接输出
while (!stk.empty()) {
printf("%d ", stk.top());
stk.pop();
}
return 0;
}
好串
#include<bits/stdc++.h>
#define ios ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
using namespace std;
typedef long long LL;
string s;
stack<int> stk;
int main() {
ios;
cin >> s;
for (int i = 0; i < s.size(); i++) {
if (s[i] == 'a') {
stk.push('a');
} else {
if (stk.empty()) {
cout << "Bad" << endl;
return 0;
} else {
stk.pop();
}
}
}
if (stk.empty()) cout << "Good";
else cout << "Bad";
return 0;
}
合并果子
思路:
思考易得,每次选择当前的果子数最少的两堆进行合并,花费的体力最少
维护两个队列
\(q1\)表示还没有合并的果子从小到大的序列
\(q2\)表示已经合并的果子的序列(自然从小到大,因为越合并果子数越大)
每次判断两个队列的队首元素大小,小的出列,合并完后放入\(q2\)
#include<bits/stdc++.h>
#define ios ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
using namespace std;
typedef long long LL;
const int N = 1e5 + 10;
int a[N];
int n;
queue<int> q1, q2;
int main() {
ios;
cin >> n;
for (int i = 1; i <= n; i++) {
cin >> a[i];
}
sort(a + 1, a + 1 + n);
for (int i = 1; i <= n; i++) {
q1.push(a[i]);
}
int ans = 0;
for (int i = 1; i < n; i++) {
int x[3];
for (int j = 1; j <= 2; j++) {
if (q2.empty() || (!q1.empty() && q1.front() < q2.front())) { //注意取q1的条件,q2为空,或者q1不为空,且q1队首小于q2队首
x[j] = q1.front();
q1.pop();
} else {
x[j] = q2.front();
q2.pop();
}
}
ans += x[1] + x[2];
q2.push(x[1] + x[2]);
}
cout << ans << endl;
return 0;
}
优先队列写法:
#include<bits/stdc++.h>
#define ios ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
#define bug(x) cout<<#x<<"=="<<x<<endl;
using namespace std;
typedef long long LL;
const int N = 1e6 + 10;
int n;
int a[N];
priority_queue<int, vector<int>, greater<int> >q;
int main() {
ios;
cin >> n;
for (int i = 1; i <= n; i++) {
cin >> a[i];
q.push(a[i]);
}
LL ans = 0;
for (int i = 1; i < n; i++) {
int tmp1 = q.top();
q.pop();
int tmp2 = q.top();
q.pop();
ans += tmp1 + tmp2;
q.push(tmp1 + tmp2);
}
cout << ans << endl;
return 0;
}
滑动窗口(deque)
题目描述:
给定一个长度为n的数列,求长度为k的定长连续子区间{\(a_1,a_2,a_3,...a_{k-1},a_k\)},{\(a_2,a_3,...a_k,a_{k+1}\)}......中每个区间的最大值和最小值。
#include<bits/stdc++.h>
#define ios ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
using namespace std;
typedef long long LL;
const int N = 1e6 + 10;
int n, k;
int a[N];
deque<int> maxn, minn;
int main() {
ios;
cin >> n >> k;
for (int i = 1; i <= n; i++) {
cin >> a[i];
}
for (int i = 1; i <= n; i++) {
if (!minn.empty() && i - minn.front() >= k) minn.pop_front();
while (!minn.empty() && a[i] <= a[minn.back()]) {
minn.pop_back();
}
minn.push_back(i);
if (i >= k) cout << a[minn.front()];
}
cout << endl;
for (int i = 1; i <= n; i++) {
if (!maxn.empty() && i - maxn.front() >= k) maxn.pop_front();
while (!maxn.empty() && a[i] >= a[maxn.back()]) {
maxn.pop_back();
}
maxn.push_back(i);
if (i >= k) cout << a[maxn.front()];
}
return 0;
}

浙公网安备 33010602011771号