zoukankan      html  css  js  c++  java
  • 51Nod 1686 第K大区间(二分,尺取,离散化)

    题目链接
      首先提一下第一句很重要,定义一个区间的值为其众数出现的#次数#,区间的值是次数而不是众数的值。这是一道经典的二分判定答案的题,如果从正面想的话不太好做,确实感觉无从下手,但是可以考虑一下判定答案,毕竟,判定比求解要简单。
      因为(n leq 1e5)所以,答案的范围就是(1)(n)之间的一个数,如果用二分的话花费的时间是很可观的。但是这样又有了一个新的问题:如何判定每个解是否正确?如果把所有区间都列出来的话,时间复杂度至少也得有(n^2),还是会TLE。对于一个区间来说,如果区间第(k)大的数是我们要判定的一个解的话,如果把这个区间向左向右扩展,那么得到的区间第(k)大一定大于等于我们判定的解,这时,如果枚举每一个区间的最左端点,肯定存在一个右端点,以这个端点左端点做起点,终点大于等于右端点的区间的第(k)大肯定都会大于判定的解。所以,我们通过枚举左端点,找到各个右端点满足条件的最小值,就能在(O(n))的时间之内计算出所有区间的值大于等于要判定的解的区间数,只要这个区间数等于或者大于(大于是一种特殊情况,比如所有区间众数的次数都一样就是大于),那么就可能有解。
      但是还有一个问题,就是计算区间的众数。这里很容易想到开一个数组来计算每个数出现的次数,然后和判定的解比较。但是题目中的数字较大,直接开数组来计算是不现实的。所以可以考虑用(map)容器来计算(但是可能会卡常),也可以用离散化(因为我们只关心每个数之间的大小关系,并不关心它的值),时间复杂度会小一点。综上所述,所有的操作时间复杂度加起来一共是(O(nlogn))

    const int maxn = 1e5+10;
    int n, k, arr[maxn], tmp[maxn], cnt[maxn];
    bool checker(int num) {
        ll sum = 0;
        int l = 0;
        zero(cnt);
        for (int i = 0; i<n; ++i) {
            ++cnt[arr[i]];
            while(cnt[arr[i]]>=num) {
                sum += n-i;
                --cnt[arr[l]];
                ++l;
            }
        }
        return sum >= k;
    }
    int main(void) {
        scanf("%d%d", &n, &k);
        for (int i = 0; i<n; ++i) {
            scanf("%d", &arr[i]);
            tmp[i] = arr[i];
        }
        sort(tmp, tmp+n);
        int p = unique(tmp, tmp+n)-tmp;
        for (int i = 0; i<n; ++i) 
            arr[i] = lower_bound(tmp, tmp+p, arr[i])-tmp;
        int l = 1, r = n;
        while(l<=r) {
            int mid = (l+r)>>1;
            if (checker(mid)) l = mid+1;
            else  r = mid-1;
        }
        printf("%d
    ", r);
        return 0;   
    }
    
  • 相关阅读:
    448. Find All Numbers Disappeared in an Array
    447. Number of Boomerangs
    441. Arranging Coins
    438. Find All Anagrams in a String
    437. Path Sum III
    434. Number of Segments in a String
    422. Valid Word Square
    415. Add Strings
    414. Third Maximum Number
    [codility]Array-closest-ascenders
  • 原文地址:https://www.cnblogs.com/shuitiangong/p/12718491.html
Copyright © 2011-2022 走看看