题目
我们所有的角色都有某些习惯。Fedor 也一样。他在邻近的超市享受购物。
超市的不同货物有不同的整数 ID。对于每个整数也有一个产品的 ID 和这个整数相同。Fedor 有 n n n 张折扣券,它们中的第 i i i 张可以用于 ID 范围介于 [ l i , r i ] [l_i, r_i] [li,ri] 的产品。今天 Fedor 想要携带恰好 k k k 张折扣券。
Fedor 想要选择 k k k 张折扣券,使得所有的折扣券都可以用于尽可能多的产品数目 x x x (为了最好的理解,参见样例)。Fedor 同时也想节省时间,所以他请求你为他选择折扣券。请帮帮 Fedor!
简要题意: 从 n n n个区间中选出恰好 k k k个, 最大化公共部分的长度.
题解
- 将左端点从小到大排序,然后用小根堆堆维护右端点(堆的大小为k)
- 为什么要用小根堆呢:因为我们要让区间长度尽可能的长,所以我们要每次弹出最小值qwq
c o d e code code
#include <bits/stdc++.h>
using namespace std;
const int maxn = 300000 + 100;
template <class T>
inline void read(T &s) {
s = 0;
T w = 1, ch = getchar();
while (!isdigit(ch)) { if (ch == '-') w = -1; ch = getchar(); }
while (isdigit(ch)) { s = (s << 1) + (s << 3) + (ch ^ 48); ch = getchar(); }
s *= w;
}
int n, k;
struct node {
int l, r, id;
bool operator <(const node &A) const {
return l < A.l;
}
};
node s[maxn];
priority_queue<int> p;
int main() {
read(n), read(k);
for (int i = 1; i <= n; ++i) {
read(s[i].l), read(s[i].r);
s[i].id = i;
}
sort(s + 1, s + n + 1);
int len = 0, L = 0, R = 0;
for (int i = 1; i <= n; ++i) {
p.push(-s[i].r);
if (p.size() > k) p.pop();
if (p.size() == k) {
int now = (-p.top()) - s[i].l + 1;
if (now > len) {
len = now;
L = s[i].l;
R = (-p.top());
}
}
}
printf("%d\n", len);
if (!len) {
for (int i = 1; i <= k; ++i)
printf("%d ", i);
}
else {
// printf("L = %d R = %d\n", L, R);
for (int i = 1, j = 1; i <= n && j <= k; ++i) {
if (s[i].l <= L && s[i].r >= R) {
printf("%d ", s[i].id), ++j;
}
}
}
return 0;
}