C++单调栈模版代码:
cpp
#include<iostream>
#include<vector>
#include<stack>
using namespace std;
/*单调栈模版*/
#define maxn 100001
#define inf 2000000000
template<typename T>
bool cmp(T a, T b) {
return a > b;
}
// ans[i]代表从i往左走,找到的第一个满足条件的下标
template<typename T>
void findFirstMeetOnleft(int n, T h[], int ans[]) {
stack<int> stk;
h[0] = inf;
stk.push(0);
for (int i = 1; i <= n; ++i) {
while(!cmp(h[stk.top()],h[i])) {
stk.pop();
}
ans[i] = stk.top();
stk.push(i);
}
}
template<typename T>
void reverseArray(int n, T arr[]) {
for (int i = 1; i <= n / 2; ++i) {
T tmp = arr[i];
arr[i] = arr[n + 1 - i];
arr[n + 1 - i] = tmp;
}
}
/*单调栈模版*/
int h[maxn], ans[maxn];
int main() {
int n;
cin >> n;
for (int i = 1; i <= n; ++i) {
cin >> h[i];
}
findFirstMeetOnleft(n, h, ans);
for (int i = 1; i <= n; ++i) {
cout << ans[i] << " ";
}
cout << endl;
return 0;
}
代码练习 1,伦太郎的等待,对应蓝桥云课 代码见下
cpp
#include<iostream>
#include<vector>
#include<stack>
using namespace std;
/*单调栈模版*/
#define maxn 100001
#define inf 2000000000
template<typename T>
bool cmp(T a, T b) {
return a >= b;
}
// ans[i]代表从i往左走,找到的第一个满足条件的下标
template<typename T>
void findFirstMeetOnleft(int n, T h[], int ans[]) {
stack<int> stk;
h[0] = inf;
stk.push(0);
for (int i = 1; i <= n; ++i) {
while(!cmp(h[stk.top()],h[i])) {
stk.pop();
}
ans[i] = stk.top();
stk.push(i);
}
}
template<typename T>
void reverseArray(int n, T arr[]) {
for (int i = 1; i <= n / 2; ++i) {
T tmp = arr[i];
arr[i] = arr[n + 1 - i];
arr[n + 1 - i] = tmp;
}
}
/*单调栈模版*/
int h[maxn], ans[maxn];
int main() {
int n;
cin >> n;
for (int i = 1; i <= n; ++i) {
cin >> h[i];
}
findFirstMeetOnleft(n, h, ans);
int ret = 0;
for (int i = 1; i <= n; ++i) {
ret += i - ans[i] - 1;
}
cout << ret << endl;
return 0;
}
代码练习2 对应蓝桥云课 百亿富翁 代码见下
cpp
#include<iostream>
#include<vector>
#include<stack>
using namespace std;
/*单调栈模版*/
#define maxn 700001
#define inf 2000000000
template<typename T>
bool cmp(T a, T b) {
return a > b;
}
// ans[i]代表从i往左走,找到的第一个满足条件的下标
template<typename T>
void findFirstMeetOnleft(int n, T h[], int ans[]) {
stack<int> stk;
h[0] = inf;
stk.push(0);
for (int i = 1; i <= n; ++i) {
while(!cmp(h[stk.top()],h[i])) {
stk.pop();
}
ans[i] = stk.top();
stk.push(i);
}
}
template<typename T>
void reverseArray(int n, T arr[]) {
for (int i = 1; i <= n / 2; ++i) {
T tmp = arr[i];
arr[i] = arr[n + 1 - i];
arr[n + 1 - i] = tmp;
}
}
/*单调栈模版*/
int h[maxn], ans[maxn];
int main() {
int n;
cin >> n;
for (int i = 1; i <= n; ++i) {
cin >> h[i];
}
findFirstMeetOnleft(n, h, ans);
for (int i = 1; i <= n; ++i) {
if (ans[i] == 0) ans[i] = -1;
cout << ans[i] << ' ';
}
cout << endl;
reverseArray(n, h);
findFirstMeetOnleft(n, h, ans);
reverseArray(n, ans);
reverseArray(n, h);
for (int i = 1; i <= n; ++i) {
if (ans[i] == 0) ans[i] = -1;
else ans[i] = (n + 1) - ans[i];
cout << ans[i] << ' ';
}
cout << endl;
return 0;
}
代码练习3 对应蓝桥云课 最大区间 代码见下
cpp
#include<iostream>
#include<vector>
#include<stack>
using namespace std;
/*单调栈模版*/
#define maxn 300001
#define inf -1
template<typename T>
bool cmp(T a, T b) {
return a < b;
}
// ans[i]代表从i往左走,找到的第一个满足条件的下标
template<typename T>
void findFirstMeetOnleft(int n, T h[], int ans[]) {
stack<int> stk;
h[0] = inf;
stk.push(0);
for (int i = 1; i <= n; ++i) {
while(!cmp(h[stk.top()],h[i])) {
stk.pop();
}
ans[i] = stk.top();
stk.push(i);
}
}
template<typename T>
void reverseArray(int n, T arr[]) {
for (int i = 1; i <= n / 2; ++i) {
T tmp = arr[i];
arr[i] = arr[n + 1 - i];
arr[n + 1 - i] = tmp;
}
}
/*单调栈模版*/
int h[maxn], l[maxn], r[maxn];
int main() {
int n;
cin >> n;
for (int i = 1; i <= n; ++i) {
cin >> h[i];
}
findFirstMeetOnleft(n, h, l);
reverseArray(n, h);
findFirstMeetOnleft(n, h, r);
reverseArray(n, h);
reverseArray(n, r);
for (int i = 1; i <= n; ++i) {
r[i] = (n + 1) - r[i];
}
long long max = 0;
for (int i = 1; i <= n; ++i) {
long long x = (r[i] - 1) - (l[i] + 1) + 1;
x = x * h[i];
if (x > max) {
max = x;
}
}
cout << max << endl;
return 0;
}