Social Distance(贪心+构造)

传送门

很有意思的一道题

  • 既然要求最大能放入多少人,那么也就暗示从左往右(或从右往左)开始,按照顺序,能放就放,这样就能保证最优。

因此,问题就可以归结到如何构造上了

那么该如何构造呢?

由于数据很大,结合经验基本可以确定是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;
}
原文地址:https://www.cnblogs.com/pureayu/p/14410279.html