cf612 D. The Union of k-Segments(被至少K条线段覆盖的所有区间)
题意:
给定n条线段,如果一个实数点被至少K条线段覆盖,称为好点。输出一列总长度最小的、包含所有好点的闭区间
输入均为整数
思路:
传世经典题。
差分思想:想象一个实数轴,所有线段左端点坐标处打上1标记,右端点打上-1。对所涉所有坐标排序,计算前缀和 k。根据当前的 k 可以判断当前点被覆盖的情况
int n, K; vector ve; //位置,类型
vector ans; //答案
signed main() {
iofast;
cin >> n >> K;
for(int i = 1; i <= n; i++) {
int l, r; cin >> l >> r;
ve.pb({l, 1}), ve.pb({r, -1});
}
sort(all(ve), [](PII &x, PII &y) { //保证先加再减
return x.fi != y.fi ? x.fi < y.fi : x.se > y.se;
});
int k = 0; for(auto &[p,t] : ve) {
if(k == K - 1 && t == 1) ans.pb({p,0});
if(k == K && t == -1) ans.back().se = p;
k += t;
}
cout << ans.size() << endl;
for(auto &[l,r] : ans) cout << l << ' ' << r << endl;
}
细节可以稍有不同:
for(int i = 1; i <= n; i++) {
int l, r; cin >> l >> r;
ve.pb({l, 1}), ve.pb({r + 1, -1}); //这样
}
sort(all(ve)); //这样
int k = 0; for(auto &[p,t] : ve) {
if(k == K - 1 && t == 1) ans.pb({p,0});
if(k == K && t == -1) ans.back().se = p-1;//这样
k += t;
}