http://codeforces.com/contest/754/problem/D
题意:
给定几组区间,找k组区间,使得它们的公共交集最大。
思路:
在k组区间中,它们的公共交集=k组区间中右端点最小值-k组区间中左端点最大值。如果我们要区间大,那我们应该尽量让左端点小,右端点大。
先对区间按照左端点排序,然后用优先队列处理。
将区间按照左端点从小到大的顺序一一进队列,只需要进右端点即可,如果此时队列内已有k个数,则队首就是这k组区间的最小右端点,而因为左端点是从小到大的顺序进队列的,所以这k组区间中左端点最大的就是当前进队列的区间,这样一来就可以算出在这种情况下的区间交集。如果此时队列内已有k+1个数,那么就弹出队首元素,因为此时弹出的区间右端点是最小的,而我们想要是的尽量大的右端点。
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<sstream>
#include<vector>
#include<stack>
#include<queue>
#include<cmath>
#include<map>
#include<set>
using namespace std;
typedef long long ll;
typedef pair<int,int> pll;
const int INF = 0x3f3f3f3f;
const int maxn=*1e5+; int n, k; struct node
{
int l, r;
int id;
bool operator < (const node& rhs) const
{
return l<rhs.l || (l==rhs.l && r<rhs.r);
}
}p[maxn]; struct cmp
{
bool operator() (const int a, const int b) const
{
return a > b;
}
}; int main()
{
// freopen("in.txt","r",stdin);
while(~scanf("%d%d",&n, &k))
{
for(int i=; i<=n; i++)
{
scanf("%d%d",&p[i].l, &p[i].r);
p[i].id = i;
} sort(p+,p+n+); priority_queue<int, vector<int>, cmp > Q;
int ans=, left, right; for(int i=;i<=n;i++)
{
Q.push(p[i].r);
if(Q.size()>k) Q.pop();
if(Q.size()==k)
{
int tmp=Q.top()-p[i].l+;
if(tmp>ans)
{
ans=tmp;
left=p[i].l;
right=Q.top();
}
}
} if(ans<=)
{
puts("");
for(int i=;i<=k;i++)
{
printf("%d%c",i,i==k?'\n':' ');
}
}
else
{
printf("%d\n",ans);
for(int i=;i<=n;i++)
{
if(p[i].l<=left && p[i].r>=right)
{
printf("%d",p[i].id);
k--;
if(k) printf(" ");
else {printf("\n");break;}
}
}
}
}
return ;
}