有时候二分法思路真的很重要,直接上题目吧!
写多了,自然而然你就会去用二分思路A掉它
第一题
题目传送门
2019年湘潭大学程序设计竞赛(重现赛)F题
题意: 给你一个长度为n的01串,然后m次转换,可以把0字符换成1,也可以把1换成0,最多 转换m次,求最后连续的0,或者连续1最长长度
思路:
第一种思路–>>>> 尺取法
第二种思路–>>>> 二分加前缀和思想
思路:
- 二分 + 前缀和思想
- 预处理前缀和,pre【i】表示的是数组【1…i】中有多少个0
- 然后我们就去二分这个答案,O(n)去验证这个答案
- 每次需判断这个区间内 0或1的个数加上m是否不小于当前二分的答案就行
- 时间复杂度O(nlogn)
AC代码
#include<bits/stdc++.h>
using namespace std;
typedef long long int ll;
const int N = 2e5 + 100, maxn = 5000+10;
const ll modd = 1e9+7;
ll a[10005];
void read(int &x)
{
int f=1;x=0;char s=getchar();
while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}
while(s>='0'&&s<='9'){x=x*10+s-'0';s=getchar();}
x*=f;
}
void solve(){
int n, m, b[N], c[N];
read(n), read(m);
char a[N];
scanf("%s",a+1);
for(int i = 1; i <= n; i++){
b[i] = b[i-1] + (a[i] == '0');
c[i] = c[i-1] + (a[i] == '1');
}
int l = 1, r = n, ans = 1;
while(l<=r){
int mid = l+r >>1, flag = 0;
for(int i = 1; i <= n; i++){
if(i+mid-1>n) break;
if(b[i+mid-1]-b[i-1]<=m||c[i+mid-1]-c[i-1]<=m){
flag = 1;
bre