题意比较简单,给定n个区间,选择其中k个区间,并且这k个区间的重叠最大。这个题目当时也是想了很久没有想出来。后来看了题解,觉得这是一个典型的问题,有一般的解题思路。一般的解题思路为,将区间按照左端点从小到大的排序,然后利用优先队列,将排序后的区间的右端点依次进入队列(右端点小的在队首),保持队列中只有k个区间的右端点。用队列的队首减去刚入队区间的左端点,得到的便是队列中k个区间的重叠部分,依次更新,取最大值即可。代码如下:
#include <cstdio>
#include <cstring>
#include <queue>
#include <algorithm>
using namespace std;
const int MAX = 300010;
struct Node1{
int l, r, p;
bool operator < (const Node1& args) const {
return l < args.l;
}
}a[MAX];
priority_queue<int, vector<int>, greater<int> > q;
int main(int argc, char const *argv[])
{
/* code */
int n, k;
scanf("%d%d", &n, &k);
for (int i = 1; i<=n; i++){
scanf("%d%d", &a[i].l, &a[i].r);
a[i].p = i;
}
sort(a+1, a+n+1);
for (int i = 1; i<k; i++){
q.push(a[i].r);
}
int ans = 0, left = -1, right = -1;
for (int i = k; i<=n; i++){
q.push(a[i].r);
int t = q.top();
if (ans < t - a[i].l + 1 ){
ans = t - a[i].l + 1;
left = a[i].l;
right = t;
}
q.pop();
}
// printf("%d %d\n", left, right);
printf("%d\n", ans);
if (ans == 0){
for (int i = 1; i<k; i++){
printf("%d ", i);
}
printf("%d\n", k);
}else{
int i, j;
for (i = 1, j = 1; j<k; i++){
if (a[i].l <= left && a[i].r >= right){
printf("%d ", a[i].p);
j++;
}
}
for (; i<=n; i++) if (a[i].l <= left && a[i].r >= right){
printf("%d\n", a[i].p);
break;
}
}
return 0;
}