双指针类型题目:共同特征,在一端区间内满足条件。这题要求在一段区间内满足k个01子序列,那么直接左右指针先指向起点都是s[0]位置。r指针负责往后扩大范围,再者我们分析何时达到k个01子序列,首先0肯定要在1前面才能满足01的要求,前面有多少个0那么在0之后的1都能和其组合,这样我们就要实时记录0和1的个数分别为cnt_0和cnt_1,也要记录cnt也就是当前区间里01子序列的个数。
如果是01序列个数少于k,我们自增r扩大区间范围:那么分析可知如果新加的数是1,那么只有cnt_1自增的时候会贡献前面cnt_0个0与其组合,那么cnt就要加上cnt_0。否则是0就cnt_0自增。
如果01序列大于k个数,我们移动l缩小区间范围:那么分析可知,每移动一位如果是移除了0,那么后面所有1都要失去一次组合,那么cnt要减去cnt_1,否则是1就只要cnt_1自减。
如果是刚好cnt==k,那么输出l+1和r+1即可直接返回结束。
否则最后输出-1即可,注意l和r都要在n的范围内。
#include<bits/stdc++.h>
using namespace std;
#define int long long
void solve() {
int n, k;
cin >> n >> k;
string s;
cin >> s;
if (s.length() == 1) {
cout << "-1" << endl;
return;
}
int l = 0;
int r = 0;
int cnt=0;//记录有当前有几组01字序列
int cnt_1=0;
int cnt_0=0;
if(s[0]=='0'){
cnt_0++;
}else cnt_1++;
while(l<n&&r<n){
if(cnt==k){
cout<<l+1<<" "<<r+1<<endl;
return;
}else if(cnt<k){//说明r指针还需要继续往后加
r++;
if(s[r]=='1'){
cnt_1++;
cnt+=cnt_0;
}else{
cnt_0++;
}
}else{//说明已经超过了k的限制,需要移动l指针
if(s[l]=='0'){
cnt_0--;
cnt-=cnt_1;
}else{
cnt_1--;
}
l++;
}
}
cout<<"-1"<<endl;//之前没有输出结果这里输出代表寻找失败
}
signed main() {
ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
solve();
return 0;
}

京公网安备 11010502036488号