Codeforces 754D. Fedor and coupons
传送门:https://codeforces.com/problemset/problem/754/D
提醒自己:
主要是针对这一类二元数对找并集的问题,可以尝试先通过排序减少变元数量。
(后来发现这个好像不止这种情况有用,其它情况有时也可以节省一定步骤。
比如说那个4D就是可以省掉一点计算步骤。)
题目大意:
这个题目还是比较好理解的,就是从n对数中选出k对数,使得这k对数每一对数所含区间它们的交集最大。然后输出这个最大的数。
主要想法:
它有两个变元,如果你想做的话应该是要发行量减少一个变元的,怎么做呢,对它的左边界或者右边界排序,这样就减少了一个变元。那么我们先随便加前k个对进去,显然,如果这个新数右界比前面的右界小,就不用管它了,反之,我们要比较加入这个新对是否可以优化利益如果可以,就把原来最小的右界去掉,加入这个新数,反之,不加入。
代码实现:
#include <bits/stdc++.h>
using namespace std;
struct node
{
int x,y,z;
}a[300300];
bool cmp(struct node d,struct node e)
{
if(d.x==e.x)return d.y<e.y;
return d.x<e.x;
}
priority_queue<int,vector<int>,greater<int> >b;
int main()
{
int n,k,max,l,r;
cin>>n>>k;
for(int i=1;i<=n;i++)
{
scanf("%d%d",&a[i].x,&a[i].y);
a[i].z=i;
}
sort(a+1,a+n+1,cmp);
for(int i=1;i<=k;++i)
{
b.push(a[i].y);
}
max=b.top()-a[k].x+1;
l=a[k].y;
r=b.top();
for(int i=k+1;i<=n;i++)
{
if(a[i].y<b.top())continue;
b.push(a[i].y);
b.pop();
if(b.top()-a[i].x+1>max)
{
l=a[i].x;
r=b.top();
max=b.top()-a[i].x+1;
}
}
if(max<=0)
{
max=0;
l=1e9;
r=-1e9;
}
cout <<max<<endl;
for(int i=1,j=1;j<=k;i++)
{
if(a[i].x<=l&&a[i].y>=r)
{
if(j!=1)cout<<' ';
cout<<a[i].z;
j++;
}
}
return 0;
}
既然提到了4D我就顺便补个链接吧:
https://blog.csdn.net/ydfy_/article/details/98754541