2023“钉耙编程”中国大学生算法设计超级联赛2--Binary Number

Problem Description

Markyyz is learning binary numbers. There is an easy problem in his homework.

You are given a binary number s1∼n (s1 is the highest bit. sn is the lowest bit.). You need to do an operation exactly k times: select an interval [l,r] (1≤l≤r≤n) arbitrarily and flip sl,sl+1,...,sr, in other word, for all i∈[l,r], si becomes 1 if si is 0, si becomes 0 if si is 1. What is the biggest result binary number after the k operations.

Markyyz found useless algorithms useless on the problem, so he asked SPY for help. SPY looked down on the problem but finally got WA (wrong answer). Can you help them to find the right solution?

Input

The first line of the input contains a single integer T (1≤T≤6×10^4), indicating the number of test cases.

In each test case:

The first line contains two integers n,k. (1≤n≤10^5,0≤k≤10^18)

The second line contains a binary number s1∼n. (s1=1, ∀i∈[2,n]:si∈{0,1})

It's guarenteed that in all test cases, ∑n≤2.5×10^6

Output

You need to print a string of length n in one line, representing the biggest binary number after the k operations.

Sample Input

2
8 2
10100101
5 233333333333333333
11101

Sample Output

11111101
11111

题意:给定长度为n的01串,你需要操作刚好k次,每次你可以把[L,R]区间中的01反转(0变1,1变0),目的是尽可能使得01串的值最大,输出最后的01串。

解析:分情况讨论,设m为连续0的区间个数,如果k>=m,那么肯定是能变成全1,因为多出来的操作次数,当01串长度>1,不管奇偶,你都可以反转抵消,例如有奇数次,[1,2]区间,你可以先[1,1],[2,2],[1,2]。如果k<m,那么就贪心选择前k个0区间变为1即可。然后特判一下初始全1的情况和长度为1的情况即可。

#include <bits/stdc++.h>
using namespace std;
const int N=1e5+5;
typedef long long ll;
typedef pair<int,int> PII;
char a[N];
void solve()
{
    ll n,k;
    scanf("%lld%lld%s",&n,&k,a+1);
    vector<PII> v;//存每个连续0的区间左右端点
    int l,r,flag=0;
    for(int i=1;i<=n;i++)
    {
        if(a[i]=='0')
        {
            if(!flag) l=i,flag=1;
            r=i;
        }
        else if(flag)
        {
            v.push_back({l,r});
            flag=0;
        }
    }
    if(flag) v.push_back({l,r});
    int m=v.size();//连续0的区间个数
    if(n==1)//如果长度只有1
    {
        if(k%2)//奇数得反转一次
        {
            if(a[n]=='0') a[n]='1';
            else a[n]='0';
        }
        printf("%s\n",a+1);
        return;
    }
    if(m==0&&k==1)//全1的情况
    {
        a[n]='0';
        printf("%s\n",a+1);
        return;
    }
    if(k>=m)//修改次数>连续0的区间个数,可以变为全1
    {
        for(int i=0;i<m;i++)
        {
            int l=v[i].first;
            int r=v[i].second;
            for(int j=l;j<=r;j++) a[j]='1';
        }
    }else
    {
        for(int i=0;i<k;i++)//把前k个区间改为1
        {
            int l=v[i].first;
            int r=v[i].second;
            for(int j=l;j<=r;j++) a[j]='1';
        }
    }
    printf("%s\n",a+1);
    return;
}
int main()
{
    int t=1;
    scanf("%d",&t);
    while(t--) solve();
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值