题目描述
你习得了魔法,并学会了熟练运用魔法石。
你得到了n颗魔法石,魔法石有两种属性,分别为火属性和水属性。你一开始得到的是这n颗魔法石的一个排列。定义这n颗魔法石释放出来的能量,为最长的属性相同的魔法石连续段的长度。
作为一名熟练的魔法师,你还可以至多修改k个魔法石的属性。你现在想知道这n颗魔法石最多可以释放出多少能量。
输入
第一行为两个正整数n,k,表示魔法石的个数和最多可以修改的魔法石数量。
接下来一行为一个长度为n的字符串,第i个字符表示第i颗魔法石的属性,a为火属性,b为水属性。
输出
输出为一行一个正整数,表示这n颗魔法石最多可以释放出的能量大小。
样例输入 Copy
【样例1】
4 2
abba
【样例2】
8 1
aabaabaa
样例输出 Copy
【样例1】
4
【样例2】
5
提示
对于30%的数据,满足n≤20。
对于60%的数据,满足n≤1000。
对于另外20%的数据,满足所有魔法石属性均相同。
对于100%的数据,满足1≤k≤n≤105。
解析:
二分答案
如何判断???
枚举二分的值作为一段区间长度,判断这段区间中a和b的数量。我们可以用前缀和维护a的数量 ,那么b的数量就是区间长度-a的数量。两者取最小值(因为我需要改动最少) 判断最小值是否<=k,如果小于l=mid+1,否则 r=mid-1;
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10000;
int sum[N];
int n,k;
char s[N];
bool check(int mid)
{
int ans=0x3f3f3f3f;
for(int i=1;i+mid-1<=n;i++)
{
int a=sum[i+mid-1]-sum[i-1];
int b=mid-a;
ans=min(ans,min(a,b));
}
if(ans<=k) return true;
return false;
}
int main()
{
cin>>n>>k;
cin>>(s+1);
for(int i=1;i<=n;i++) sum[i]=sum[i-1]+(s[i]=='a');
int l=0,r=n;
int res=0;
while(l<=r)
{
int mid=l+r>>1;
if(check(mid)) res=mid,l=mid+1;
else r=mid-1;
}
cout<<res<<endl;
}