这个题应该有很多种做法, 看完题后第一想法是二分,但想了半天不知道怎么check。。最后搜了题解看网上的二分是枚举左端点然后对右端点二分,还要用树状数组维护=。=
想不出来二分,有想过排序加优先队列,但感觉每次出队出最小元素不是最优解,后来想通了,举几个例子,画一画就好了,其实就是对于每个区间,找别的区间里找左端点符合条件的区间(符合条件是指左端点比我小,在我左边),再从这些区间里找最大的右端点,对左端点排完序后,符合条件的其实也就是我前面的那些区间,通过维护一个长度为k的优先队列,找到那个最大。
#include<stdio.h>
#include<algorithm>
#include<functional>
#include<queue>
using namespace std;
struct node
{
int le,ri,num;
}nn[300005],ans;
struct cmp1
{
bool operator()(int &a,int &b)
{
return a>b;
}
};
int cmp(node u,node v)
{
return u.le<v.le;
}
int main()
{
int n,k,i,maxx,t,j;
priority_queue<int,vector<int>,cmp1>q;
scanf("%d %d",&n,&k);
for(i=0;i<n;i++)
{
scanf("%d %d",&nn[i].le,&nn[i].ri);
nn[i].num=i+1;
}
sort(nn,nn+n,cmp);
for(i=0;i<k;i++)
{
q.push(nn[i].ri);
}
maxx=q.top()-nn[k-1].le;
ans.le=nn[k-1].le;
ans.ri=q.top();
for(i=k;i<n;i++)
{
q.pop();
q.push(nn[i].ri);
t=q.top()-nn[i].le;
if(t>maxx)
{
maxx=t;
ans.le=nn[i].le;
ans.ri=q.top();
}
}
//输出部分
if(maxx>=0)
{
printf("%d\n",maxx+1);
for(i=0,j=0;i<n;i++)
{
if(j==k)
break;
if(nn[i].le<=ans.le&&nn[i].ri>=ans.ri)
{
printf("%d ",nn[i].num);
j++;
}
}
printf("\n");
}
else
{
printf("0\n");
for(i=1;i<=k;i++)
printf("%d ",i);
printf("\n");
}
return 0;
}