专栏文章

CF2167E题解

CF2167E题解参与者 2已保存评论 1

文章操作

快速查看文章及其快照的属性,并进行相关操作。

当前评论
1 条
当前快照
1 份
快照标识符
@min5olvx
此快照首次捕获于
2025/12/01 20:59
3 个月前
此快照最后确认于
2025/12/01 20:59
3 个月前
查看原文

思路

最大化首个朋友到达传送点的时间,二分答案找最大可能的最小距离 dd
对每个 dd,计算朋友需覆盖的区间并合并,判断剩余空位能否放 kk 个传送点。
确定 dd 后,从合并区间外的空位中选 kk 个位置作为传送点。

代码

CPP
#include<bits/stdc++.h>
#define int long long
#define ft first
#define sd second
using namespace std;
int read(){
	int cnt = 0, sign = 1;
	char c = getchar();
	while(!isdigit(c)){
		if(c == '-')	sign = -1;
		c = getchar();
	}
	while(isdigit(c)){
		cnt = (cnt << 1) + (cnt << 3) + (c ^ 48);
		c = getchar();
	}
	return cnt * sign;
}
const int N = 2e5 + 10;
int a[N]; 
signed main(){
	int T = read();
	while(T--){
		int n = read(), k = read(), x = read();
		for(int i = 1; i <= n; i++){
			a[i] = read();
		}
		sort(a + 1, a + n + 1);
		int l = 0, r = x + 2;
		while(l <= r){
			int mid = (l + r) >> 1;
			vector < pair <int, int> > vec;
			for(int i = 1; i <= n; i++){
				int lt = max(a[i] - mid + 1, 0ll);
				int rt = min(a[i] + mid - 1, x * 1ll);
				if(lt <= rt)	vec.push_back({lt, rt});
			}
			sort(vec.begin(), vec.end());
			vector < pair <int, int> > mer;
			for(auto &t : vec){
				if(mer.empty() || t.ft > mer.back().sd + 1){
					mer.push_back(t);
				}else{
					mer.back().sd = max(mer.back().sd, t.sd);
				}
			}
			int sum = 0;
			for(auto &t : mer){
				sum += (t.sd - t.ft + 1);
			}
			if(x + 1 - sum >= k){
				l = mid + 1;
			}else{
				r = mid - 1;
			}
		}
		vector < pair <int, int> > vec;
		int de = r;
		for(int i = 1; i <= n; i++){
			int lt = max(a[i] - de + 1, 0ll);
			int rt = min(a[i] + de - 1, x * 1ll);
			if(lt <= rt)	vec.push_back({lt, rt});
		}
		sort(vec.begin(), vec.end());
		vector < pair <int, int> > mer;
		for(auto &t : vec){
			if(mer.empty() || t.ft > mer.back().sd + 1){
				mer.push_back(t);
			}else{
				mer.back().sd = max(mer.back().sd, t.sd);
			}
		}
		vector <int> ans;
		int cnt = 0;
		for(auto &t : mer){
			for(int i = cnt; i < t.ft && ans.size() < k; i++){
				ans.push_back(i);
			}
			cnt = t.sd + 1;
			if(ans.size() >= k){
				break;
			}
		}
		if(ans.size() < k){
			for(int i = cnt; i <= x && ans.size() < k; i++){
				ans.push_back(i);
			}
		}
		for(int i = 0; i < k; i++){
			printf("%d ", ans[i]);
		}
		printf("\n");
	}
	return 0;
}

评论

1 条评论,欢迎与作者交流。

正在加载评论...