牛客多校3 J题
题意:
B
O
2
b
−
1
BO 2b-1
BO2b−1套
B
O
2
a
−
1
BO 2a-1
BO2a−1赛制,内部是
B
O
2
a
−
1
BO 2a-1
BO2a−1赛制,外部是
B
O
2
b
−
1
BO 2b-1
BO2b−1赛制,给定
n
n
n长度的
01
01
01串,
0
0
0表示输,
1
1
1表示赢。问从
i
i
i位置开始,不断循环完整的该字符串结果,问最终每个位置
i
i
i开始比赛时,整个比赛的最终结果是
1
1
1还是
0
0
0
题解:
先考虑从
i
i
i位置开始的内部的
B
O
2
a
−
1
BO 2a - 1
BO2a−1赛制结果,显然利用双指针,左端表示开始的位置,右端表示从开始的位置比赛后的内部赛的结果的位置,当左端点向右移动时,我们需要移动右端点直到比赛比出胜负,然后初始化倍增数组,将开始位置向右跳一步到比出胜负的下一步的过程设置为
f
[
i
]
[
0
]
=
j
f[i][0] = j
f[i][0]=j,同时用一个二维
s
u
m
sum
sum数组表示倍增过程中的胜负的次数统计。
然后再用
f
[
i
]
[
0
]
,
s
u
m
[
i
]
[
0
]
f[i][0],sum[i][0]
f[i][0],sum[i][0]表示出所有的
f
[
n
]
[
20
]
,
s
u
m
[
n
]
[
20
]
f[n][20],sum[n][20]
f[n][20],sum[n][20]状态,最后从每个
i
i
i开始,贪心向右跳,如果要跳的步数小于等于外部赛制的最大局数
2
∗
b
−
1
2*b - 1
2∗b−1,那么就跳,同时统计
s
u
m
sum
sum中赢的场次。最后比较胜利的场次是否大于等于
b
b
b即可。
#include<bits/stdc++.h>
using namespace std;
#define endl '\n'
#define int long long
#define debug(p) for(auto i : p)cerr << i << " "; cerr << endl;
#define debugs(p) for(auto i : p)cerr << i.first << " " << i.second << endl;
typedef pair<int, int> pll;
string yes = "YES";
string no = "NO";
constexpr int N = 1e5 + 7;
int f[N][22];
int sum[N][22];
void solve()
{
int n, a, b;
cin >> n >> a >> b;
string s;
cin >> s;
int cnt[2] = {0, 0};
for (int i = 0, j = 0; i < n; i++)
{
while(cnt[0] < a && cnt[1] < a)
{
cnt[s[j] - '0']++;
j = (j + 1) % n;
}
f[i][0] = j;
sum[i][0] = (cnt[1] > cnt[0]);
cnt[s[i] - '0']--;
}
for (int i = 1; i < 20; i++)
{
for (int j = 0; j < n; j++)
{
sum[j][i] = sum[j][i - 1] + sum[f[j][i - 1]][i - 1];
f[j][i] = f[f[j][i - 1]][i - 1];
}
}
for (int i = 0; i < n; i++)
{
int win = 0, pos = i, rest = 0;
for (int j = 19; j >= 0; j--)
{
if(rest + (1ll << j) <= 2 * b - 1)
{
rest += (1ll << j);
win += sum[pos][j];
pos = f[pos][j];
}
}
if(win >= b)cout << 1;
else cout << 0;
}
cout << endl;
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
int T = 1;
// cin >> T;
while(T--)
{
solve();
}
}