周任务:
算法主题:
单调栈
具体任务:
对于单调栈还是比较熟悉的,完成任务过程出现了一些困难——都是源自自己对题意的理解,单调栈倒是没啥问题。
POJ2559(一维单调栈维护直方图的面积)
链接
代码:
#include"iostream"
using namespace std;
const int maxn = 100000+5;
int s[maxn],H[maxn],top,N;
int L[maxn],R[maxn];
int main(){
while(~scanf("%d",&N)){
if(N==0)break;
top = 0;
for(int i = 1;i <= N;i++)
scanf("%d",&H[i]);
for(int i = 1;i <= N;i++){
while(top>0&&H[s[top]]>=H[i])top--;
if(top==0)L[i] = 0;
else L[i] = s[top];
s[++top] = i;
}
top = 0;
for(int i = N;i >= 1;i--){
while(top>0&&H[s[top]]>=H[i])top--;
if(top==0)R[i] = N;
else R[i] = s[top] - 1;
s[++top] = i;
}
long long ans = 0;
for(int i = 1;i <= N;i++)
ans = max(ans,(long long)1*(R[i] - L[i])*H[i]);
cout << ans <<endl;
}
return 0;
}
POJ3494(二维单调栈维护直方图面积)
链接
代码:
#include"iostream"
#include"stdio.h"
#include"cstring"
using namespace std;
int N,M;
int a[2005][2005],up[2005],s[2005],l[2005],r[2005],top;
int main(){
while(~scanf("%d%d",&N,&M)){
int ans = 0;
memset(up,0,sizeof(up));
for(int i = 1;i <= N;i++){
for(int j = 1;j <= M;j++){
scanf("%d",&a[i][j]);
if(a[i][j]==0)
up[j] = 0;
else
up[j]++;
}
top = 0;
for(int j = 1;j <= M;j++){
while(top > 0&&up[s[top]] >= up[j])top--;
if(top==0)l[j] = 0;
else l[j] = s[top];
s[++top] = j;
}
top = 0;
for(int j = M;j >= 1 ;j--){
while(top > 0&&up[s[top]] >= up[j])top--;
if(top==0)r[j] = M;
else r[j] = s[top] - 1;
s[++top] = j;
}
for(int j = 1;j <= M;j++)
ans = max(ans,(r[j]-l[j])*up[j]);
}
printf("%d\n",ans);
}
return 0;
}
2019牛客多校训练营第一场A(单调栈记录序列变化趋势)
链接
代码:
#include"bits/stdc++.h"
using namespace std;
const int maxn = 1e5+5;
int N,a[maxn],b[maxn],S1[maxn],S2[maxn];
int main(){
while(~scanf("%d",&N)){
for(int i = 1;i <= N;i ++)
scanf("%d",&a[i]);
for(int i = 1;i <= N;i++)
scanf("%d",&b[i]);
int top1 = 0,top2 = 0,ans = N;
for(int i = 1;i <= N;i++){
while(top1>0&&a[S1[top1]]>a[i])top1--;
S1[++top1] = i;
while(top2>0&&b[S2[top2]]>b[i])top2--;
S2[++top2] = i;
if(top1==top2)continue;
else{
ans = i - 1;
break;
}
}
printf("%d\n",ans);
}
return 0;
}
2019牛客多校训练营第二场H(单调栈求二维直方图面积,题目要求第二大,就要加入最大的内含最大矩形)
链接
代码:(这是我不太喜欢的STL实现)
#include"bits/stdc++.h"
using namespace std;
int N,M,m1 = 0,m2 = 0,a[1005][1005],up[1005][1005]={0};
void Ud(int x,int y){
int sum = x*y;
if(sum > m1){
m2 = m1;
m1 = sum;
}
else if(sum>m2) m2 = sum;
}
int main(){
scanf("%d%d",&N,&M);
for(int i = 1;i <= N;i++)
for(int j = 1;j <= M;j++){
scanf("%1d",&a[i][j]);
}
for(int i = 1;i <= N;i++){
for(int j = 1;j <= M;j++){
if(a[i][j]==0)up[i][j] = 0;
else up[i][j] = up[i-1][j] + 1;
}
}
for(int i = 1;i <= N;i++){
stack<int> S;
S.push(0);
for(int j = 1;j <= M+1;j++){
while(up[i][S.top()]>up[i][j]){
int pos = S.top();
S.pop();
int h = up[i][pos];
int w = j - S.top() - 1;
//cout <<pos<<" "<<j<<" "<<h<<endl;
Ud(w,h);
Ud(w-1,h);
Ud(w,h-1);
}
S.push(j);
}
}
cout << m2;
return 0;
}
2019牛客多校训练营第八场A——(单调栈维护非包含子矩形)
链接
代码:
#include <stdio.h>
#include <stack>
using namespace std;
char s[3005][3005];
int MatrixBottom[3005][3005],up[3005],N,M,ans = 0;
int main() {
scanf("%d%d", &N, &M);
for (int i = 1; i <= N; i++) {
scanf("%s", s[i]);
}
for(int i = 1; i <= N; i++) {
for(int j = 0; j < M; j++) {
if(s[i][j] == '0')
up[j] = 0;
else
up[j]++;
}
stack<int> S;
for(int j = 0; j <= M; j++) {
while(!S.empty() && up[S.top()] > up[j]) {
int t = S.top();
S.pop();
int l;
while(!S.empty() && up[S.top()] == up[t]) S.pop();
if(S.empty()) l = 0;
else l = S.top() + 1;
if(MatrixBottom[l][j - 1] != i) ans++;
MatrixBottom[l][j - 1] = i + 1;
}
S.push(j);
}
}
printf("%d\n", ans);
}