QOJ #10331. Shuffle and Max Bracket Score 题解

Description

对于一个长度为 2n2n 的序列 b1,b2,,b2nb_1,b_2,\ldots,b_{2n},定义 ti=1t_i=1 表示第 ii 个位置是左括号,否则为右括号。序列的权值为满足这个括号序列合法的条件下,biti\sum b_it_i 的最大值。

现在给一个序列 a1,a2,,a2na_1,a_2,\ldots,a_{2n},问将其随机打乱的期望权值。

998244353998244353 取模。

n105n\leq 10^5

Solution

先考虑怎么求一个给定序列的权值。

pip_i 表示第 ii 个左括号的位置,那么如果所有 pip_i 都不超过 2i12i-1 则这个序列一定合法,容易证明这是充要条件。

现在就可以得到一个贪心做法:从前往后枚举序列的每一个数,每次将 aia_i 加到大根堆里,如果 ii 是奇数则弹出大根堆堆顶元素,弹出的就是选择左括号的位置。


考虑怎么求期望。

上面那个东西还是过于复杂,不适合计数。

套路性地,先对序列进行离散化,对于每个 aia_i,将 ai\geq a_i 的看成 11<ai<a_i 的看成 00,就转化为了 0101 问题。

现在变为对于每个 ss,求有 ss112ns2n-s00 的期望权值,设其为 f(s)f(s)

容易发现最后被选到的 11 一定是一段前缀,所以可以用 Hall 定理的思想,没有选到的 11 的个数为:所有后缀中 aia_i 之和减需要进行匹配的位置的个数的最大值。写成式子:

ans=smaxk{si=1kai2nk2}=mink{i=1kai+2nk2}=n+mink{i=1kai+k2}=n+mink{i=1k(2ai1)2}\begin{aligned} ans&=s-\max_{k}{\left\{s-\sum_{i=1}^{k}{a_i}-\left\lfloor\frac{2n-k}{2}\right\rfloor\right\}}\\ &=\min_{k}{\left\{\sum_{i=1}^{k}{a_i}+\left\lfloor\frac{2n-k}{2}\right\rfloor\right\}}\\ &=n+\min_{k}{\left\{\sum_{i=1}^{k}{a_i}+\left\lfloor\frac{-k}{2}\right\rfloor\right\}}\\ &=n+\min_{k}{\left\{\left\lfloor\frac{\sum_{i=1}^{k}{(2a_i-1)}}{2}\right\rfloor\right\}} \end{aligned}

上面转化为了求 2ai12a_i-1 的最小前缀和,而这个东西的值域是 {1,1}\{1,-1\},就是括号匹配的那个东西!

g(s,t)g(s,t) 表示有 ss11,答案不小于 tt 的方案数,推一下式子容易得到 g(s,t)=(2ns)(2n2ts1)\displaystyle g(s,t)=\binom{2n}{s}-\binom{2n}{2t-s-1}

所以 f(s)=t=0min{s,n}[(2ns)(2n2ts1)]\displaystyle f(s)=\sum_{t=0}^{\min\{s,n\}}{\left[\binom{2n}{s}-\binom{2n}{2t-s-1}\right]},维护一下奇偶的组合数前缀和即可。

时间复杂度:O(n)O(n)

Code

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
#include <bits/stdc++.h>

// #define int int64_t

const int kMaxN = 2e5 + 5, kMod = 998244353;

int n;
int a[kMaxN], p[kMaxN], fac[kMaxN], ifac[kMaxN], sum[kMaxN], f[kMaxN];

int qpow(int bs, int64_t idx = kMod - 2) {
int ret = 1;
for (; idx; idx >>= 1, bs = (int64_t)bs * bs % kMod)
if (idx & 1)
ret = (int64_t)ret * bs % kMod;
return ret;
}

inline int add(int x, int y) { return (x + y >= kMod ? x + y - kMod : x + y); }
inline int sub(int x, int y) { return (x >= y ? x - y : x - y + kMod); }
inline void inc(int &x, int y) { (x += y) >= kMod ? x -= kMod : x; }
inline void dec(int &x, int y) { (x -= y) < 0 ? x += kMod : x; }

int C(int m, int n) {
if (m < n || m < 0 || n < 0) return 0;
return 1ll * fac[m] * ifac[n] % kMod * ifac[m - n] % kMod;
}

void prework() {
fac[0] = 1;
for (int i = 1; i <= 2 * n; ++i) fac[i] = 1ll * i * fac[i - 1] % kMod;
ifac[2 * n] = qpow(fac[2 * n]);
for (int i = 2 * n; i; --i) ifac[i - 1] = 1ll * i * ifac[i] % kMod;
}

void dickdreamer() {
std::cin >> n;
for (int i = 1; i <= 2 * n; ++i) std::cin >> a[i];
std::sort(a + 1, a + 1 + 2 * n);
prework();
int ans = 0;
for (int i = 0; i <= 2 * n; ++i)
sum[i] = add(C(2 * n, i), i <= 1 ? 0 : sum[i - 2]);
for (int i = 1; i <= 2 * n; ++i) {
int lim = std::min(i, n);
f[i] = 1ll * lim * C(2 * n, i) % kMod;
if (2 * lim - i - 1 >= 0) dec(f[i], sum[2 * lim - i - 1]);
}
for (int i = 1; i <= 2 * n; ++i)
inc(ans, 1ll * (a[i] - a[i - 1]) * f[2 * n - i + 1] % kMod * fac[i - 1] % kMod * fac[2 * n - i + 1] % kMod);
std::cout << 1ll * ans * ifac[2 * n] % kMod << '\n';
}

int32_t main() {
#ifdef ORZXKR
freopen("in.txt", "r", stdin);
freopen("out.txt", "w", stdout);
#endif
std::ios::sync_with_stdio(0), std::cin.tie(0), std::cout.tie(0);
int T = 1;
// std::cin >> T;
while (T--) dickdreamer();
// std::cerr << 1.0 * clock() / CLOCKS_PER_SEC << "s\n";
return 0;
}

QOJ #10331. Shuffle and Max Bracket Score 题解
https://sobaliuziao.github.io/2025/04/23/post/f0721c20.html
作者
Egg_laying_master
发布于
2025年4月23日
许可协议