• 牛客编程巅峰赛S1第8场


    牛客编程巅峰赛S1第8场 - 王者 C-最大最小 (ST表+双指针)

    链接:https://ac.nowcoder.com/acm/contest/6778/C
    来源:牛客网

    题目描述

    牛妹有一个数组array,她想知道里面有多少个区间满足区间最大值大于等于区间最小值的两倍。

    输入:

    给定Array数组$ 1≤array.size≤10^5,1 leq array.size leq 10{5},1≤array.size≤105( ) 1≤array[i]≤1091 leq array[i] leq 10^{9}1≤array[i]≤109 $

    输出:

    返回满足条件的区间个数

    思路:

    先用ST表(O(n*logn))预处理一下,之后可以(O(1))查询区间最值。

    然后我们枚举区间的左端点(mathit L)

    对于每一个(mathit L),我们只需要找到一个最小的右端点(mathit R),使其(2 imessum_{i=L}^{i=R}min(a_i)leqsum_{i=L}^{i=R}max(a_i))

    那么所有以(mathit L)为左端点的区间中,当右端点大于等于(mathit R)时就满足条件,所以贡献为(n-R+1)

    把所有的左端点区间的贡献加起来就是总答案。

    代码:

    class Solution {
    public:
        /**
         *
         * @param array int整型一维数组 array
         * @param arrayLen int array数组长度
         * @return long长整型
         */
        int a[100010];
        int l[100010];
        int r[100010];
        int st1[100010][25];//st表
        int st2[100010][25];//st表
    
        void init(int n)
        {
            for (int i = 0; i < n; i++)
            {
                st1[i][0] = a[i + 1];
                st2[i][0] = a[i + 1];
            }
            for (int i = 1; (1 << i) <= n; i++)
            {
                for (int j = 0; j + (1 << i) - 1 < n; j++)
                {
                    st1[j][i] = max(st1[j][i - 1], st1[j + (1 << (i - 1))][i - 1]);
                    st2[j][i] = min(st2[j][i - 1], st2[j + (1 << (i - 1))][i - 1]);
                }
            }
        }
    
        int querysmax(int l, int r)
        {
            l--;
            r--;
            int k = (int)(log((double)(r - l + 1)) / log(2.0));
            return max(st1[l][k], st1[r - (1 << k) + 1][k]);
        }
    
        int queryemin(int l, int r)
        {
            l--;
            r--;
            int k = (int)(log((double)(r - l + 1)) / log(2.0));
            return min(st2[l][k], st2[r - (1 << k) + 1][k]);
        }
    
        long long MaxMin(int* array, int arrayLen) {
            // write code here
            int n = arrayLen;
            for (int i = 1; i <= n; ++i)
            {
                a[i] = array[i - 1];
            }
            init(n);
            long long ans = 0ll;
            int l = 1;
            int r = 1;
            for (l = 1; l <= n; ++l)
            {
                while (r < n && 1ll * queryemin(l, r) * 2 > querysmax(l, r))
                {
                    r++;
                }
                if (1ll * queryemin(l, r) * 2 <= querysmax(l, r))
                {
                    ans += (n - r + 1);
                }
            }
            return ans;
        }
    };
    
    本博客为本人原创,如需转载,请必须声明博客的源地址。 本人博客地址为:www.cnblogs.com/qieqiemin/ 希望所写的文章对您有帮助。
  • 相关阅读:
    [linux]CentOS防火墙
    [工具]VIM键位
    [mac]mac 终端 常用命令
    [数据结构]“堆”,"栈","堆栈","队列"的区别
    [java]Java构造方法与析构方法
    [环境]Eclipse安装WindowBuilder
    [BZOJ 1441]Min(裴蜀定理)
    [BZOJ 4563][Haoi2016]放棋子(错排公式)
    [BZOJ 4517][Sdoi2016]排列计数(组合数学/错排公式)
    [BZOJ 3680]吊打XXX(模拟退火)
  • 原文地址:https://www.cnblogs.com/qieqiemin/p/13418298.html
Copyright © 2020-2023  润新知