首页 > 代码库 > 洛谷 P1823 音乐会的等待 题解

洛谷 P1823 音乐会的等待 题解

此文为博主原创题解,转载时请通知博主,并把原文链接放在正文醒目位置。

题目链接:https://www.luogu.org/problem/show?pid=1823

题目描述

N个人正在排队进入一个音乐会。人们等得很无聊,于是他们开始转来转去,想在队伍里寻找自己的熟人。队列中任意两个人A和B,如果他们是相邻或他们之间没有人比A或B高,那么他们是可以互相看得见的。

写一个程序计算出有多少对人可以互相看见。

输入输出格式

输入格式:

输入的第一行包含一个整数N (1 ≤ N ≤ 500 000), 表示队伍中共有N个人。

接下来的N行中,每行包含一个整数,表示人的高度,以毫微米(等于10的-9次方米)为单位,每个人的调度都小于2^31毫微米。这些高度分别表示队伍中人的身高。

输出格式:

输出仅有一行,包含一个数S,表示队伍中共有S对人可以互相看见。

输入输出样例

输入样例#1:
7 2 4 1 2 2 5 1
输出样例#1:
10

说明

数据制作: @w

 

 

分析:(参考了@hychychyc 的题解)

此题用单调栈来做,构建一个单调递减的栈。

一旦出现了一个比栈顶大的元素,那么该元素就可以“看到”栈内第一个比它大的元素之前的所有元素。

这时就把栈内元素依次弹出,直到栈顶元素比该元素大(或栈被弹空)再将该元素入栈。

 

AC代码

 1 #include<iostream> 2 #include<cstdio> 3 #include<cmath> 4 #include<stack> 5  6 using namespace std; 7 int num[500005]; 8 //数组模拟一个栈  9 int main()10 {11     int n,x,top = 1,ans = 0,tmp;12     //tmp记录当前相等的元素个数 13     scanf("%d%d",&n,&x);14     num[1] = x;15     for(int i = 2;i <= n;i ++)16     {17         tmp = 1;18         scanf("%d",&x);19         if(x >= num[top])20         {21             while(x > num[top] && top > 0)22                 top --,ans ++;23             while(x == num[top] && top > 0)24             {//相等情况 25                 tmp ++;26                 top --,ans ++;27             }28         }29         if(top != 0)    ans ++;30         //如果栈内还有元素,即比x大的第一个元素,两者也可以相互看到 31         top += tmp;//把相等的元素加回去 32         num[top] = x; 33     }34     printf("%d\n",ans);35     return 0;36 } 

洛谷 P1823 音乐会的等待 题解