题目描述
A
, B
からなる長さ N+1 の文字列 S = S0⋯ SN が与えられます. 各 k=1, …, N に対して次の問題を解いてください:
Alice と Bob が集合 X を使ってゲームをします.X ははじめ空集合で,t=1,…, k の順に次の行動を行います.
- t が奇数ならば,Alice が非負整数 x を選び,X を X∪ {x} に置き換える.
- t が偶数ならば,Bob が非負整数 x を選び,X を X∪ {x} に置き換える.
k 回すべての行動が終わった時点での mex(X) を x とするとき,文字 Sx が
A
ならば Alice が,Sx がB
ならば Bob が勝者となります.集合 X の要素数は k 以下であるため,x = mex(X) ≤ k が成り立つ(したがって文字 Sx が存在する)ことに注意してください.両者が最適に行動した場合の勝者の名前を出力してください.
mex(X) とは? 非負整数からなる有限集合 X に対し,x∈/ X を満たす最小の非負整数 x を mex(X) と定義します.
输入格式
入力は以下の形式で標準入力から与えられます.
N S
输出格式
N 行出力してください.i 行目には,k=i とした場合のゲームについて,両者が最適に行動した場合の勝者の名前(Alice
または Bob
)を出力してください.
题意翻译
给定一个长度为 (n+1)(1≤n≤2×105) 的字符串 s。共 n 轮游戏,第 i 轮进行 i 次操作,每轮均由 Alice
先,与 Bob
交替往集合 X 中加入非负整数(一次加入即一次操作)。对于每一轮,记 x=mex(X),若 sx 为 A 则 Alice
胜,反之 Bob
胜。对于每一轮,输出谁胜。
题解
由于Alice和Bob总会采取最优策略,可知到Alice的回合时,Alice会将位置靠前且未被加入过集合中的字符串中'B'的下标加入集合中,Bob同理,所以这道题就变成了比较A和B出现的次数,如果A多,则Alice赢,反之,则Bob赢。
#include <iostream>
using namespace std;
int cnt[200005];
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int n;
cin>>n;
string S;
cin>>S;
int opA=0,opB=0;
int cnt_a=0;
for(int i=0;i<=n;i++){
if(S[i]=='A')cnt_a++;
cnt[i]=cnt_a;
}
for(int i=1;i<=n;i++){
if(i%2)opA++;
else opB++;
if(opB>=cnt[i])cout<<"Bob";
else cout<<"Alice";
cout<<endl;
}
return 0;
}
-
输入部分:
- 首先输入一个整数
n
表示字符串S
的长度。 - 然后输入字符串
S
。
- 首先输入一个整数
-
计数数组:
cnt
数组用来记录截至到每个位置 'A' 的数量。即cnt[i]
表示字符串S
前i
个字符中 'A' 的个数。
-
遍历字符串:
- 首先通过一个循环计算每个位置的 'A' 的数量,更新
cnt
数组。
- 首先通过一个循环计算每个位置的 'A' 的数量,更新
-
判断胜者:
- 使用两个变量
opA
和opB
分别代表当前轮次 "Alice" 和 "Bob" 的机会。 - 然后通过第二个循环,从
1
到n
,每次判断当前机会的数量与cnt
数组的值进行比较:- 若 "Bob" 的机会数量
opB
大于或等于截至到当前轮的 'A' 数量cnt[i]
,则输出 "Bob"。 - 否则输出 "Alice"。
- 若 "Bob" 的机会数量
- 使用两个变量