诺诺的队列

题目描述

诺诺表现、成绩双优,于是校长给她一笔money,让她去外地玩玩。由于本地没有飞机场,所以诺诺只能坐火车去咯。所以诺诺今天去火车站买票,却看到了N多人在火车站里啊,诺诺一阵头晕。机灵的她突然发现,有N个人在队伍里(和上文的N毫无关系- -||),人们等得很无聊,于是他们开始转来转去,想在队伍里寻找自己的熟人。队列中任意两个人A和B,如果他们是相邻或他们之间没有人比A或B高,那么他们是可以互相看得见的。
诺诺想计算出有多少对人可以互相看见,那么你能帮帮诺诺吗?

本题数据范围:
40%的测试数据:N≤10000;
80%的测试数据:N≤100000;
100%的测试数据:N≤500000。

输入格式

输入的第一行包含一个整数N (1≤N≤500 000), 表示队伍中共有N个人;
接下来的N行中,每行包含一个整数,表示人的高度,人的高度<10000。

输出格式

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

 

 

 

第一道单调队列题目。二分优化。

 1 #include<iostream>
 2 #include<stdio.h>
 3 //#include<fstream>
 4 using namespace std;
 5 //ifstream fin("cin.in");
 6 
 7 int n,h[500005],Q[500005];
 8 long long ans=0;
 9 
10 int main()
11 {
12     scanf("%d",&n);
13     
14     for(int i=1;i<=n;++i)
15     scanf("%d",&h[i]);
16     
17     int tail=1;
18     Q[1]=1;
19     
20     for(int i=2;i<=n;++i)
21     {
22       if(h[i]<h[Q[tail]]) {Q[++tail]=i;ans++;} 
23       else 
24       {
25         int l=1,r=tail,mid;
26         while(l<r)
27         {
28           mid=(l+r)>>1;
29           if(r==l+1) mid=r;
30           if(h[Q[mid]]>h[i]) l=mid;
31           else r=mid-1;
32                    }
33         
34         ans+=tail-l+1;
35         while(tail>=1&&h[Q[tail]]<h[i]) tail--;
36         tail++;
37         Q[tail]=i;
38         
39            }
40             }
41     
42     cout<<ans<<endl;
43     return 0;
44     
45     }
posted on 2012-08-20 21:12  怡红公子  阅读(425)  评论(0编辑  收藏  举报