题解:CF1458D Flip and Reverse
520 表白出题人,真的是非常好的 Ad-Hoc,令我原地升天。
- 选择一个满足
01 个数相同的子区间。 - 将这个区间
flip。 - 再翻转区间。
一般遇到这种诡异的操作都考虑找一找不变的量和变化了的量。
-
- 记一个
s_0=0 ,然后s_{1\sim n} 表示这个前缀和序列。那么我们会发现,操作区间[l,r] 相当于翻转s_{l\sim r-1} 。操作的时候需要满足s_{l-1}=s_r 。
这时候我们容易想到一个牛逼的建模:将
因为可以任意地翻转欧拉回路,所以就相当于,环的访问顺序可以是任意的。这时候,任意欧拉回路就会代表在最终字符串(经过操作的)中可能出现的一个子串,保证一一对应。
那么最终的字符串可以表示为由
复杂度
constexpr tp N = 1e6 + 8, K = 5e5 + 2;
tp n;
string s;
array<array<tp, 2>, N> e;
tp HARUTO() {
cin >> s, n = s.size(), s = ' ' + s;
tp u = 0;
//for (tp i = 0; i <= n + K; ++i) e[i][0] = e[i][1] = 0;
for (tp i = 1; i <= n; ++i) {
e[u + K][s[i] - '0']++;
u += s[i] == '0' ? -1 : 1;
}
u = 0;
for (tp i = 1; i <= n; ++i) {
if (e[u + K][0] && e[u - 1 + K][1]) cout << '0', e[u + K][0]--, u--;
else if (e[u + K][1]) cout << '1', e[u + K][1]--, u++;
else cout << '0', e[u + K][0]--, u--;
}
cout << "\n";
return 0;
}
int main() {
QWQ();
tp t = 1; cin >> t;
while (t--) HARUTO();
return 0;
}