P1823 [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

说明/提示

数据制作: @w

2018.6.29添加3组数据

【思路】

单调栈

很有意思的一道题目

【题目大意】

一个队列

两个人中间只要没有比他俩其中一个高的就可以相互看见

求能够相互看见的对数

【理智分析】

这对点能够互相看见是基于两者之间没有比他们任何一者高的基础上的

一个人能够看见最远的一个人就是两边第一个比他高的

这很显然对吧?

因为第一个比他高的之后的人就被他挡住了

(贴合实际)

然后如果这个人和一边第一个比他高的人

中间的人不一定能够全部被这个人看见

【举例】

因为:

1 1 4 5 1 4 1 9 1 9

位置8上的那个9右边能看到最远的就是位置1上的1

但是位置1到位置8之间所有的数

他不是都能够彼此看见的

比如位置5上的那个1

就不能彼此看见

因为中间有一个位置6上的4是比1高的

所以彼此看不见

看一下位置8上的9右边能够看到的数

5 4 1

很显然这是一个大向右递增的区间

因为你看到了右边第一个之后

看到的右边第二个不能够比右边第一个要低

不然就是不能够被看见的

【呼之欲出】

是不是很显然了?

这不就是单调栈吗!?

【最终思路】

上面的过程完全就是在单调栈的过程对吧

如果栈里面的栈顶元素比手上这个元素要小

那栈顶元素左边能够看到的最后一个元素就是手上这个了

再也看不到别的了

这就是1对可以互相看见

弹出就好了

然后手上这个继续和栈顶去比较

【注意】

两个一样高的人是可以相互看见的

1 1 1 1 1

这串数字里面

第一个1是可以和最后一个1相互看见的

千万不要忽略哦

然后就是怎么处理上面这种情况了

一开始我想的是暴力从栈里面取出来

计数有多少个

计完数之后再放回栈

这样就超时了两个点

这两个点我下载了一个点的测试数据看来一下

500000个一样的10

不超时才怪……

所以 可以在栈中存一个结构体

记录这个人的高度和人数

也就是和她一样高的并且在栈中位置是紧挨着的

遇到和她一样的情况只需要将其弹出

然后在弹入一个v(计数多少个人) + 1的就好了

【完整代码】

【80分暴力出栈代码】

#include<iostream>
#include<cstdio>
#include<stack>
using namespace std;
const int Max = 500005;
int a[Max];
stack<int>s;
int main()
{
int n;
cin >> n;
for(register int i = 1;i <= n;++ i)
cin >> a[i];
int js = 0;
for(register int i = 1;i <= n;++ i)
{
int jj = 0;
while(!s.empty() && a[i] >= s.top())
{
if(a[i] == s.top())
{
while(!s.empty() && s.top() == a[i])
s.pop(),jj ++,js ++;
}
else
{
s.pop();
js ++;
}
}
if(!s.empty())
js ++;
while(jj --)
s.push(a[i]);
s.push(a[i]);
}
cout << js << endl;
return 0;
}

【AC代码】

#include<iostream>
#include<cstdio>
#include<stack>
#define int long long
using namespace std;
const int Max = 500005;
struct node
{
int h;
int v;
}a[Max];
stack<node>s;
signed main()
{
// freopen("music.in","r",stdin);
int n;
cin >> n;
for(register int i = 1;i <= n;++ i)
cin >> a[i].h,a[i].v = 1;
int ans = 0;
for(register int i = 1;i <= n;++ i)
{
while(!s.empty() && a[i].h > s.top().h)
{
ans += s.top().v;
s.pop();
}
if(!s.empty() && a[i].h == s.top().h)
{
node qwq = s.top();
ans += s.top().v;
s.pop();
if(!s.empty())
ans ++;
s.push((node){qwq.h,qwq.v + 1});
}
else
{
if(!s.empty())
ans ++;
s.push(a[i]);
}
}
cout << ans << endl;
return 0;
}

洛谷 P1823 [COI2007] Patrik 音乐会的等待 题解的更多相关文章

  1. 洛谷 P1823 [COI2007] Patrik 音乐会的等待

    洛谷 P1823 [COI2007] Patrik 音乐会的等待 洛谷传送门 题目描述 N个人正在排队进入一个音乐会.人们等得很无聊,于是他们开始转来转去,想在队伍里寻找自己的熟人.队列中任意两个人A ...

  2. 洛谷P1823 [COI2007] Patrik 音乐会的等待(单调栈+二分查找)

    洛谷P1823 [COI2007] Patrik 音乐会的等待(单调栈+二分查找) 标签:题解 阅读体验:https://zybuluo.com/Junlier/note/1333275 这个题不是很 ...

  3. 洛谷P1823 [COI2007] Patrik 音乐会的等待

    https://www.luogu.org/problemnew/show/P1823 自己只会一个log的 设取的人的位置分别是l,r(l<r) 这个做法大概是考虑枚举r,设法对于每个r求出有 ...

  4. 洛谷 1823 [COI2007] Patrik 音乐会的等待

    [题解] 维护一个单调栈即可. 但是因为有相同身高的存在,所以要稍微考虑下相同身高的处理.因为这个卡了一下下QAQ... #include<cstdio> #include<algo ...

  5. P1823 [COI2007] Patrik 音乐会的等待 单调栈 洛谷luogu

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

  6. [COI2007] Patrik 音乐会的等待 (单调栈,模拟)

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

  7. luoguP1823 [COI2007] Patrik 音乐会的等待

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

  8. [COI2007] Patrik 音乐会的等待 单调栈

    Code: #include<cstdio> #include<algorithm> #include<iostream> #include<cstring& ...

  9. [洛谷P1823]音乐会的等待 题解(单调栈)

    [洛谷P1823]音乐会的等待 Description N个人正在排队进入一个音乐会.人们等得很无聊,于是他们开始转来转去,想在队伍里寻找自己的熟人.队列中任意两个人A和B,如果他们是相邻或他们之间没 ...

随机推荐

  1. [SOJ #537]不包含 [CF102129I]Incomparable Pairs(2019-8-6考试)

    题目大意:给定一个长度为$n$的字符串$s$,求有多少个无序字符串二元组$(x,y)$满足:$x,y$是$s$的字串,且$x$不是$y$的字串,$y$不是$x$的字串 题解:发现满足$x,y$是$s$ ...

  2. UOJ46 清华集训2014玄学(线段树)

    注意到操作有结合律,容易想到用一个矩形表示第i次操作对第j个位置的数的影响.那么修改是单行内的区间修改,而查询是单列内的区间查询.这样二维线段树上以列为外层行为内层直接打标记就可以维护.然后就喜闻乐见 ...

  3. twbsPagination.js分页插件

    分页插件在使用时注意,如果页面中存在其他异步加载的数据,在运行分页方法第一次后,页面上的分页样式与分页中的data数据就是第一次的数据,如果异步加载重新在页面上录入数据,并希望分页继续在新的数据上实现 ...

  4. 全栈项目|小书架|服务器开发-Koa2中间件机制洋葱模型了解一下

    KOA2 是什么? Koa是一个新的 web 框架,由 Express 幕后的原班人马打造, 致力于成为 web 应用和 API 开发领域中的一个更小.更富有表现力.更健壮的基石. 通过利用 asyn ...

  5. 通俗易懂的join、left join、right join、full join、cross join

    内连接:列出与连接条件匹配的数据行(join\inner join) 外连接:两表合并,如有不相同的列,另外一个表显示null(left join\right join\full outer join ...

  6. iOS 播放系统自带铃声

    播放声音代码例子 https://github.com/baitongtong/git-.git 给一个国外网址,苹果系统铃声以及自定义铃声免登陆免费下载:http://www.zedge.net/r ...

  7. DDL 操作表结构

    DDL 操作表结构:CRUD 一.C(create)创建 1.创建表 create table 表名( 列名1 数据类型1, 列名2 数据类型2, 列名3 数据类型3, ... 列名n 数据类型n ) ...

  8. 用户在浏览器输入URL回车之后,浏览器都做了什么

    在直接列出执行的步骤之前先来普及几个知识,相信了解完这些知识之后会对前后端的交互有更深入的理解. 1.TCP连接 TCP:Transmission Control Protocol, 传输控制协议,是 ...

  9. java git .gitignore常用规则

    # Created by .ignore support plugin (hsz.mobi).gitignore # Operating System Files *.DS_Store Thumbs. ...

  10. 18,flask项目中使用celery

    导包: from celery import Celery from celery.result import AsyncResult app.config['CELERY_BROKER_URL'] ...