1. 程式人生 > >洛谷 P1053 音樂會的等待 解題報告

洛谷 P1053 音樂會的等待 解題報告

print () == 音樂 記錄 的人 can HR 音樂會

P1823 音樂會的等待

題目描述

\(N\)個人正在排隊進入一個音樂會。人們等得很無聊,於是他們開始轉來轉去,想在隊伍裏尋找自己的熟人。隊列中任意兩個人\(A\)\(B\),如果他們是相鄰或他們之間沒有人比\(A\)\(B\)高,那麽他們是可以互相看得見的。

寫一個程序計算出有多少對人可以互相看見。

輸入輸出格式

輸入格式:

輸入的第一行包含一個整數\(N (1 ≤ N ≤ 500 000)\), 表示隊伍中共有\(N\)個人。

接下來的\(N\)行中,每行包含一個整數,表示人的高度,以毫微米(等於\(10^{-9}\)次方米)為單位,每個人的調度都小於\(2^{31}\)毫微米。這些高度分別表示隊伍中人的身高。

輸出格式:

輸出僅有一行,包含一個數\(S\),表示隊伍中共有\(S\)對人可以互相看見。


很明顯的單調棧。

維護一個非嚴格遞減的序列,彈一次加一次\(ans\)即可。

有兩個點:

  1. 關於身高相等的人的處理
    我用額外的cnt記錄了每個身高的人的出現次數,在彈出時加上次數即可

但要註意,在處理相鄰的時候,千萬不要加上cnt了,最開始因為這個只有25分。

2.開 \(long\) \(long\)


code:

#include <cstdio>
#define ll long long
const ll N=500010;
ll a,ans=0,top=0,n;
struct node
{
    ll cnt,h;
}s[N];
void pop() {top--;}
void push(node t) {s[++top]=t;}
int main()
{
    scanf("%lld",&n);
    node t;
    for(ll i=1;i<=n;i++)
    {
        scanf("%lld",&a);
        t.cnt=1;
        t.h=a;
        while(top&&s[top].h<=a)
        {
            if(s[top].h==a) t.cnt+=s[top].cnt;
            ans+=s[top].cnt;
            pop();
        }
        if(top) ans+=1;
        push(t);
    }
    printf("%lld\n",ans);
    return 0;
}

2018.5.19

洛谷 P1053 音樂會的等待 解題報告