Codeforces Round #782 (Div. 2 )B. Bit Flipping

B. Bit Flipping

time limit per test

1 second

memory limit per test

256 megabytes

You are given a binary string of length n. You have exactly k moves. In one move, you must select a single bit. The state of all bits except that bit will get flipped (0 becomes 1, 1 becomes 0). You need to output the lexicographically largest string that you can get after using all k moves. Also, output the number of times you will select each bit. If there are multiple ways to do this, you may output any of them.

A binary string a is lexicographically larger than a binary string b of the same length, if and only if the following holds:

  • in the first position where a and b differ, the string a contains a 1, and the string b contains a 0.

Input

The first line contains a single integer t ( 1 ≤ t ≤ 1000 ) (1 \le t \le 1000) (1t1000) — the number of test cases.

Each test case has two lines. The first line has two integers n and k ( 1 ≤ n ≤ 2 ⋅ 1 0 5 ; 0 ≤ k ≤ 1 0 9 ) (1 \leq n \leq 2 \cdot 10^5; 0 \leq k \leq 10^9) (1n2105;0k109).

The second line has a binary string of length n, each character is either 0 or 1.

The sum of n over all test cases does not exceed 2 ⋅ 1 0 5 2 \cdot 10^5 2105.

Output

For each test case, output two lines.

The first line should contain the lexicographically largest string you can obtain.

The second line should contain n integers f 1 f_1 f1, f 2 f_2 f2, … \ldots , f n f_n fn, where f i f_i fi is the number of times the i − t h i-th ith bit is selected. The sum of all the integers must be equal to k.

Example

input

Copy

6
6 3
100001
6 4
100011
6 0
000000
6 1
111001
6 11
101100
6 12
001110

output

Copy

111110
1 0 0 2 0 0 
111110
0 1 1 1 0 1 
000000
0 0 0 0 0 0 
100110
1 0 0 0 0 0 
111111
1 2 1 3 0 4 
111110
1 1 4 2 0 4

Note

Here is the explanation for the first testcase. Each step shows how the binary string changes in a move.

  • Choose bit 1: 1 ‾ 00001 → 1 ‾ 11110. \color{red}{\underline{1}00001} \rightarrow \color{red}{\underline{1}}\color{blue}{11110}. 100001111110.
  • Choose bit 4: 111 1 ‾ 10 → 000 1 ‾ 01. \color{red}{111\underline{1}10} \rightarrow \color{blue}{000}\color{red}{\underline{1}}\color{blue}{01}. 111110000101.
  • Choose bit 4:$ \color{red}{000\underline{1}01} \rightarrow \color{blue}{111}\color{red}{\underline{1}}\color{blue}{10}.$

The final string is 111110 111110 111110 and this is the lexicographically largest string we can get.

Let’s see how many times a given bit will get flipped. Clearly, a bit gets flipped whenever it is not selected in an operation. Therefore, the i-th bit gets flipped k-f_i times. We want to select a bit as few times as possible. Now we can handle a few cases.

  1. k is even, bit i is 1 ⇒ f i = 0 \Rightarrow f_i=0 fi=0 (even number of flips don’t change the bit)
  2. k is even, bit i is 0 ⇒ f i = 1 \Rightarrow f_i=1 fi=1 (odd number of flips toggle the bit from 0 to 1)
  3. k is odd, bit i is 1 ⇒ f i = 1 \Rightarrow f_i=1 fi=1 (even number of flips don’t change the bit)
  4. k is odd, bit i is 0 ⇒ f i = 0 \Rightarrow f_i=0 fi=0 (odd number of flips toggle the bit from 0 to 1)

Process the string from left to right until you can’t anymore. If you still have some remaining moves at the end, you can just give them all to the last bit. Then you can construct the final string by checking the parity of k-f_i.

Time complexity: O ( n ) \mathcal{O}(n) O(n)

分析

需要让字典序最大,那么我们就要让前面尽量是1,所以我们从头开始目的就是让前面的1保留同时让0变成1.

我们可以看出一个规律,如果偶数次操作,最终会变回原来的样子,如果奇数次操作,那么最后就会反过来。所以我们要利用不变的次数,让一些位置操作数变少。如果总的操作数为奇数没那么最后就会让0变成1,1变成0,所以从头到尾遍历的时候,就要遇到1就要使用一次不变次数,让他最后保持为1,如果前面都能保持为1了,那么就全部都放在最后一位,是什么就看剩下的操作数了。

#include <cstring>
#include <iostream>
#include <vector>
using namespace std;
int a[100000];
int main() {
    cin.tie(0);
    cout.tie(0);
    ios::sync_with_stdio(0);
    int n;
    cin >> n;
    int len, t;
    while (n--) {
        cin >> len >> t;
        string s;
        vector<int> f(len, 0);
        cin >> s;
        int tmpt = t;
        for (int i = 0; i < len && tmpt > 0; i++) {
            if (t % 2 == 0) {
                if (s[i] == '0') {
                    f[i] = 1;
                    tmpt--;
                }
            } else if (t % 2 == 1) {
                if (s[i] == '1') {
                    f[i] = 1;
                    tmpt--;
                }
            }
        }
        f[len - 1] += tmpt;
        for (int i = 0; i < len; i++) {
            if (f[i] % 2 == 1) {
                if (t % 2 == 0) {
                    s[i] = (s[i] == '0') ? '1' : '0';
                }
            }
            if (f[i] % 2 == 0) {
                if (t % 2 == 1) {
                    s[i] = (s[i] == '0') ? '1' : '0';
                }
            }
        }
        cout << s << '\n';
        for (auto i : f) {
            cout << i << " ";
        }
        cout << '\n';
    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值