📅  最后修改于: 2023-12-03 14:50:07.308000             🧑  作者: Mango
“MEX 前缀数组和”是指一个数组的前缀中,MEX(Minimum excluded number)最大的值与该前缀的数组和的和。现给定一个长度为 $n$ 的正整数排列,求具有最大 MEX 前缀数组和的排列的个数。
我们可以设 $f_i$ 为以 $i$ 结尾的具有最大 MEX 前缀数组和的数组的排列计数,那么我们可以考虑当将一个数 $x$ 插入到排列前面时,对答案的影响为:
$$f_i = \sum_{j=1}^{p-1}f_j + \sum_{j=p+1}^{i} (a_j \geq a_p) \times a_j + x$$
其中 $\sum_{j=p+1}^{i} (a_j \geq a_p) \times a_j$ 表示将 $[p+1,i]$ 中大于 $x$ 的数插入到 $p$ 的位置所导致的影响。
综上,我们考虑枚举 $x$,再枚举 $p$,根据 $x$ 与 $f_{i-1}$ 的大小关系确定 $f_i$ 的值即可。时间复杂度 $\mathcal{O}(n^2)$。
当然,我们可以通过维护 $f_1,f_2,\cdots,f_{i-1}$ 的最值来消去枚举 $p$ 的部分,这样时间复杂度就被优化到了 $\mathcal{O}(n \log_2 n)$,但此处不再阐述。
MOD = 998244353
n = int(input())
a = [int(x) for x in input().split()]
f = [0] * (n + 1)
sum_ = [0] * (n + 1)
for i in range(1, n+1):
sum_[i] = sum_[i-1] + i
ans = 0
for x in range(1, n+1):
rev = [i for i in range(n) if a[i] >= x]
dp = [0] * (n-rev[0]) # f_1, f_2, ..., f_{p-1}
s = sum(a[i] for i in rev)
for i in range(rev[0], n):
if a[i] < x:
continue
j = bisect_right(rev, i)
p = rev[j-1]
if a[p] < x:
continue
if j == 1:
dp[j-1] = sum_[i-1] + x
else:
k = j-2
while k >= 0 and rev[k] >= p:
k -= 1
val = (dp[k] + s - sum(a[i] for i in rev[k+1:j])) % MOD
dp[j-1] = val + sum_[i-1] + x
ans = (ans + dp[j-1]) % MOD
print(ans)