【题解】JOIOIの塔

JOIOI の塔 题解

题目描述

有一长度为 N N N 的字符串,只由 JOI 组成。现在,你可以按从前到后顺序选择三个字母,使他们组成的字符串为 JOIIOI,但是字母不可以被选择两次。你需要求出最多可以选取几个这样的字符串。

解析

我们发现答案符合单调性:如果可以拼出 n n n 个字符串,那一定可以拼出 n − 1 n-1 n1 个字符串。我们利用这个进行二分,那我们只需判断是否可以拼出 m i d mid mid 个字符串即可。

由于 JOIIOI 后缀相同,想到从后往前遍历字符串,将每个字符放在原有的字符串前面或者将 I 字符作为一个新的字符串,这样每个完整字符串的形成过程就是 I->OI->IOII->OI->JOI。令 c n t 1 cnt1 cnt1 表示现成的 I 字符串个数, c n t 2 cnt2 cnt2 表示现成的 OI 字符串个数, c n t 3 cnt3 cnt3 表示现成的 IOI/JOI 字符串个数。于是,对于每个 J,将一个 OI 变为 JOI;对于每个 O,将一个 I 变为 OI;对于每个 I,需要分开考虑:若目前的字符串个数( c n t 1 + c n t 2 + c n t 3 cnt1+cnt2+cnt3 cnt1+cnt2+cnt3)已经达到了最终的需求( m i d mid mid),则无需新建一个字符串 I,如果没有到达,那就新建一个 I 的字符串。

例如:判断 JOIOII 能否拼出一个字符串。
JOIOI[I]{"I"};(目前字符串个数小于需求,所以新建)
JOIO[II]{"I"};(目前字符串个数达到需求,无需新建,那这个字符串就不需要了)
JOI[OII]{"OI"};(对于 O 只需将其加在 I 的前面)
JO[IOII]{"IOI"};(字符串个数到达需求,无需新建;目前已有 OI 字符串,所以加在它的前面就好了);已有的字符串个数达到需求,直接返回结果:JOIOI 可以拼出一个字符串。

代码

#include <bits/stdc++.h>
#define int long long
using namespace std;
inline int read(){
	int s = 0, w = 1;
	char ch = getchar();
	for(; ch < '0' || ch > '9'; w *= ch == '-' ? -1 : 1, ch = getchar());
	for(; ch >= '0' && ch <= '9'; s = 10 * s + ch - '0', ch = getchar());
	return s * w;
}
const int MAXN = 1000005;
int N;
string s;
bool check(int x){
	int tot = 0, one, two;
	one = two = 0;
	for(int i = N; i >= 1; i--){
		if(s[i - 1] == 'J'){
			if(two != 0) two--, tot++;
		} else if (s[i - 1] == 'O'){
			if(one != 0) one--, two++;
		} else if (s[i - 1] == 'I'){
			if(one + two + tot >= x && two){
				two--, tot++;
			} else {
				one++;
			}
		}
	}
	return tot >= x;
}
signed main(){
	cin >> N >> s;
	int l = 0, r = N, mid;
	while(l < r){
		mid = (l + r + 1) >> 1;
		if(check(mid)){
			l = mid;
		} else {
			r = mid - 1;
		}
	}
	cout << l << endl;
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值