zoukankan      html  css  js  c++  java
  • [CF5E] Bindian Signalizing

    [CF5E] Bindian Signalizing - 单调栈

    Description

    给定一个环,环上 n 座山,若连接两座山的两个弧中有任何一个上没有比两座山更高的山,那么这两座山可以互相看见彼此。现在给定 n 座山的高度,求能够看见彼此信号的山的数量。

    Solution

    对于 x,y,如果 x!=y 我们用小的去统计大的,如果 x=y 我们把能相互看见的放在一起统计

    设最高的山为 a0,也是 an,其余按顺序旋转排列

    现在显然 0 和 n 可以看见所有的山

    我们求出每个数前面第一个严格大于它的和右边第一个严格大于它的,位置分别记为 l,r,那么只要这两个存在,就会贡献一个 2

    同时,考虑每个数和他右边第一个更大数之前的所有等大的数的贡献,假设有 c 个,那么这个数还贡献一个 c

    但需要注意,如果 l,r 找不到,那么贡献直接记为 n-1

    求 l,r 直接用单调栈即可,维护一个不严格单调递增的栈,每个元素被弹出时,记录一下它是被谁弹出的,这个家伙就是第一个严格比他大的

    求 c,在弹栈的过程中用一个计数维护一下

    #include <bits/stdc++.h>
    using namespace std;
    
    #define int long long
    
    const int N = 1000005;
    
    int n, a[N], b[N], s[N], top, l[N], r[N], c[N];
    
    signed main()
    {
        ios::sync_with_stdio(false);
        cin >> n;
        for (int i = 1; i <= n; i++)
            cin >> b[i];
        int maxpos = max_element(b + 1, b + n + 1) - b;
        for (int i = 0; i <= n; i++)
            a[i] = b[(maxpos + i - 1) % n + 1];
        top = 0;
        int last_pop = -1, last_pop_count = 0;
        for (int i = 0; i <= n; i++)
        {
            while (top && a[i] > a[s[top]])
            {
                if (last_pop == a[s[top]])
                    ++last_pop_count;
                else
                    last_pop_count = 0, last_pop = a[s[top]];
                c[s[top]] = last_pop_count;
                r[s[top]] = i, --top;
            }
            s[++top] = i;
            if (a[i] != last_pop)
                last_pop = -1, last_pop_count = 0;
        }
        while (top)
        {
            if (last_pop == a[s[top]])
                ++last_pop_count;
            else
                last_pop_count = 0, last_pop = a[s[top]];
            c[s[top]] = last_pop_count;
            r[s[top]] = -1, --top;
        }
        top = 0;
        for (int i = n; i >= 0; i--)
        {
            while (top && a[i] > a[s[top]])
            {
    
                l[s[top]] = i, --top;
            }
            s[++top] = i;
        }
        while (top)
            l[s[top]] = -1, --top;
        // for (int i = 0; i <= n; i++)
        //     cout << a[i] << " ";
        // cout << endl;
        // for (int i = 0; i <= n; i++)
        //     cout << l[i] << " ";
        // cout << endl;
        // for (int i = 0; i <= n; i++)
        //     cout << r[i] << " ";
        // cout << endl;
        // for (int i = 0; i <= n; i++)
        //     cout << c[i] << " ";
        // cout << endl;
    
        c[0] = 0;
    
        int ans = 0;
        for (int i = 0; i < n; i++)
        {
            if (a[i] < a[0])
            {
                ans += 2;
                if (l[i] == 0 && r[i] == n)
                    ans--;
            }
            ans += c[i];
        }
        cout << ans << endl;
    }
    
    
  • 相关阅读:
    CAFFE安装(3):cuDNN v4
    监测查询性能(1)
    SQL Server 中的三种分页方式
    使用DBCC SHOW_STATISTICS展示索引的统计信息
    查询表的分配单元数据
    Node.js中的事件
    node-mysql中的连接池代码学习
    Excel动态生成JSON
    使用SignalR实现比特币价格实时刷新
    使用Async同步执行异步函数
  • 原文地址:https://www.cnblogs.com/mollnn/p/14406131.html
Copyright © 2011-2022 走看看