习题:Cipele (二分&贪心)
题目
在将大部分钱花在各种项目上之后,Nadan决定为他的软件开发人员提供高质量的鞋。幸运的是,Nadan在他的地下室发现了N双左脚穿的鞋子和M双右脚穿的鞋子,由于它们的来源不明,因此这些鞋子有各种各样的尺寸。
Nadan要求你尽可能多的给这些鞋子配对(重要的是所有的鞋子配对后就不能再选择新的鞋子),每双鞋子有一只左脚穿的和一只右脚穿的。在搭配时,你应该确保这些鞋的丑陋值最小,丑陋值是指所有的搭配中左右两只鞋子尺寸大小差的绝对值的最大值。
输入格式
第一行输入两个数字N和M(1≤N,M≤100000),分别表示左鞋子和右鞋子的数量。
第二行输入N个数字Li(1≤Li≤109),表示第i只左鞋子的尺寸。
第三行输入M个数字Ri(1≤Ri≤109),表示第i只右鞋子的尺寸。
输出格式
输出所有可能的鞋子搭配中最小的丑陋值。
样例
样例输入1
2 3
2 3
1 2 3
样例输出1
0
样例输入2
4 3
2 39 41 45
39 42 46
样例输出2
1
样例输入3
5 5
7 6 1 2 10
9 11 6 3 12
样例输出3
4
思路:
看到这道题,首先想到的必然是贪心,将两种鞋按从小到大排序。
之后就直接二分答案,检测结合排序后的数组很容易就能写出
二分注意边界条件的判断
代码:
#include<cstdio>
#include<iostream>
#include<climits>
#include<cstring>
#include<algorithm>
using namespace std;
void read(long long &x)
{
x=0;
int f=1;
char c=getchar();
while('0'>c||c>'9')
{
if(c=='-')
f=-1;
c=getchar();
}
while('0'<=c&&c<='9')
{
x=(x<<3)+(x<<1)+c-'0';
c=getchar();
}
x*=f;
}
void write(long long x)
{
if(x<0)
{
putchar('-');
write(-x);
return;
}
if(x<10)
{
putchar(x+'0');
}
else
{
write(x/10);
putchar(x%10+'0');
}
}
long long ans=INT_MAX;
long long l,r;
long long n,m;
long long a[100005];
long long b[100005];
bool f[100005];
long long f_abs(long long x)
{
if(x<0)
return -x;
return x;
}
bool check(int step,long long x)
{
memset(f,0,sizeof(f));
int _index=1;
for(int i=1;i<=n;i++)
{
while(f_abs(a[i]-b[_index])>x&&_index<=m)
_index++;
if(_index==m+1)
return 0;
_index++;
}
return 1;
}
int main()
{
read(n);
read(m);
for(int i=1;i<=n;i++)
read(a[i]);
for(int i=1;i<=m;i++)
read(b[i]);
if(n>m)
{
for(int i=1;i<=n;i++)
swap(a[i],b[i]);
swap(n,m);
}
sort(a+1,a+n+1);
sort(b+1,b+m+1);
l=0;
r=f_abs(b[m]-a[1]);
while(l+1<r)
{
long long mid=(l+r)/2;
if(check(n,mid))
{
ans=min(ans,mid);
r=mid;
}
else
l=mid;
}
if(check(n,l))
ans=min(ans,l);
if(check(n,r))
ans=min(ans,r);
write(ans);
return 0;
}

浙公网安备 33010602011771号