诺诺的队列
题目描述
诺诺表现、成绩双优,于是校长给她一笔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 }