貌似是套路题.
假设给定我们一些区间,那么这些区间交集的左端点是左端点最靠右区间的左端点.
所以我们将所有区间按照左端点从小到大排序,然后用堆维护前 k 大的右端点.
那么,对于枚举到的第 $i$ 个区间来说,右端点就是第 $k$ 大的右端点与当前区间右端点的较小值.
code:
#include <cstdio>
#include <string>
#include <cstring>
#include <queue>
#include <cctype>
#include <algorithm>
#define N 1000050
using namespace std;
namespace IO {
void setIO(string s)
{
string in=s+".in";
string out=s+".out";
freopen(in.c_str(),"r",stdin);
}
inline char nc()
{
static char buf[100000] , *p1 , *p2;
return p1 == p2 && (p2 = (p1 = buf) + fread(buf , 1 , 100000 , stdin) , p1 == p2) ? EOF : *p1 ++ ;
}
inline int rd()
{
int ret = 0; char ch = nc();
while(!isdigit(ch)) ch = nc();
while(isdigit(ch)) ret = ((ret + (ret << 2)) << 1) + (ch ^ '0') , ch = nc();
return ret;
}
};
int n,k,ans,A[N];
struct node {
int l,r,id;
node(int l=0,int r=0,int id=0):l(l),r(r),id(id){}
bool operator<(node b) const { return r>b.r; }
}arr[N];
priority_queue<node>q;
bool cmp(node a,node b) { return a.l<b.l; }
int main()
{
// IO::setIO("input");
int i,j,mx=0;
using namespace IO;
n=rd(),k=rd();
for(i=1;i<=n;++i)
{
arr[i].l=rd(),arr[i].r=rd();
arr[i].id=i;
}
sort(arr+1,arr+1+n,cmp);
for(i=1;i<=n;++i)
{
q.push(arr[i]);
if(i<k) continue;
else
{
if(i>k) q.pop();
node p=q.top();
mx=max(mx,min(arr[i].r,q.top().r)-arr[i].l);
}
}
printf("%d\n",mx);
while(!q.empty()) q.pop();
for(i=1;i<=n;++i)
{
if(i<k) q.push(arr[i]);
else
{
node p=q.top();
q.push(arr[i]);
if(i>k) q.pop();
int now=q.top().r-arr[i].l;
if(now==mx)
{
int tot=0;
while(!q.empty()) A[++tot]=q.top().id,q.pop();
sort(A+1,A+1+tot);
for(i=1;i<=tot;++i) printf("%d ",A[i]);
return 0;
}
}
}
return 0;
}