All our characters have hobbies. The same is true for Fedor. He enjoys shopping in the neighboring supermarket.
The goods in the supermarket have unique integer ids. Also, for every integer there is a product with id equal to this integer. Fedor has n discount coupons, the i-th of them can be used with products with ids ranging from li to ri, inclusive. Today Fedor wants to take exactly k coupons with him.
Fedor wants to choose the k coupons in such a way that the number of such products x that all coupons can be used with this product x is as large as possible (for better understanding, see examples). Fedor wants to save his time as well, so he asks you to choose coupons for him. Help Fedor!
InputThe first line contains two integers n and k (1 ≤ k ≤ n ≤ 3·105) — the number of coupons Fedor has, and the number of coupons he wants to choose.
Each of the next n lines contains two integers li and ri ( - 109 ≤ li ≤ ri ≤ 109) — the description of the i-th coupon. The coupons can be equal.
In the first line print single integer — the maximum number of products with which all the chosen coupons can be used. The products with which at least one coupon cannot be used shouldn't be counted.
In the second line print k distinct integers p1, p2, ..., pk (1 ≤ pi ≤ n) — the ids of the coupons which Fedor should choose.
If there are multiple answers, print any of them.
4 2 1 100 40 70 120 130 125 180
31 1 2
3 2 1 12 15 20 25 30
0 1 2
5 2 1 10 5 15 14 50 30 70 99 100
21 3 4
In the first example if we take the first two coupons then all the products with ids in range [40, 70] can be bought with both coupons. There are 31 products in total.
In the second example, no product can be bought with two coupons, that is why the answer is 0. Fedor can choose any two coupons in this example.
题目大意:某人有n张优惠券,每张优惠券都有一个优惠区间,比如说某张优惠券能优惠1~25号商品(1~25号为商品编号,一共25个商品),现在需要从n张优惠劵中选出k张,保证这k张能重叠优惠到最大商品区间来使这个区间中的商品经过多次优惠以至价格最低。本质就是从n个区间中选k个区间。
题解:这题我一开始用到暴力,复杂度为(n*(n-1))/2,没想到超时了,我的暴力思想是先对所给的区间左值排好序,从第k个商品开始,扫描前面商品,保留最小右值与第k个左值,保留所得区间,然后再从k+1个商品开始,扫描前面的商品,以此下去,不断改变最大区间,好像在第八组的时候超时了。参考别的博主用的是优先队列,受益匪浅。
使用优先队列,也是先对左值排序,选定k个商品,按右值从小到大进队,求重叠区间,然后出队(此时出队肯定是右值最小的,它出队对于后面区间的没有影响,因为后面区间左值大于它,重叠的区间不会比它大,自己考虑),不断更新最大值,这样只扫描了一遍就得出结果,在输出时也要注意,自己考虑技巧吧。下面是优先队列ac代码。
#include <iostream>
#include <algorithm>
#include <queue>
using namespace std;
typedef struct point{
int start;
int end;
int id;
}pt;
pt p[300005];
bool cmp (pt a,pt b)
{
return a.start<b.start;
}
int main ()
{
int n,k;
int i,j,value,flag,l;
while (scanf ("%d%d",&n,&k)!=EOF)
{
priority_queue<int,vector<int>,greater<int> >q;\\队列申请在while里,放在外面要不断再把队列清空。
l=0;
value=0;
for (i=1;i<=n;i++)
{
cin>>p[i].start>>p[i].end;
p[i].id=i;
}
sort (p+1,p+n+1,cmp);
for (i=1;i<=n;i++)
{
l=p[i].start;
q.push(p[i].end);
while (q.size()>k)
q.pop();
if (q.size()==k)
{
if (q.top()-l+1>value)
{
value=q.top()-l+1;
flag=i;
}
}
}
cout<<value<<endl;
if (value==0)
{
for (i=1;i<=k;i++)
{
if (i!=1)
cout<<" ";
cout<<i;
}
cout<<endl;
}
else
{
for (i=1;i<=flag;i++)\\要好好考虑,是个技巧。
if (p[i].end-p[flag].start+1>=value)
cout<<p[i].id<<" ";
cout<<endl;
}
}
return 0;
}