很有意思的一道题
- 既然要求最大能放入多少人,那么也就暗示从左往右(或从右往左)开始,按照顺序,能放就放,这样就能保证最优。
因此,问题就可以归结到如何构造上了
那么该如何构造呢?
由于数据很大,结合经验基本可以确定是O(N)的时间复杂度,因此就要思考如何处理才能使得操作具有O(N)的时间复杂度
我的思路
先用一个优先队列(小根堆)存入每个值为1的点,这样所有为1的点就按照顺序排列了,还有一点非常重要的是:
- 最后再放入一个很大的数字
再然后就是判断了,如果符合条件就跳到下一个符合条件的地方并且答案+1,即:i + k + 1
如果不符合就跳到下一个符合条件的地方
#include <iostream>
#include <string>
#include <algorithm>
#include <queue>
using namespace std;
const int N = 2e5 + 10;
int a[N];
void solve(){
priority_queue<int, vector<int>, greater<int> > pq;
int n, k;
string s;
cin >> n >> k;
cin >> s;
for(int i = 0; i < n; i ++)
if(s[i] == '1')
pq.push(i);
int size = pq.size();
if(!size){
if(n < k + 1)
cout << 1 << endl;
else{
if(n % (k + 1) == 0)
cout << n / (k + 1) << endl;
else
cout << n / (k + 1) + 1 << endl;
}
return;
}
pq.push(n + 3e5);
int temp = 0;
while(pq.size() && temp < n){
if(temp <= pq.top())
a[temp] = pq.top();
else{
pq.pop();
a[temp] = pq.top();
}
temp ++;
}
int ans = 0;
for(int i = 0; i < n; i ++){
if(s[i] == '1')
i = i + k;
else{
if(a[i] - i > k){
ans ++;
i = i + k;
}
}
}
cout << ans << endl;
}
int main(){
int t;
cin >> t;
while(t --){
solve();
}
return 0;
}