单调栈
定义:
单调栈是指一个栈内部的元素是具有严格单调性的一种数据结构,分为单调递增栈和单调递减栈。
性质:
① 满足从栈顶到栈底元素具有严格的单调性。
② 满足栈的后进先出特性,越靠近栈底的元素越早进栈。
单调队列
定义:
单调队列是指一个队列内部的元素具有严格单调性的一种数据结构,分为单调递增队列和单调递减队列。
性质:
① 单调队列必须满足从队头到队尾的严格单调性。
② 满足队列的先进先出特性,排在队列前面的比排在队列后面的要先出队。
练习
单调栈和单调队列可以用STL中的stack(栈)和deque(双端队列)实现,也可以手写数组实现并且因为数据只会进出至多一次,所以不会超限。
单调栈&单调队列的思想和实现都比较简单,可以试做以下例题去体验这种思想。
单调栈:
#include<iostream>
#include<cstdio>
#include<stack>
using namespace std;
int const maxn=80005;
long long h[maxn],sum;
stack<long long> sta;
int main()
{
int n,i;
scanf("%d",&n);
for(i=1;i<=n;i++) scanf("%lld",&h[i]);
for(i=1;i<=n;i++)
{
while(!sta.empty()&&h[i]>=h[sta.top()]) sta.pop();
sum+=sta.size();
sta.push(i);
}
printf("%lld
",sum);
return 0;
}
#include<iostream>
#include<cstdio>
#include<stack>
using namespace std;
int const maxn=100005;
long long w[maxn],sum[maxn];
int L[maxn],R[maxn];
stack<long long> sta;
int main()
{
int n,i,l,r;
long long ans=-1;
scanf("%d",&n);
for(i=1;i<=n;i++) scanf("%lld",&w[i]),sum[i]=sum[i-1]+w[i];
for(i=n;i>=1;i--)
{
while(!sta.empty()&&w[i]<w[sta.top()])
L[sta.top()]=i+1,sta.pop();
sta.push(i);
}
while(!sta.empty()) L[sta.top()]=1,sta.pop();
for(i=1;i<=n;i++)
{
while(!sta.empty()&&w[i]<w[sta.top()])
R[sta.top()]=i-1,sta.pop();
sta.push(i);
}
while(!sta.empty()) R[sta.top()]=n,sta.pop();
for(i=1;i<=n;i++)
{
if(ans<w[i]*(sum[R[i]]-sum[L[i]-1]))
{
l=L[i];
r=R[i];
ans=w[i]*(sum[R[i]]-sum[L[i]-1]);
}
}
printf("%lld
%d %d
",ans,l,r);
return 0;
}
poj 2559 Largest Rectangle in a Histogram
#include<iostream>
#include<cstdio>
#include<stack>
using namespace std;
struct node
{
int w;
long long h;
node(){}
node(int a,long long b)
{w=a;h=b;}
};
int const maxn=100005;
long long h[maxn];
int main()
{
int n,i;
long long ans;
while(scanf("%d",&n)&&n)
{
stack<node> sta;
ans=-1;h[n+1]=0;
for(i=1;i<=n;i++) scanf("%lld",&h[i]);
for(i=1;i<=n+1;i++)
{
if(sta.empty()||h[i]>sta.top().h) sta.push(node(1,h[i]));
else
{
int t=0;
while(!sta.empty()&&h[i]<=sta.top().h)
{
t+=sta.top().w;
ans=max(ans,sta.top().h*t);
sta.pop();
}
sta.push(node(t+1,h[i]));
}
}
printf("%lld
",ans);
}
return 0;
}
单调队列:
#include<iostream>
#include<cstdio>
#include<queue>
using namespace std;
const int maxn=100010;
deque <int> quemax,quemin;
int w[maxn];
int main()
{
int i,n,m,k,ans,cnt;
while(~scanf("%d%d%d",&n,&m,&k))
{
quemax.clear();quemin.clear();ans=0;cnt=0;
for(i=1;i<=n;i++) scanf("%d",&w[i]);
for(i=1;i<=n;i++)
{
while(!quemax.empty()&&w[i]>w[quemax.back()]) quemax.pop_back();
quemax.push_back(i);
while(!quemin.empty()&&w[i]<w[quemin.back()]) quemin.pop_back();
quemin.push_back(i);
while(!quemax.empty()&&!quemin.empty()&&w[quemax.front()]-w[quemin.front()]>k)
{
if(quemax.front()<quemin.front())
cnt=quemax.front(),quemax.pop_front();
else
cnt=quemin.front(),quemin.pop_front();
}
if(!quemax.empty()&&!quemin.empty()&&w[quemax.front()]-w[quemin.front()]>=m) ans=max(ans,i-cnt);
}
printf("%d
",ans);
}
return 0;
}
#include<iostream>
#include<cstdio>
#include<queue>
using namespace std;
const int maxn=1000005;
deque <int> quemax,quemin;
int w[maxn],mmax[maxn],mmin[maxn];
int main()
{
int i,n,k;
while(~scanf("%d%d",&n,&k))
{
quemax.clear();quemin.clear();
for(i=1;i<=n;i++) scanf("%d",&w[i]);
for(i=1;i<=n;i++)
{
while(!quemax.empty()&&w[i]>w[quemax.back()]) quemax.pop_back();
quemax.push_back(i);
while(!quemax.empty()&&quemax.front()<=i-k) quemax.pop_front();
mmax[i]=w[quemax.front()];
while(!quemin.empty()&&w[i]<w[quemin.back()]) quemin.pop_back();
quemin.push_back(i);
while(!quemin.empty()&&quemin.front()<=i-k) quemin.pop_front();
mmin[i]=w[quemin.front()];
}
for(i=k;i<=n;i++)
printf("%d%c",mmin[i],i==n?'
':' ');
for(i=k;i<=n;i++)
printf("%d%c",mmax[i],i==n?'
':' ');
}
return 0;
}
#include<iostream>
#include<cstdio>
#include<queue>
using namespace std;
int const maxn=2*1e6+5;
int w[maxn],mmax[maxn];
deque<int> que;
int main()
{
int i,n,k;
scanf("%d%d",&n,&k);
for(i=1;i<=n;i++) scanf("%d",&w[i]);
for(i=1;i<=n;i++)
{
while(!que.empty()&&que.front()<=i-k) que.pop_front();
while(!que.empty()&&w[i]>w[que.back()]) que.pop_back();
que.push_back(i);
mmax[i]=w[que.front()];
}
for(i=k;i<=n;i++) printf("%d
",mmax[i]);
return 0;
}
#include<bits/stdc++.h>
using namespace std;
int const maxn=500005;
int sum[maxn];
deque<int> que;
int main()
{
int n,m,x,i,ans=-1;
scanf("%d%d",&n,&m);
for(i=1;i<=n;i++) scanf("%d",&x),sum[i]+=sum[i-1]+x;
for(i=1;i<=n;i++)
{
while(!que.empty()&&que.front()<i-m) que.pop_front();
while(!que.empty()&&sum[i]<sum[que.back()]) que.pop_back();
que.push_back(i);
ans=max(ans,sum[i]-sum[que.front()]);
}
printf("%d
",ans);
return 0;
}
#include<bits/stdc++.h>
using namespace std;
int const maxn=100005;
int h[maxn],ans[maxn];
stack<int> sta;
int main()
{
int n,i;
scanf("%d",&n);
for(i=1;i<=n;i++) scanf("%d",&h[i]);
for(i=1;i<=n;i++)
{
while(!sta.empty()&&h[i]>h[sta.top()])
{
ans[sta.top()]=i;
sta.pop();
}
sta.push(i);
}
while(!sta.empty()) ans[sta.top()]=0,sta.pop();
for(i=1;i<=n;i++) printf("%d
",ans[i]);
return 0;
}