这是一个很菜的 Oier 的博客|

Hanx16Msgr

园龄:2年8个月粉丝:12关注:3

CF1612G Max Sum Array

Max Sum Array

Luogu CF1612G

题面描述

  • 给定一个长为 m 的序列 c1,c2,,cm
  • 序列 A 满足:对于所有 1imiA 中出现了 ci 次。
  • 定义一个序列 A 的值如下:

f(A)=1i<jn,ai=ajji

  • 求满足条件的 f(A) 的最大值,及在取最大值时有多少种序列 A
  • 1m5×105,1ci106

Solution

分开讨论每一种颜色。

假设一个颜色出现的位置为 p1,p2,p3,,pn。拆一下贡献的式子,发现对于一个位置 pi,它最后会对答案造成 (2in1)pi 的贡献。由于每个颜色出现的次数固定,因此所有的系数也是固定的,所以只需要找到一种 p 的分配方案使得答案最小即可。不难发现 p 只需要按照系数的大小关系分配,系数大的 p 也分配大的位置即可。

对于方案的求法,当两个位置的系数相等的时候,这两个位置一定可以交换且不影响答案。所以记 cnti 表示系数为 i 的位置个数,那么最后的方案数应当为 cnti!

如果直接按照上面的做法做,时间复杂度是 O(m2) 的。发现每一个颜色对系数桶的贡献其实相当于是一个步长为 2 的区间加,那么直接使用差分快速维护系数桶即可。

时间复杂度 O(m)

Code
int N, cnt[_N];
mint fac[_N];
void init(int n) {
    fac[0] = 1; For(i, 1, n) fac[i] = fac[i-1] * i;
}
signed main() {
    cin.tie(0)->sync_with_stdio(0);
    cin >> N; init(M);
    For(i, 1, N) {
        int x; cin >> x;
        ++cnt[M-x], --cnt[M+x];
    }
    i64 sum = 0;
    mint ans = 0, tot = 1;
    auto calc = [](i64 l, i64 r)->mint {
        return (l + r) * (r - l + 1) / 2 % mod;
    };
    For(i, 2, M << 1) {
        cnt[i] += cnt[i-2];
        ans += calc(sum + 1, sum + cnt[i]) * (mint(i) - M + 1);
        tot *= fac[cnt[i]];
        sum += cnt[i];
    }
    cout << ans << ' ' << tot << '\n';
}
posted @   Hanx16Msgr  阅读(6)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起