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 尽可能的多,所以选择添加的字符一定在 JOI 当中。

我们枚举插入的位置。

假设在第 \(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;
}

posted @ 2025-03-19 10:33  jxy2012  阅读(26)  评论(1)    收藏  举报
//雪花飘落效果