专栏文章
题解:P11794 [JOI 2016 Final] 集邮比赛 2 / Collecting Stamps 2
P11794题解参与者 2已保存评论 1
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 1 条
- 当前快照
- 1 份
- 快照标识符
- @mip8wg6j
- 此快照首次捕获于
- 2025/12/03 08:04 3 个月前
- 此快照最后确认于
- 2025/12/03 08:04 3 个月前
思路
预处理
首先先算出最初的个数,固定枚举
JOI 中间的 O,然后在 O 的前面统计枚举 J,后面统计枚举 I,然后根据乘法原理相乘然后再根据假发原理将每个 O 的情况个数再相加即可。也就是: 和 ,然后再计算 。
增加字符
分为三种情况
- 插入
O:O必须在J和I两个字符之间才有贡献,做法和预处理类似,都是用乘法原理,找到个数最多的那个, 也就是cnt = max(cnt, totj[i] * toti[i+1])。 - 插入
J:只有在它之后的字符可以与它组合,于是将它放到最前,再计算枚举每个O能搭配的情况个数,相加,即cnt1 += toti[i]。 - 插入
I:同插入J,只需插到最后面。
AC代码
CPP#include<bits/stdc++.h>
using namespace std;
long long toti[100005]/*I的情况*/, totj[100005]/*J的情况*/;
int main()
{
long long n, cnt = 0, cnt1 = 0, cnt2 = 0, ans = 0;
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
string s;
cin >> n >> s;
for(int i = 1; i <= n; i++)
{
totj[i] = totj[i - 1];
if(s[i - 1] == 'J')
totj[i]++;
}
for(int i = n; i >= 1; i--)
{
toti[i] = toti[i + 1];
if(s[i - 1] == 'I')
toti[i]++;
}
for(int i = 1; i <= n; i++)
{
if(s[i - 1] == 'O')
{
ans += totj[i] * toti[i];
}
}
//插入O
for(int i = 1; i < n; i++)
{
cnt = max(cnt, totj[i] * toti[i+1]);
}
//插入J
for(int i = 1; i <= n; i++)
{
if(s[i - 1] == 'O')
{
cnt1 += toti[i];
}
}
//插入I
for(int i = 1; i <= n; i++)
{
if(s[i - 1] == 'O')
{
cnt2 += totj[i];
}
}
cnt = max({cnt, cnt1, cnt2}); //比较求最大的
ans += cnt;
cout << ans << endl;
return 0;
}
相关推荐
评论
共 1 条评论,欢迎与作者交流。
正在加载评论...