zoukankan      html  css  js  c++  java
  • Codeforces Round #672 (Div. 2) D. Rescue Nibel!(排序)

    题目链接:https://codeforces.com/contest/1420/problem/D

    前言

    之前写过这场比赛的题解,不过感觉这一题还可以再单独拿出来好好捋一下思路。

    题意

    给出 $n$ 个闭区间,问 $k$ 个区间共区间共有多少种情况。

    题解一

    以区间为单位进行考虑,排序+优先队列。

    将所有区间以左端点为第一关键字,右端点为第二关键字从小到大排序,优先队列中存储不小于当前区间左端点的之前区间的右端点,每个区间对答案的贡献即 $C_{(pque.size(), k - 1)}$ 。

    代码

    #include <bits/stdc++.h>
    using namespace std;
    constexpr int N = 1e6 + 100;
    constexpr int MOD = 998244353;
    
    int fac[N], inv[N];
    
    int binpow(int a, int b) {
        int res = 1;
        while (b) {
            if (b & 1) res = 1LL * res * a % MOD;
            a = 1LL * a * a % MOD;
            b >>= 1;
        }
        return res;
    }
    
    long long C(int n, int m){
        if(m < 0 or m > n) return 0;
        return 1LL * fac[n] * inv[m] % MOD * inv[n - m] % MOD;
    }
    
    void Init(){
        fac[0] = 1;
        for (int i = 1; i < N; i++) fac[i] = 1LL * fac[i - 1] * i % MOD;
        inv[N - 1] = binpow(fac[N - 1], MOD - 2);
        for (int i = N - 2; i >= 0; i--) inv[i] = 1LL * inv[i + 1] * (i + 1) % MOD;
    }
    
    int main() {
        ios::sync_with_stdio(false);
        cin.tie(nullptr);
        
        Init();
        
        int n, k;
        cin >> n >> k;
        
        vector<pair<int, int>> seg(n);
        for (auto &[l, r] : seg) cin >> l >> r;
            
        sort(seg.begin(), seg.end());
        
        long long ans = 0;
        
        priority_queue<int, vector<int>, greater<int>> pque;
        
        for (int i = 0; i < n; i++) {
            auto [l, r] = seg[i];
            while (pque.size() and pque.top() < l) pque.pop();
            ans += C(pque.size(), k - 1);
            ans %= MOD;
            pque.push(r);
        }
        
        cout << ans << "
    ";
        
        return 0;
    }

    题解二

    以点为单位进行考虑,排序+离散化+差分。

    记录包含当前点 $i$ 的区间个数 $dif_i$ 和以当前点为左端点的区间个数 $bg_i$,将 $k$ 个区间视为两部分,从之前区间选出的部分和从以当前点为左端点的区间中选出的部分,即 $C_{(dif_i - bg_i, k-j)} imes C_{(bg_i, j)}$,为了去重 $j$ 的值从 $1$ 取起,值域为 $[1,min(k, bg_i)]$,每个点对答案的贡献为 $sum_{j = 1}^{min(k, bg_i)} limits C_{(dif_i - bg_i, k-j)} imes C_{(bg_i, j)}$ 。

    代码

    #include <bits/stdc++.h>
    using namespace std;
    constexpr int N = 1e6 + 100;
    constexpr int MOD = 998244353;
    
    int fac[N], inv[N];
    
    int binpow(int a, int b) {
        int res = 1;
        while (b) {
            if (b & 1) res = 1LL * res * a % MOD;
            a = 1LL * a * a % MOD;
            b >>= 1;
        }
        return res;
    }
    
    long long C(int n, int m){
        if(m < 0 or m > n) return 0;
        return 1LL * fac[n] * inv[m] % MOD * inv[n - m] % MOD;
    }
    
    void Init(){
        fac[0] = 1;
        for (int i = 1; i < N; i++) fac[i] = 1LL * fac[i - 1] * i % MOD;
        inv[N - 1] = binpow(fac[N - 1], MOD - 2);
        for (int i = N - 2; i >= 0; i--) inv[i] = 1LL * inv[i + 1] * (i + 1) % MOD;
    }
    
    int main() {
        ios::sync_with_stdio(false);
        cin.tie(nullptr);
        
        Init();
        
        int n, k;
        cin >> n >> k;
        
        vector<int> x(n), y(n);
        vector<int> disc;
        for (int i = 0; i < n; i++) {
            cin >> x[i] >> y[i];
            disc.push_back(x[i]);
            disc.push_back(y[i]);
        }
    
        sort(disc.begin(), disc.end());
        disc.resize(unique(disc.begin(), disc.end()) - disc.begin());
        
        vector<int> dif(disc.size() + 1), bg(disc.size() + 1);
        for (int i = 0; i < n; i++) {
            int l = lower_bound(disc.begin(), disc.end(), x[i]) - disc.begin();
            int r = lower_bound(disc.begin(), disc.end(), y[i]) - disc.begin();
            ++bg[l];
            ++dif[l];
            --dif[r + 1];
        }
        
        long long ans = 0;
        for (int i = 0; i < int(dif.size()); i++) {
            if (i > 0) dif[i] += dif[i - 1];
            for (int j = 1; j <= min(k, bg[i]); j++) {
                ans += C(dif[i] - bg[i], k - j) * C(bg[i], j);
                ans %= MOD;
            }
        }
        cout << ans << "
    ";
        
        return 0;
    }
  • 相关阅读:
    暂停公告
    【laravel】Laravel 5 TokenMismatchException on PHP 5.6.9
    【laravel】laravel class 里面定义以head开头的方法会报错
    【kindle】【转发】kindle链接WIFI自动断开问题
    【js】window.onscroll 无效问题
    【js】【转发】jreturn;、return true、return false;区别
    【js】【vue】获取当前dom层
    【js】input 焦点到内容的最后
    【jquery】 选中复选框 和 return false 的影响
    【jquery】 form ajaxSubmit 问题
  • 原文地址:https://www.cnblogs.com/Kanoon/p/13775659.html
Copyright © 2011-2022 走看看