zoukankan      html  css  js  c++  java
  • [COI2007] [luogu P1823] Patrik 音乐会的等待 解题报告 (单调栈)

    题目链接:https://www.luogu.org/problemnew/show/P1823

    题目:

    N个人正在排队进入一个音乐会。人们等得很无聊,于是他们开始转来转去,想在队伍里寻找自己的熟人。

    队列中任意两个人A和B,如果他们是相邻或他们之间没有人比A或B高,那么他们是可以互相看得见的。

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

    题解:

    我们发现,其实就是算每个人向前看能看到多少个人之和对吧?

    发现如果1号既比2号,又比2号靠后,后面的人就不可能看得到2号

    于是我们考虑维护一个单调递减的栈,在不含重复大小元素的情况下,发现弹出的元素的数目就可以直接累加进ans里,特判一下如果这个时候还有元素在栈里那么显然也是看得到的,ans++

    但是怎么处理重复的元素呢?我们考虑把重复的元素合并起来一起处理,具体实现就是开个pair,first记录高度,second记录人数

    luogu上别忘了开long long

    #include<algorithm>
    #include<cstring>
    #include<cstdio>
    #include<iostream>
    typedef long long ll;
    
    using std::pair;
    const int N=5e5+15;
    int n,r;
    ll ans;
    ll a[N];
    pair <int,int> q[N];
    inline ll read()
    {
        char ch=getchar();
        ll s=0,f=1;
        while (ch<'0'||ch>'9') {if (ch=='-') f=-1;ch=getchar();}
        while (ch>='0'&&ch<='9') {s=(s<<3)+(s<<1)+ch-'0';ch=getchar();}
        return s*f;
    }
    int main()
    {
        n=read();
        for (int i=1;i<=n;i++) a[i]=read();
        for (int i=1;i<=n;i++)
        {
            pair <int,int> p(a[i],1);
            while (r&&q[r].first<=a[i]) 
            {
                ans+=q[r].second;
                if (q[r].first==a[i]) p.second+=q[r].second;
                r--;
            }
            if (r) ans++;
            q[++r]=p;
        }
        printf("%lld
    ",ans);
        return 0;
    }
  • 相关阅读:
    Leetcode-645 Set Mismatch
    2017百度软研(C++)
    二叉树中任意两个节点的最近公共祖先
    不用加减乘除做加法
    一些leetcode算法题
    Leetcode 98. Validate Binary Search Tree
    C++ 通过ostringstream 实现任意类型转string
    Leetcode 215. Kth Largest Element in an Array
    382. Linked List Random Node
    一些基础函数的实现
  • 原文地址:https://www.cnblogs.com/xxzh/p/9680936.html
Copyright © 2011-2022 走看看