题目链接
https://codeforces.ml/contest/1504/problem/B
题目截图
题目大致描述
给定两个01串s与t,其中对s的任意前缀,当0的数量和1的数量相等时,即可进行翻转操作,即将0变成1,1变成0
问:s通过有限次以上操作能否转变成t
题解
这一场。。是一个悲伤的一场。。。我不仅在这场中由蓝降成了青。。而且这场是我打cf以来第一次也是唯一一次我爆零的一场。。。。
首先这场前三题全部是有关字符串的构造题(思维)
A题。。我没怎么多想。。。毕竟是签到题。。。所以就随便写了一个pretest过了就没管了。。。结果最后被fst(tle)了。。。赛后仔细看了一下。。A了
B题。。也就是这题。。。尽管A题我最后被fst了,但并未影响我比赛时的节奏以及情绪。。这题我调了好久。。一直WA。。WA到自闭了
其实我思路大体上是对的,分块贪心,用01相等的前缀来分块,对每一块判断判断st是否满足(即要么异或为0要么同或为0)
这有一个小错误。。。比如:00011 00110这个就不对。。
这个因为没有01相同前缀。。而我对这种情况没处理。。
之后我特判了一下这种情况。。。不过还是WA。。一直WA到自闭(当然途中我切了C的。。不过C也自闭了。。。最终整场下来我爆零了。。。。)
赛后看了一下测试数据然后明白了。。。
10001
01010
这种有一个前缀为可以翻转的。。但是后面却不相同的。。。。正确答案是NO。。而我是YES
只要比较一下后面部分两串是否相等。。。就AC了
再提一下其他的把,尽管这场我很惨。。不过学到了许多。。比如我这个错误数据是第518个。。。cf中是看不到这个数据的,但是我可以单纯将t == 10000且第518数据打印出来,这一就能显示这个数据了(又是一个菜鸡小技巧
然后就是我发现我每个数据都memset一遍时间为到998ms,而事实上没必要,去掉后只有几十ms了,因此以后能不memset就不memset!!!!!
代码如下
#pragma GCC optimize(2)
#include <bits/stdc++.h>
using namespace std;
#define IOS std::ios_base::sync_with_stdio(false), std::cin.tie(0), std::cout.tie(0);
typedef long long ll;
typedef unsigned long long ull;
const int mod = 1e9 + 7;
const int inf = 0x3f3f3f3f;
struct InputOutputStream {
enum { SIZE = 1000001 };
char ibuf[SIZE], *s, *t, obuf[SIZE], *oh;
bool eof;
InputOutputStream() : s(), t(), oh(obuf), eof(false) {}
~InputOutputStream() { fwrite(obuf, 1, oh - obuf, stdout); }
explicit operator bool() const {
return static_cast<bool>(eof == false);
}
inline char read() {
if (s == t) t = (s = ibuf) + fread(ibuf, 1, SIZE, stdin);
return s == t ? -1 : *s++;
}
inline InputOutputStream &operator>>(char* x) {
static char c;
for (c = read(); isspace(c); c = read())
if (c == -1) {eof = true; return *this;}
for (; !isspace(c); c = read()) *x = c, ++x;
*x = 0;
return *this;
}
template <typename T>
inline InputOutputStream &operator>>(T &x) {
static char c;
static bool iosig;
for (c = read(), iosig = false; !isdigit(c); c = read()) {
if (c == -1) {eof = true; return *this;}
iosig |= c == '-';
}
for (x = 0; isdigit(c); c = read()) x = x * 10 + (c ^ '0');
if (iosig) x = -x;
return *this;
}
inline void print(char c) {
if (oh == obuf + SIZE) {
fwrite(obuf, 1, SIZE, stdout);
oh = obuf;
}
*oh++ = c;
}
template <typename T>
inline void print(T x) {
static int buf[23], cnt;
if (x != 0) {
if (x < 0) print('-'), x = -x;
for (cnt = 0; x; x /= 10) buf[++cnt] = x % 10 | 48;
while (cnt) print((char)buf[cnt--]);
} else print('0');
}
template <typename T>
inline InputOutputStream &operator<<(const T &x) {
print(x);
return *this;
}
inline void print(const char* x) {
for(; *x; x++)
print(*x);
}
inline void print(char* x) {
for(; *x; x++)
print(*x);
}
} io;
#define cin io
#define cout io
const int maxn = 3e5 + 50;
int t;
int n;
char s1[maxn], s2[maxn];
int cnt1[maxn], cnt2[maxn];//count 1
int tmp[maxn], tot;
bool is_valid(int l, int r) {
if(s1[l] != s2[l]) {
for(int i = l;i <= r;++i) {
if(s1[i] == s2[i]) { return false; }
}
} else {
for(int i = l;i <= r;++i) {
if(s1[i] != s2[i]) { return false; }
}
}
return true;
}
signed main() {
cin >> t;
for(int _ = 1;_ <= t;++_) {
// memset(s1, 0, sizeof(s1));
// memset(s2, 0, sizeof(s2));
tot = 0;
cin >> n;
cin >> (s1 + 1);
cin >> (s2 + 1);
// if(_ == 518) {
// cout << (s1 + 1) << '\n';
// cout << (s2 + 1) << '\n';
// return 0;
// }
// if(t == 10000) { continue; }
cnt1[0] = cnt2[0] = 0;
for(int i = 1;i <= n;++i) {
cnt1[i] = cnt1[i-1] + (s1[i] == '1');
cnt2[i] = cnt2[i-1] + (s2[i] == '1');
}
if(cnt1[n] != cnt2[n]) {
cout << "NO\n";
continue;
}
for(int i = 2;i <= n;i += 2) {
if(cnt1[i] == i / 2) {
tmp[++tot] = i;
}
}
int pre = 1;
bool flag = true;
for(int i = 1;i <= tot;++i) {
int j = tmp[i];
// cout << "j: " << j << '\n';
if(!is_valid(pre, j)) {
flag = false;
break;
}
pre = j + 1;
}
if(strcmp(s1+pre, s2+pre) != 0) {
flag = false;
}
if(flag) {
cout << "YES\n";
} else {
cout << "NO\n";
}
}
return 0;
}
/*
1
5
10001
01010
*/