单调栈模板
* 本代码对应的是单调递减栈
*共n个元素,编号为0~n-1
*/
while(栈不为空) 栈顶元素出栈;
a[n]=-1;
for(i=0;i<=n;i++)
{
if(栈为空或入栈元素小于等于栈顶元素) 入栈;
else
{
while(栈非空并且入栈元素大于栈顶元素)
{
栈顶元素出栈;
更新结果;
}
面对不同的题,不同入栈方式。
1、当所有破坏栈的单调性的元素出栈后,将当前元素入栈。
2、将最后一次出栈的栈顶元素(即当前元素可以拓展到的位置)入栈; 更新最后一次出栈的栈顶元素其对应的值;
}
}
最基础的应用就是给定一组数,针对每个数,寻找它和它右边第一个比它大的数之间有多少个数。
#include<stdio.h>
#include<string.h>
#include<iostream>
#include<stack>
#define inf 0x3f3f3f3f
using namespace std;
typedef long long LL;
int main(){
int i,n,top,a[80010];
LL ans;
stack<int> st;
while(~scanf("%d",&n)){
while(!st.empty()) st.pop();
for(i=0;i<n;i++)
scanf("%d",&a[i]);
a[n]=inf;
ans=0;
for(i=0;i<=n;i++){
if(st.empty()||a[i]<a[st.top()]){
st.push(i);
}
else {
while(!st.empty()&&a[i]>=a[st.top()]){
top=st.top();
st.pop();
ans+=(i-top-1);
}
st.push(i);
}
}
printf("%lld\n",ans);
}
return 0;
}
给定一序列,寻找某一子序列,使得子序列中的最小值乘以子序列的长度最大
#include<stdio.h>
#include<string.h>
#include<iostream>
#include<stack>
using namespace std;
typedef long long LL;
int main()
{
int i,n,top;
stack<int> st;
LL tmp,ans,a[100010];
while(~scanf("%d",&n)&&n){
for(i=0;i<n;i++)
scanf("%lld",&a[i]);
ans=0;
a[n]=-1;
for(i=0;i<=n;i++){
if(st.empty()||a[i]>=a[st.top()]){
st.push(i);
}
else{
while(!st.empty()&&a[i]<a[st.top()]){
top=st.top();
st.pop();
tmp=(i-top)*a[top];
if(tmp>ans) ans=tmp;
}
st.push(top);
a[top]=a[i];
}
}
printf("%lld\n",ans);
}
return 0;
}
给定一序列,寻找某一子序列,使得子序列中的最小值乘以子序列所有元素和最大
#include<stdio.h>
#include<iostream>
#include<stack>
using namespace std;
typedef long long LL;
int main()
{
int i,n;
LL tmp,top,ans,a[100010],sum[100010];
stack<int> st;
while(~scanf("%d",&n)){
while(!st.empty()) st.pop();
sum[0]=0;
for(i=1;i<=n;i++){
scanf("%lld",&a[i]);
sum[i]=sum[i-1]+a[i];
}
a[n+1]=-1;
ans=0;
for(i=1;i<=n+1;i++){
if(st.empty()||a[i]>=a[st.top()]){
st.push(i);
}
else {
while(!st.empty()&&a[i]<a[st.top()]){
top=st.top();
st.pop();
tmp=sum[i-1]-sum[top-1];
tmp*=a[top];
if(tmp>=ans)ans=tmp;
}
st.push(top);
a[top]=a[i];
}
}
printf("%lld\n",ans);
}
return 0;
}