博主太懒,不想写题目描述了
思路:
首先可以发现最终的结果和操作顺序无关,因此可以从头开始操作,遇到1就操作一次,更新后面的值,但是如果每次更新后面的字符串时间消耗太大,因此可以用一个数组记录每个位置的数字被操作的次数,操作了偶数次相当于没有操作,根据操作次数和原本的数字可以判断当前的数字
于是~问题转换成了怎么记录操作次数
可以用差分区间的方法,对于每一个位置,如果是1,后面的数字都要反转,也就是后面的数字的操作次数加1,对应cnt[ i ]++,每次循环到一个新的位置时线计算前缀和(即当前位置的值),因为每次操作第一个可以保证第一个前面没有1,所以可以一边循环一边求差分数组的前缀和,时间复杂度线性
#include <bits/stdc++.h>
#define endl "\n"
using namespace std;
const int N = 100010;
char s[N];
int cnt[N], sum[N];
int main()
{
ios::sync_with_stdio(0);
int n;
cin >> n;
while (n--){
memset(cnt, 0, sizeof cnt);
memset(sum, 0, sizeof sum);
cin >> s;
int len = strlen(s);
int res = 0;
if(s[0] == '1'){
res++;
cnt[1]++;
cnt[len]--;
}
for (int i = 1; i < len; i++){
sum[i] = sum[i - 1] + cnt[i];
if(s[i] == '1' && sum[i] % 2 == 0){
res++;
cnt[i + 1]++;
cnt[len]--;
}
else if(s[i] == '0' && sum[i] % 2 == 1){
res++;
cnt[i + 1]++;
cnt[len]--;
}
}
if(res & 1)cout << "Yes\n";
else cout << "No\n";
}
return 0;
}