D. Multiplication Table

https://codeforces.com/problemset/problem/448/D

题意:n*m矩阵,对应位置的数值是行列下标相乘,求排序后第k个元素数值。

思路:元素值最大是n * m, 最小是1,在这个范围内2分,统计出所有比当前数值x(二分值)小的数的数量cnt,如果cnt<k,那么x有可能是第k个值,要将二分的左边界右移。

总结:cnt < k 是个比较难理解的点。cnt < k 说明比x小的数不到k个,那么x也有可能是第cnt + 1~k - 1个数,所以需要将左边界右移。
还有个难理解的点是如何统计出比x小的数的数量。一开始想的是按斜线遍历,但是很复杂感觉无法实现。正解应该是按行遍历,因为x已知,行号i已知,则可以求出最大j,j值就是该行中小于x的值的数量(如果j>m,那么j=m)

感觉也算是经典模板题了,矩阵上第k大二分

void solve(){
    long long n, m;
    cin >> n >> m;

    long long k;
    cin >> k;

    auto valid = [&](long long x){
        long long cnt = 0;
        for (int i = 1; i <= n; ++i){
            cnt += min(m, (x - 1) / i);
        }
        return cnt < k;
    };

    long long l = 1, r = n * m;
    while (l < r){
        long long mid = (l + r + 1) >> 1;
        if (valid(mid)){
            l = mid;
        }
        else{
            r = mid - 1;
        }
    }

    cout << l << endl;
}
posted @ 2024-04-30 10:04  _Yxc  阅读(9)  评论(0编辑  收藏  举报