zoukankan      html  css  js  c++  java
  • [JXOI2018]排序问题

    题目

    大模拟

    显然这个期望次数是(frac{(n+m)!}{prod a_i!})(a_i)表示第(i)个数出现的次数,我们要最大化这个值只需要最小化(prod a_i!)就好了

    要加入(m)个范围在([l,r])的数,肯定不会影响在原序列里出现过的且不属于([l,r])的数的出现次数,这个直接算就好了

    我们有(r-l+1)个数可以加入,一个贪心是我们先加入出现次数最少的数,正确性显然

    于是用小根堆维护一下就有(50pts)

    我们可以把每一种数的出现次数搞出来,再用一个桶表示出现次数为(i)的有多少种数,这样可以转化成一个类似区间覆盖的东西,之后就没有了

    离散化写跪调了一上午,std::unique竟然会改变原数列

    代码

    #include <bits/stdc++.h>
    #include <tr1/unordered_map>
    using namespace std::tr1;
    #define re register
    #define max(a, b) ((a) > (b) ? (a) : (b))
    const int mod = 998244353;
    const int maxn = 2e5 + 5;
    const int maxM = 1e7 + 2e5 + 5;
    inline int read() {
        char c = getchar();
        int x = 0;
        while (c < '0' || c > '9') c = getchar();
        while (c >= '0' && c <= '9') x = (x << 3) + (x << 1) + c - 48, c = getchar();
        return x;
    }
    inline int ksm(int a, int b) {
        int S = 1;
        for (; b; b >>= 1, a = 1ll * a * a % mod)
            if (b & 1) S = 1ll * S * a % mod;
        return S;
    }
    int n, m, l, r, sz, tot, T, U;
    unordered_map<int, int> ma;
    std::vector<int> v[maxn >> 1];
    int tax[maxn], a[maxn], b[maxn], c[maxn];
    int ifac[maxM], fac[maxM];
    int N[maxn >> 1], M[maxn >> 1], L[maxn >> 1], R[maxn >> 1];
    inline int find(int x) {
        int lx = 1, ry = sz;
        while (lx <= ry) {
            int mid = lx + ry >> 1;
            if (c[mid] == x)
                return mid;
            if (c[mid] < x)
                lx = mid + 1;
            else
                ry = mid - 1;
        }
        return 0;
    }
    int main() {
        T = read();
        fac[0] = ifac[0] = 1;
        for (re int i = 1; i <= T; i++) {
            N[i] = read(), M[i] = read(), L[i] = read(), R[i] = read(), U = max(U, N[i] + M[i]);
            for (re int j = 0; j < N[i]; j++) v[i].push_back(read());
        }
        for (re int i = 1; i <= U; i++) fac[i] = 1ll * fac[i - 1] * i % mod;
        ifac[U] = ksm(fac[U], mod - 2);
        for (re int i = U - 1; i; --i) ifac[i] = 1ll * ifac[i + 1] * (i + 1) % mod;
        for (re int t = 1; t <= T; t++) {
            tot = 0, n = N[t], m = M[t], l = L[t], r = R[t];
            int ans = fac[n + m];
            for (re int i = 0; i < n; i++)
                if (v[t][i] < l || v[t][i] > r)
                    ma[v[t][i]]++;
                else c[++tot] = v[t][i];
            for (re int i = 0; i < n; i++) {
                if (v[t][i] >= l && v[t][i] <= r) continue;
                ans = 1ll * ans * ifac[ma[v[t][i]]] % mod;
                ma[v[t][i]] = 0;
            }
            std::sort(c + 1, c + tot + 1);
            for (re int i = 1; i <= tot; i++) a[i] = c[i];
            sz = std::unique(c + 1, c + tot + 1) - c - 1;
            for (re int i = 1; i <= tot; i++) tax[a[i] = find(a[i])]++;
            for (re int i = 1; i <= sz; i++) b[tax[i]]++, tax[i] = 0;
            int res = r - l + 1 - sz, now = 0, g = 1;
            for (re int i = 1; i <= tot; i++) g = 1ll * g * ksm(fac[i], b[i]) % mod;
            for (re int i = 1; i <= tot; i++) {
                if (!b[i]) continue;
                if (1ll * (i - now) * res > m) {
                    int k = m / res;
                    g = 1ll * g * ksm(1ll * fac[now + k] * ifac[now] % mod, res) % mod;
                    g = 1ll * g * ksm(k + now + 1, m % res) % mod;
                    m = 0; break;
                }
                m -= (i - now) * res;
                g = 1ll * g * ksm(1ll * fac[i] * ifac[now] % mod, res) % mod;
                res += b[i]; now = i;
            }
            if (m) {
                int k = m / res;
                g = 1ll * g * ksm(1ll * fac[now + k] * ifac[now] % mod, res) % mod;
                g = 1ll * g * ksm(k + now + 1, m % res) % mod;
            }
            for (re int i = 1; i <= tot; i++) b[i] = 0;
            printf("%d
    ", 1ll * ans * ksm(g, mod - 2) % mod);
        }
    }
    
    
  • 相关阅读:
    linux shell创建目录、遍历子目录
    linux shell写入单行、多行内容到文件
    如何起个好名字
    linux shell编程中的数组定义、遍历
    详解浏览器分段请求基础——Range,助你了解断点续传基础
    实现一个大文件上传和断点续传
    localStorage设置过期时间
    Python3 __slots__
    Nginx 流量统计分析
    argparse简要用法总结
  • 原文地址:https://www.cnblogs.com/asuldb/p/11294458.html
Copyright © 2011-2022 走看看