P11794 题解
日本人怎么出这么简单的题,建议降橙。
首先考虑如果不插入的话,怎么计算数量。
根据乘法原理,显然答案是 \(\sum_{i=1}^n{[s_i=O](\sum_{j=1}^{i-1}{[s_i=J]})(\sum_{j=i+1}^{n}{[s_i=I]})}\)
这东西用前缀和优化一下是线性的。
接下来考虑插入字符。
因为要让 JOI 尽可能的多,所以选择添加的字符一定在 J、O、I 当中。
我们枚举插入的位置。
假设在第 \(i\) 个字符的后面插入了一个字符 \(c\)。
如果 \(c=J\),根据刚才的式子,和原字符串相比,增加了 \(\sum_{j=i+1}^n{[s_j=O](\sum_{k=j+1}^n{[s_k=I]})}\)。
如果 \(c=O\),增加了 \((\sum_{j=1}^{i-1}{[s_i=J]})(\sum_{j=i+1}^{n}{[s_i=I]})\)。
如果 \(c=I\),增加了 \(\sum_{j=1}^i{[s_j=O](\sum_{k=1}^{j-1}[s_k=J])}\)。
这些东西用一堆前缀和优化一下就好了。
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
const ll mod = 1e9 + 7;
const int N = 200005;
const int INF = 0x3f3f3f3f;
int totj[N], toto[N], toti[N];
char a[N];
int main() {
int n;
scanf("%d%s", &n, a + 1);
for (int i = 1; i <= n; i++) {
totj[i] = totj[i - 1] + (a[i] == 'J');
toto[i] = toto[i - 1] + (a[i] == 'O');
toti[i] = toti[i - 1] + (a[i] == 'I');
}
ll tot = 0;
for (int i = 1; i <= n; i++) {
if (a[i] == 'O') {
tot += totj[i - 1] * (toti[n] - toti[i]);
}
}
ll ans = tot;
for (int i = 0; i <= n; i++) {
ll cntj = 0;
for (int j = i + 1; j <= n; j++) {
if (a[j] == 'O') cntj += toti[n] - toti[j];
}
ll cnto = totj[i] * (toti[n] - toti[i]);
ll cnti = 0;
for (int j = 1; j <= i; j++) {
if (a[j] == 'O') cnti += totj[j - 1];
}
ans = max(ans, tot + cntj);
ans = max(ans, tot + cnto);
ans = max(ans, tot + cnti);
}
printf("%lld\n", ans);
return 0;
}

浙公网安备 33010602011771号