您的位置:首页 > Web前端

Codeforces Round #390 (Div. 2) D. Fedor and coupons(区间最大交集+优先队列)

2017-06-26 14:34 387 查看
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=3*1e5+5;

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=1; i<=n; i++)
{
scanf("%d%d",&p[i].l, &p[i].r);
p[i].id = i;
}

sort(p+1,p+n+1);

priority_queue<int, vector<int>, cmp > Q;
int ans=0, left, right;

for(int i=1;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+1;
if(tmp>ans)
{
ans=tmp;
left=p[i].l;
right=Q.top();
}
}
}

if(ans<=0)
{
puts("0");
for(int i=1;i<=k;i++)
{
printf("%d%c",i,i==k?'\n':' ');
}
}
else
{
printf("%d\n",ans);
for(int i=1;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 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐