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;
}