音乐会的等待-单调栈

关于本题,这里只是基础的写法,完美的避开了特殊情况,另一篇博文会详细讲解特殊情况

[COI2007] Patrik 音乐会的等待

题目描述

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

说句实话,这道题真的挺坑的,首先,我们先来说一下大体的思路。

这道题其实就是给出一个队伍,要找出所有能相互看见的一对(两个人之间没有比两个人任意一个人高的人),那么我们该怎么做呢?

我们来想一下,由于题中让我们找的是对数,为了避免找重了,我们只能看一个方向(如果你偏要看两个方向再除以二也没有人拦你。。。),但是从左往右看显然前面元素会受到后面的影响,为了保证正序判断,这里应该从右往左看。

我们任意取一位人,那么这个人所能看到最远的人就是它前面第一个比他高的人,并且如果这个人高于他左边的人P,那么显然他右边的人一定看不到P。

根据这两条性质,我们很容易想到一种数据结构:栈。又因为每个人入栈时栈中元素一定是单调不递增的,所以该栈具有单调性,因此我们引入一个新的概念:单调栈。

归概来说,每当我们放入一个元素,我们只需要执行两个操作:

1.查找第一个比他高的人,统计看到的人数

2.弹出会被他遮到(小于他)的元素

第一条我们可以用二分法查找,而第二条直接线性搜索即可。

最后,附上本题代码:

 1 #include<cstdio>
 2 using namespace std;
 3 int n,top;
 4 long long Ans;
 5 int a[500050],stk[500050];
 6 void dfs(int x)
 7 {
 8     int le=0,ri=top,mid,ret=0;
 9     while(le<=ri)
10     {
11         mid=(le+ri)>>1;
12         if(a[stk[mid]]>x)ret=mid,le=mid+1;
13         else ri=mid-1;
14     }
15     if(!ret)Ans+=top;
16     else Ans+=top-ret+1;
17 }
18 int main()
19 {
20     scanf("%d",&n);
21     for(int i=1; i<=n; ++i)scanf("%d",&a[i]);
22     for(int i=1; i<=n; ++i)
23     {
24         dfs(a[i]);
25         while(top>0&&a[i]>a[stk[top]])--top;
26         stk[++top]=i;
27     }
28     printf("%lld",Ans);
29     return 0;
30 }

原文地址:https://www.cnblogs.com/yufenglin/p/10306366.html

时间: 2024-10-22 07:36:14

音乐会的等待-单调栈的相关文章

洛谷P1823 音乐会的等待 单调栈

洛谷P1823 音乐会的等待 单调栈 维护一个上升的单调栈 用以记录有当前这个数向后能看到几个数 但是每次加入一个数 时 他能看到的 是 单调栈中所有比他小的 和跟他一样的数 比他小的下次就没有用了,所以直接退栈 但是 相同的数到后面还是可能会有贡献的,所以贡献算完以后又要进栈 最后如果栈中还有元素,那么栈顶一定能看到自身,所以+1 1 #include <bits/stdc++.h> 2 #define For(i,j,k) for(int i=j;i<=k;i++) 3 #defin

音乐会的等待-单调栈(进阶版)

这道题的基础做法在上一篇博文中已经提到了,详情请见:https://www.cnblogs.com/yufenglin/p/10306366.html 而在课上有人提到了一种简便做法(错的,但可以改对),先来回顾一下题目: 题目描述 N个人正在排队进入一个音乐会.人们等得很无聊,于是他们开始转来转去,想在队伍里寻找自己的熟人.队列中任意两个人A和B,如果他们是相邻或他们之间没有人比A或B高,那么他们是可以互相看得见的. 写一个程序计算出有多少对人可以互相看见. 输入输出格式 输入格式: 输入的第

洛谷——P1823 音乐会的等待

https://www.luogu.org/problem/show?pid=1823 题目描述 N个人正在排队进入一个音乐会.人们等得很无聊,于是他们开始转来转去,想在队伍里寻找自己的熟人.队列中任意两个人A和B,如果他们是相邻或他们之间没有人比A或B高,那么他们是可以互相看得见的. 写一个程序计算出有多少对人可以互相看见. 输入输出格式 输入格式: 输入的第一行包含一个整数N (1 ≤ N ≤ 500 000), 表示队伍中共有N个人. 接下来的N行中,每行包含一个整数,表示人的高度,以毫微

洛谷 P1823 音乐会的等待

题目描述 N个人正在排队进入一个音乐会.人们等得很无聊,于是他们开始转来转去,想在队伍里寻找自己的熟人.队列中任意两个人A和B,如果他们是相邻或他们之间没有人比A或B高,那么他们是可以互相看得见的. 写一个程序计算出有多少对人可以互相看见. 输入输出格式 输入格式: 输入的第一行包含一个整数N (1 ≤ N ≤ 500 000), 表示队伍中共有N个人. 接下来的N行中,每行包含一个整数,表示人的高度,以毫微米(等于10的-9次方米)为单位,每个人的调度都小于2^31毫微米.这些高度分别表示队伍

洛谷 P1823 音乐会的等待 题解

此文为博主原创题解,转载时请通知博主,并把原文链接放在正文醒目位置. 题目链接:https://www.luogu.org/problem/show?pid=1823 题目描述 N个人正在排队进入一个音乐会.人们等得很无聊,于是他们开始转来转去,想在队伍里寻找自己的熟人.队列中任意两个人A和B,如果他们是相邻或他们之间没有人比A或B高,那么他们是可以互相看得见的. 写一个程序计算出有多少对人可以互相看见. 输入输出格式 输入格式: 输入的第一行包含一个整数N (1 ≤ N ≤ 500 000),

(单调栈)poj-2559 Largest Rectangle in a Histogram

A histogram is a polygon composed of a sequence of rectangles aligned at a common base line. The rectangles have equal widths but may have different heights. For example, the figure on the left shows the histogram that consists of rectangles with the

【单调栈】hdu1506 Largest Rectangle in a Histogram

单调栈的介绍及一些基本性质 http://blog.csdn.net/liujian20150808/article/details/50752861 依次把矩形塞进单调栈,保持其单增,矩形中的元素是一个三元组,存储其位置,高度,以及以其为高度的情况下,大矩形的左边界最多扩展到哪里. 每次将新的元素塞进栈的时候,其左边界就是其左侧第一个小于它的矩形的位置+1. 然后,每个矩形出栈的时候,记录其右边界为当前往栈里面塞的矩形的位置-1,然后更新答案即可. 注意最后把所有的矩形出栈,更新答案. #in

BZOJ 3238 AHOI 2013 差异 后缀数组+单调栈

题目大意: 思路:一看各种后缀那就是后缀数组没跑了. 求出sa,height之后就可以乱搞了.对于height数组中的一个值,height[i]来说,这个值能够作为lcp值的作用域只在左边第一个比他小的位置到右边第一个比他小的位置.这个东西很明显可以倍增RMQ+二分/单调栈. 之后就是数学题了 Σlen[Ti] + len[Tj] = (len + 1) * len * (len - 1),之后吧所有求出来的Σ2 * lcp(Ti,Tj)减掉就是答案. 记得答案开long long CODE:

51nod 1215 数组的宽度&amp;poj 2796 Feel Good(单调栈)

单调栈求每个数在哪些区间是最值的经典操作. 把数一个一个丢进单调栈,弹出的时候[st[top-1]+1,i-1]这段区间就是弹出的数为最值的区间. poj2796 弹出的时候更新答案即可 #include<iostream> #include<cstdlib> #include<cstring> #include<cstdio> #include<algorithm> #include<queue> #include<cmath