单调栈
单调栈顾名思义就是让栈中的元素是单调的,要么递增,要么递减。同样它也满足栈的性质,先进后出。
- 单调递增栈,则从栈顶到栈底的元素是严格递增的
- 单调递减栈,则从栈顶到栈底的元素是严格递减的
练习题
POJ3250
POJ3250传送门
对于每一个牛来说,能看到的数目为向右数身高比它小的个数,累加就是答案。
所以可以倒着维护一个单调递增的栈,记录i之前的弹栈数目,累加。
(正着也可以,那么就是维护对于每一头牛来说,它被多少头牛看到)
Code:
#include <stdio.h>
#define MAXN 80000+100
typedef unsigned long long llu;
llu n,ans=0;
long long s_size=-1;
llu s[MAXN];
int main()
{
scanf("%llu",&n);
for(llu i=1;i<=n;i++)
{
llu x;
scanf("%llu",&x);
while(s_size>=0&&x>=s[s_size])s_size--;
s[++s_size]=x;
ans+=s_size;
}
printf("%llu\n",ans);
return 0;
}
POJ2796
-
POJ2796传送门 这道题比较麻烦,但是思想很重要,对于每一个点,求出向左/右第一个比它大的位置,然后O(N)枚举,找出最值。 但是需要注意两点:
- 开long long
-
预处理前缀和
Code:
#include<stdio.h>
#include<string.h>
#include<stack>
#define MAXN 100005
typedef long long ll;
using namespace std;
ll n,x,ans,l_,r_,top;
ll a[MAXN],l[MAXN],r[MAXN],s[MAXN],sum[MAXN];
ll max(ll a,ll b){
return a>b?a:b;}
int main()
{
while(~scanf("%lld",&n)&&n)
{
ans=0;
l