問題 F: 魔法石-------------------------思維(二分)

題目描述
你習得了魔法,並學會了熟練運用魔法石。
你得到了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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章