![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/f2c06048cb0ad0775ad84b17c7aa6696.png)
- 要全部拿完,且要次数最小,那么第一次拿肯定是找r最小的,在这个最小的r处第一次拿
- 此时可能有很多区间覆盖了这个r,为了让拿的次数最小,要让下一次拿的时间尽可能晚,因此在这些覆盖了r的区间里选择r最小的k个区间
- 用一个结构体数组a记录l和r和编号,再用一个完全相同的结构体数组b复制一份,a数组按照r从小到大排序,b数组按照l从小到大排序;del数组,以编号为下标,记录该区间是否已经被删除
- 双指针,遍历a数组,如果当前这个已经被删除,则continue;i指针为a数组的指针,j指针为b数组的指针;i每次前进一个,将b数组中当前的r覆盖到的区间(记录r和编号)全部放入优先队列中(覆盖的判断方式:l小于等于r即可);然后删除小于等于k个
- 每一次当前没有被删除的区间中r最小的,将这个最小的r作为标准,然后将所有还未被放入过优先队列的l比当前r小的全都放入优先队列,然后删掉最多k个,同时标记它们已经被删除
#include <iostream>
#include <algorithm>
#include <cstring>
#include <queue>
#define endl '\n'
#define _(a) cout << #a << ": " << (a) << " "
using namespace std;
const int N = 1e5 + 10;
typedef pair<int, int> PII;
int n, k;
struct node {
int l, r, id;
}a[N], b[N];
struct cmp {
bool operator() (const PII &x, const PII &y) {
return x.first > y.first;
}
};
bool del[N];
bool cmpr(node a, node b) {
return a.r < b.r;
}
bool cmpl(node a, node b) {
return a.l < b.l;
}
int main() {
ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
int _; cin >> _;
while (_ -- ) {
cin >> n >> k;
int ans = 0;
for (int i = 1; i <= n; ++ i) {
cin >> a[i].l >> a[i].r;
a[i].id = i;
b[i] = a[i];
del[i] = false;
}
sort(a + 1, a + n + 1, cmpr);
sort(b + 1, b + n + 1, cmpl);
priority_queue<PII, vector<PII>, cmp> pq;
int j = 1;
for (int i = 1; i <= n; ++ i) {
if (del[a[i].id]) continue;
while (j <= n && b[j].l <= a[i].r) {
pq.push({b[j].r, b[j].id});
j ++ ;
}
ans ++ ;
for (int t = 1; t <= k; ++ t) {
if (pq.empty()) break;
PII now = pq.top(); pq.pop();
del[now.second] = true;
}
}
cout << ans << endl;
}
}