LG11794
首先考虑如何求出原串中 JOI 的出现次数。不难想到以 O 为中心,将左边 J 与右边 I 的数量相乘再累加起来即可。同样,我们可以运用类似的思路分析插入的字母对答案的影响。当插入 J 时,增加的贡献即为每个 O 后面 I 的出现次数的和(注意是每个),此时显然在最前面插入最优。同理,插入 I 时,增加的贡献即为每个 O 前面 J 的出现次数的和,在最后面插入最优。插入 O 时,则与最开始的计算方式相同。三种情况取最大值即可。时间复杂度 \(O(n)\)。
#include <iostream>
#include <cstdio>
#define ll long long
#define N 200010
using namespace std;
int n,a[N];
ll c1,c2,c3,s1[N],s2[N],s3[N],ans,mx1,mx2,mx3;
string s;
int main()
{
ios::sync_with_stdio( false );
cin.tie( 0 );
cout.tie( 0 );
cin >> n;
cin >> s;
for( int i = 1 ; i <= n ; i ++ )
{
if( s[i - 1] == 'J' ) a[i] = 1;
if( s[i - 1] == 'O' ) a[i] = 2;
if( s[i - 1] == 'I' ) a[i] = 3,c3 ++;
}
for( int i = 1 ; i <= n ; i ++ )
{
if( a[i] == 1 ) c1 ++;
if( a[i] == 3 ) c3 --;
if( a[i] == 2 )
{
s1[i] = c1;
s3[i] = c3;
ans += c1 * c3;
}
mx2 = max( mx2 , c1 * c3 );
}
for( int i = 1 ; i <= n + 1 ; i ++ )
s1[i] += s1[i - 1],mx1 = max( mx1 , s1[i] );
for( int i = n + 1 ; i >= 1 ; i -- )
s3[i] += s3[i + 1],mx3 = max( mx3 , s3[i] );
cout << ans + max( max( mx1 , mx3 ) , mx2 );
return 0;
}

浙公网安备 33010602011771号