【糟糕的一天】
-题目描述-
农民约翰的某N(1 < N < 80000)头奶牛正在过乱头发节!所有N头牛面向东方排成一排,牛N在最前面,而牛1在最后面.第i头牛可以看到她前面的那些牛的头。每一头牛i有一个高度,只要那些牛的高度严格小于她的高度,而且中间没有比hi高或相等的奶牛阻隔。约翰希望统计出能够看到其他牛的头发的牛的数量。让Ci表示第i头牛可以看到发型的牛的数量,请输出Ci的总和。(https://www.luogu.org/problem/show?pid=P2866)
-输入格式-
第1行n,表示奶牛的头数。
第2行到第n+1行,每行一个数,表示牛的高度。
-输出格式-
一行,Ci的总和。
-样例数据-
input
6
10
3
7
4
12
2
output
5
-分析-
这是一道很典型的单调栈的题。
(输入顺序不同)
我们所要维护一个单调递减的栈。栈中放入的是奶牛的编号。如果当前是要放入的奶牛的高度的大小比栈顶的奶牛编号所代表的奶牛的高度小,就直接放入(这是栈中的奶牛都可以看见的)。不然不断弹出栈顶的奶牛编号(栈顶奶牛不能看见),直至找到栈顶奶牛的高度比当前枚举到的奶牛的高度大或者栈为空,再放入。所要求的个数即为:当奶牛所处位置-弹出栈顶的奶牛的位置-1。
-代码-
#include<bits/stdc++.h>
using namespace std;
int n;
int h[80100]={};
int f[80100]={};
int tail=0;
long long ans=0;
int main()
{
cin>>n;//读入奶牛头数
for(int i=1;i<=n;i++)
cin>>h[i];//读入每一头奶牛的高度
f[++tail]=1;//先将第一头奶牛的编号放入栈
for(int i=2;i<=n;i++)//注意是从编号小(后面的奶牛)开始枚举
{
for(;h[f[tail]]<=h[i]&&tail>0;)//当栈顶奶牛的高度小于想放入奶牛的高度并且栈不为空
{
ans+=i-f[tail]-1;//答案累加
tail--;//弹出栈顶奶牛的编号
}
f[++tail]=i;//放入
}
for(;tail>0;)
{
ans+=n-f[tail];
tail--;
}//加上没有弹出的元素
cout<<ans<<endl;//输出答案
return 0;
}