題目描述
你習得了魔法,並學會了熟練運用魔法石。
你得到了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;
}