JOI2013 JOIOI の塔 (Tower of JOIOI)题解
Description
给定一个由 J、O、I 组成的字符串,求最多能拆分成多少 JOI 或 IOI。
对于所有数据,\(1\leq \vert S\vert\leq 10^6\)。
Solution
先处理出 \(\text{pre}_i\) 为前缀 J 和 I 的数量,即能组成多少个头部。
然后倒着做,维护当前拼出的 I、OI 和最终成品的数量。遇到 J、O 就模拟拼接,遇到 I 判断当前的 \(\text{pre}_i\) 是否小于等于 I、OI 的总数量,若成立就拼成 IOI,否则作为 I。
判断这个是因为 I 可以作为最后的 I 也可以作为开头的 I。若大于等于前缀 J、I 数量则作为最后的 I 数量够用,无需继续拼接了。
时间复杂度 \(\mathcal{O}(n)\)。
Code
#include <bits/stdc++.h>
using namespace std;
namespace Milkcat {
const int N = 2e7 + 5;
int n, ow, w, tot, pre[N]; char s[N];
int main() {
cin >> n >> (s + 1);
for (int i = 1; i <= n; i ++)
pre[i] = pre[i - 1] + (s[i] == 'J' || s[i] == 'I');
for (int i = n; i >= 1; i --) {
if (s[i] == 'J' && ow) ow --, tot ++;
if (s[i] == 'O' && w) w --, ow ++;
if (s[i] == 'I') {
if (ow + w >= pre[i] && ow) ow --, tot ++;
else w ++;
}
}
cout << tot << '\n';
return 0;
}
}
int main() {
ios::sync_with_stdio(0);
cin.tie(0), cout.tie(0);
int T = 1;
while (T --) Milkcat::main();
return 0;
}
/*
15
NNOWWOONONWOWWO
*/

浙公网安备 33010602011771号