CF1705D-Mark and Lightbulbs
题目大意:给定两个仅由01组成的字符串s, t
。可以对s
做出如下“操作”:取s
中一个左右两边的字符互不相同的字符,将该字符翻转。问至少需要对s
进行多少次“操作”可以将s
变为t
。如果不能变则输出-1
。
首先,s
的第一个字符跟最后一个字符都不能改变,需要与t
对应位置的字符相等。
注意到:不论如何进行操作,s
中为01
、10
的子串的数目总是不变的。所以t
首先需要满足01
、10
子串的数目跟s
中的相等。通过试验可以发现,通过对相邻字符的连续操作可以实现把01
、10
子串移动到想要的位置,需要的操作次数为原位置与目标位置的位值之差。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49
| #include <bits/stdc++.h> #define int long long using namespace std; char s[200005], t[200005]; int as[200005], at[200005]; signed main() { int _, n, i, j; scanf("%lld", &_); while (_--) { scanf("%lld", &n); scanf("%s%s", s + 1, t + 1); if (s[1] != t[1] || s[n] != t[n]) { printf("-1\n"); continue; } int sums = 0, sumt = 0; for (i = 1; i < n; i++) { as[i] = (s[i] != s[i + 1]); at[i] = (t[i] != t[i + 1]); sums += as[i]; sumt += at[i]; } if (sums != sumt) { printf("-1\n"); continue; } int res = 0; for (i = j = 1; i < n; i++) { if (at[i]) { for (;; j++) { if (as[j]) break; } res += llabs(j - i); j++; } } printf("%lld\n", res); } return 0; }
|