音乐会的等待
题目描述
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;
}

浙公网安备 33010602011771号