问题 F: 魔法石-------------------------思维(二分)

53 篇文章 0 订阅
28 篇文章 0 订阅

题目描述
你习得了魔法,并学会了熟练运用魔法石。
你得到了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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值