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;
    }
    
    
  • 相关阅读:
    [BZOJ1565][NOI2009]植物大战僵尸
    [BZOJ1566][NOI2009]管道取珠
    [BZOJ4104][Thu Summer Camp 2015]解密运算
    [BZOJ1003][ZJOI2006]物流运输
    [BZOJ3790]神奇项链
    指纹模块原理_光学指纹模块原理
    Ubuntu 16.04无损分区大小调整工具Gparted
    16进制转换10进制
    Memory Ordering in Modern Microprocessors
    python 多态
  • 原文地址:https://www.cnblogs.com/mollnn/p/14406131.html
Copyright © 2011-2022 走看看