N people are waiting in line to enter a concert. People get bored waiting so they turn and look for someone familiar in the line.
n個人排隊等待進入音樂會。人們無聊地看看隊伍裏有沒有自己熟悉的人。
Two persons A and B standing in line can see each other if they’re standing right next to each other or if no person between them is strictly taller than person A or person B.
A和B兩個人如果能夠互相看見,他們要麼挨着,要麼他們兩人之間沒有人嚴格高於A或B。
Write a program that determines the number of pairs of people that can see each other.
設計一個程序,求出人羣中有多少對人能夠互相看見。
隨機的題。。題目第一眼看起來就是個單調棧。。
考慮 怎麼看到左邊的人
一定能互相看到左邊第一個比他高的人。
可以看到左邊單調遞減區間的人。
這個東西維護一個單調遞減的單調棧就好了。
然後對於相同高度的,我們可以縮點分類討論一下記錄塊中的 。
只有 這個塊中最左邊的人能向左一覽無餘單調遞減區間。而遇到比他高的人 整塊都會看到。
如果碰到高度相同的人,顯然兩兩都能看到,然後最後合併 。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<ll,ll>par;
typedef pair<par,ll>pii;
const ll INF=2e18;
const int MAXN=8e5+5;
#define mp make_pair
par a[MAXN];
pii sta[MAXN];
ll cnt=0,n,top=0,ans=0,recalc=0;
int main(){
scanf("%lld",&n);
recalc=n-1;
for(int i=1;i<=n;i++){
ll tmp;
scanf("%lld",&tmp);
if(tmp!=a[cnt].first)a[++cnt]=mp(tmp,1);
else a[cnt].second++;
}
for(int i=1;i<=cnt;i++)if(a[i].second>2)recalc+=(a[i].second-1)*(a[i].second-2)/2;
// a[0]=mp(INF,1);
// sta[++top]=mp(a[0],0);
for(int i=1;i<=cnt;i++){
//cout<<ans<<endl;
int flag=0;
while(top&&sta[top].first.first<=a[i].first){
if(sta[top].first.first==a[i].first){
ans+=sta[top].first.second*a[i].second;
flag=sta[top].first.second;top--;
break;
}
ans+=sta[top].first.second;
if(i>1&&i-1==sta[top].second)ans--;
top--;
}
if(top)ans+=a[i].second;
if(top&&sta[top].second==i-1)ans--;
if(flag)a[i].second+=flag;
sta[++top]=mp(a[i],i);
}
printf("%lld\n",ans+recalc);
return 0;
}
/*
6
3
2
2
1
2
2
*/