音乐会的等待

题目描述

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

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

输入输出格式

输入格式

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

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

输出格式

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

输入输出样例

输入样例

7
2
4
1
2
2
5
1

输出样例

10

题解

单调栈的入门题

代码

#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;

const int MAXN=500050;
class MyStack
{
public:
	MyStack():p(0){memset(stack,0,sizeof(stack));}
	bool empty(){return p<=0;}
	void push(int x){stack[++p]=x;}
	void pop(){--p;}
	int top(){return stack[p];}
	int size(){return p;}
	int get(int x){return stack[x];}
private:
	int stack[MAXN];
	int p;
};

int read()
{
	int x=0,f=1;
	char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
	return x*f;
}

int main()
{
	int n=read(),ans=0;
	MyStack S;
	S.push(read());
	for(int i=2;i<=n;++i)
	{
		int temp=read();
		if(temp<S.top())
		{
			S.push(temp);
			++ans;
		}
		else
		{
			int L=1,R=S.size(),mid=0;
			while(L<R)
			{
				mid=(L+R)>>1;
				if(mid==R-1)
					mid=R;
				if(S.get(mid)>temp)
					L=mid;
				else
					R=mid-1;
			}
			ans+=S.size()-L+1;
			while(!S.empty()&&S.top()<temp)
				S.pop();
			S.push(temp);
		}
	}
	cout<<ans<<'\n';
	return 0;
}
posted @ 2017-04-15 19:04  dustbin  阅读(211)  评论(0)    收藏  举报