- 假设最后的结果左边界为i,右边界为j,那么当左边界为i,右边界在j右边时,计算出的结果一定大于等于k,同样的,如果右边界在j左边,结果一定小于等于k。同理,固定j变化i可以得到相似的结论。
- 所以,使用i和j两个位置,先将j一直向右移动,一旦i j超过了k,那么就将i向右移动。直到满足等于k为止,这样就能找到所有可能等于k的区间。
- 可以使用类似前缀和的思想,不停维护i j之间的0 1序列数量。
#include <bits/stdc++.h>
using namespace std;
int main() {
int n;
long long k;
cin >> n >> k;
string s;
cin >> s;
int i = 0, j = 0;
int cnt0 = 0, cnt1 = 0;
long long cnt = 0;
int flag = 1;
while (j != n) {
// cout << i << ' ' << j << ' ' << cnt << '\n';
// if (i > 40)
// printf("%d %d %lld\n", i, j, cnt);
if (flag == 1) {
if (s[j] == '1') {
cnt1++;
cnt += cnt0;
if (cnt == k) {
cout << i + 1 << ' ' << j + 1 << '\n';
return 0;
}
} else if (s[j] == '0') {
cnt0++;
}
} else if (flag == 2) {
if (s[i - 1] == '1') {
cnt1--;
} else if (s[i - 1] == '0') {
cnt -= cnt1;
cnt0--;
if (cnt == k) {
cout << i + 1 << ' ' << j + 1 << '\n';
return 0;
}
}
}
if (cnt < k) {
j++;
flag = 1;
} else if (cnt > k) {
i++;
flag = 2;
}
}
cout << -1 << '\n';
return 0;
}