H题
突然发现H题可以用好多种方法做的。
方法一
双指针,维护一个修改次数小于等于k的区间
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod=1e9+7;
const int N=1e5+5;
const int inf=0x3f3f3f3f;
const int dx[]={-1,1,0,0};
const int dy[]={0,0,-1,1};
typedef vector<ll>vec;
typedef vector<vec>mat;
int n,k;
int solve(string s,char ch){
int l,r;
l=r=1;
int cnt=0;
int ans=1;
for(int i=1;i<=n;i++){
if(s[i]==ch){
if(cnt<k){
cnt++;
r++;
}
else {
while(l<=r&&s[l]!=ch){
l++;
}
l++;
r++;
}
}
else{
r++;
}
ans=max(ans,r-l);
}
return ans;
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0),cout.tie(0);
cin>>n>>k;
string s;
cin>>s;
s=" "+s;
cout<<max(solve(s,'0'),solve(s,'1'))<<endl;
return 0;
}
方法二
二分最大长度
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod=1e9+7;
const int N=2e5+5;
const int inf=0x3f3f3f3f;
const int dx[]={-1,1,0,0};
const int dy[]={0,0,-1,1};
typedef vector<ll>vec;
typedef vector<vec>mat;
int n,k;
int dp[N][2];
bool check(int len){
for(int i=1;i+len-1<=n;i++){
if(dp[i+len-1][0]-dp[i-1][0]<=k||dp[i+len-1][1]-dp[i-1][1]<=k)return 1;
}
return 0;
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0),cout.tie(0);
cin>>n>>k;
string s;
cin>>s;
s=" "+s;
for(int i=1;i<=n;i++){
dp[i][0]=dp[i-1][0];
dp[i][1]=dp[i-1][1];
dp[i][s[i]-'0']++;
}
int l=1,r=n;
while(l<r){
int m=(l+r+1)>>1;
if(check(m)){
l=m;
}
else r=m-1;
}
cout<<l<<endl;
return 0;
}
方法三
序列自动机
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod=1e9+7;
const int N=2e5+5;
const int inf=0x3f3f3f3f;
const int dx[]={-1,1,0,0};
const int dy[]={0,0,-1,1};
typedef vector<ll>vec;
typedef vector<vec>mat;
int n,k;
int nxt[N][2],pos[2],num[2];
int main()
{
ios::sync_with_stdio(false);
cin.tie(0),cout.tie(0);
cin>>n>>k;
string s;
cin>>s;
s=" "+s;
for(int i=n;i;i--){
for(int j=0;j<2;j++){
nxt[i-1][j]=nxt[i][j];
}
nxt[i-1][s[i]-'0']=i;
}
int ans=0;
for(int i=1;i<=n;i++){
num[s[i]-'0']++;
if(num[s[i]-'0']>k)pos[s[i]-'0']=nxt[pos[s[i]-'0']][s[i]-'0'];
ans=max(ans,max(i-pos[0],i-pos[1]));
}
cout<<ans<<endl;
return 0;
}