PTA 7-1 单调栈

题目

N人们排队等着参加音乐会。人们等得很无聊,于是他们转身去排队寻找熟悉的人。
如果两个人A和B并排站在一起,或者如果他们中间没有人比A或B高,那么他们可以看到对方。

编写一个程序,确定可以看到彼此的成对人数。

输入格式:

第一行输入包含一个整数N(1≤N≤500000),排队的人数。

以下N行中的每一行都包含一个整数,即一个人的身高(以纳米为单位)。

每个人的身高都将小于231纳米。高度是按照人们排队的顺序给出的。

输出格式:

输出可以看到对方的成对人数

  • 输入样例:
7
2
4
1
2
2
5
1
  • 输出样例:
10

代码

#include<iostream>
using namespace std;
int st[500010],n,top=1,m;
typedef long long LL;
LL ans;
int main()
{
    cin>>n;
    int a;
    cin>>st[1];
    for(int i=2;i<=n;i++)
    {
        cin>>a;
        if(st[top]>a)
        {
            top++,ans++,st[top]=a;
        }
        else
        {
            int l=1,r=top;
            while(l<r)
            {
                m=(l+r)>>1;
                if(r==l+1)m=r;
                if(a>=st[m])r=m-1;
                else l=m;
            }
            ans+=top-l+1;
            while(top>0&&st[top]<a)top--;
            st[++top]=a;
        }
    }
    cout<<ans;
}

分析

这道题考察单调栈。

首先分析题目要求,求互相看见人的对数,避免重复,我们选择一种方向进行解答,本解使用从前往后。

继续分析,我们任取一人,这个人所能看见最远的人就是前一个比他高的人,并且这个人高于前面的人,那么他后面的人肯定是无法看到前面的人的。

我们再思考用什么数据结构能维持这个性质,单调栈。

之后我们在往栈插入元素时考虑两点:

第一点往前找到第一个比他大的数

第二点是删除所有比他小的数(再也无法与后续数据产生关联,使用二分实现)

最后即可得出结果

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值