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;
    }
  • 相关阅读:
    使用golang访问kubebernetes
    使用 Rancher 管理现有 Kubernetes 集群
    Running powershell scripts during nuget package installation and removal
    How to Create, Use, and Debug .NET application Crash Dumps in 2019
    寻找写代码感觉(一)之使用 Spring Boot 快速搭建项目
    Selenium+Java之解决org.openqa.selenium.InvalidArgumentException: invalid argument报错问题
    Selenium环境搭建
    关于Xpath定位方法知道这些基本够用
    Web自动化之浏览器启动
    【翻译】编写代码注释的最佳实践
  • 原文地址:https://www.cnblogs.com/Kanoon/p/13775659.html
Copyright © 2011-2022 走看看