【糟糕的一天】
-題目描述-
農民約翰的某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;
}