• 【每日一题】ABC155D - Pairs | 二分双指针 | 简单


    题目内容

    原题链接

    给定一个长度为 n n n 的整数数组 a a a

    选择两个不同的下标 i i i j j j ,乘积为 a i × a j a_i\times a_j ai×aj

    问在 n × ( n − 1 ) 2 \frac{n\times (n-1)}{2} 2n×(n1) 种不同的元素对中,第 k k k 小乘积是多少。

    数据范围

    • 2 ≤ n ≤ 2 × 1 0 5 2\leq n\leq 2\times 10^5 2n2×105
    • 1 ≤ k ≤ n × ( n − 1 ) 2 1\leq k\leq \frac{n\times (n-1)}{2} 1k2n×(n1)
    • − 1 0 9 ≤ a i ≤ 1 0 9 -10^9\leq a_i\leq 10^9 109ai109

    题解

    二分第 k k k 小乘积 m i d mid mid

    然后 c h e c k check check 是否有至少 k k k 个元素对的乘积小于等于 m i d mid mid

    c h e c k check check 中使用双指针来降低时间复杂度,如果在 c h e c k check check 中也使用二分,就得多一个 O ( log ⁡ n ) O(\log n) O(logn) 的复杂度。

    时间复杂度: O ( n log ⁡ n ) O(n\log n) O(nlogn)

    代码

    #include 
    using namespace std;
    
    typedef long long ll;
    
    int main()
    {
        int n;
        cin >> n;
    
        ll k;
        cin >> k;
    
        vector<int> pos, neg;
        ll zero = 0;
        for (int i = 0; i < n; ++i) {
            int x; cin >> x;
            if (x == 0) zero += 1;
            else if (x > 0) pos.push_back(x);
            else neg.push_back(x);
        }
    
        int nn = int(neg.size());
        int np = int(pos.size());
        zero = zero * (zero - 1) / 2 + zero * (nn + np);
    
        sort(pos.begin(), pos.end());
        sort(neg.begin(), neg.end(), greater<>());
    
        ll mul_neg = 1ll * nn * np;
        if (k <= mul_neg) {
            auto check = [&](ll mid) {
                // mul 为负数小于等于 mid 的
                // 考虑正数对应的所有负数即可,这块可以双指针
                // 枚举每个正数,找到对应的一个最大的负数,满足两数之积小于等于 mid
    
                ll cnt = k;
                for (int i = np - 1, j = 0; i >= 0; --i) {
                    while (j < nn && 1ll * pos[i] * neg[j] > mid) j += 1;
                    cnt -= (nn - j);
                }
    
                return cnt <= 0;
            };
    
            ll l = -1e18, r = -1;
            while (l < r) {
                ll mid = (l + r) >> 1;
                if (check(mid)) r = mid;
                else l = mid + 1;
            }
    
            cout << l << "\n";
        } else if (k <= mul_neg + zero) {
            cout << "0\n";
        } else {
            auto check = [&](ll mid) {
                // mul 为正数小于等于 mid 的
    
                ll cnt = k - mul_neg - zero;
                // 正数 * 正数
                for (int i = 0, j = np - 1; i < j; ++i) {
                    while (j >= 0 && 1ll * pos[i] * pos[j] > mid) j -= 1;
                    if (i < j) cnt -= j - i;
                }
    
                if (cnt <= 0) return true;
    
                // 负数 * 负数
                for (int i = 0, j = nn - 1; i < nn; ++i) {
                    while (j >= 0 && 1ll * neg[i] * neg[j] > mid) j -= 1;
                    if (i < j) cnt -= j - i;
                }
    
                return cnt <= 0;
            };
            ll l = 1, r = 1e18;
            while (l < r) {
                ll mid = (l + r) >> 1;
                if (check(mid)) r = mid;
                else l = mid + 1;
            }
            cout << l << "\n";
        }
    
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
  • 相关阅读:
    红米Note12Turbo解锁BL刷入PixelExperience原生ROM系统详细教程
    JVM 类的加载子系统
    双版本数据加载的系统设计
    一次logstash的实践解锁了如此多的玩法....
    软件常见设计模式
    数据库系统原理与应用教程(072)—— MySQL 练习题:操作题 121-130(十六):综合练习
    网站页脚展示备案号并在新标签页中打开超链接
    统计教程|PASS实现单因素二元Logistic回归分析且自变量为二分类的优势比检验的样本量估计
    1.mysql-DDL-数据库操作
    零基础解读ChatGPT:对人类未来工作是威胁还是帮助?
  • 原文地址:https://blog.csdn.net/weixin_43900869/article/details/132871367