不知道是为了找罪受还是闲的蛋疼,最近开始刷CF了。已经无力吐槽CF上的英语了,日式英语,俄式英语,美式,中式。。。。。各国大杂块啊!!!表示有时候题目要研读半天。为了害怕有些人跟莪一样要读题读半天,所以我就勉强的解释一下吧。
题意分析:题目说给你三个数,分别代表有多少辆自行车,有几个人,可以公用的钱数。下面n个数是每辆自行车的价格,m个数是每个人的私有钱数。现在题目要求你求出在可以得到最多自行车的条件下,使得每个人私有钱数花费最少。要求是输出最多自行车数,每个人花费的最少私人的钱。注意:是在可以花最多的钱数前提下,在求出最少的花费私人钱数。一开始的时候我就二分错误了,把私人钱数当成了二分对象。囧。
在分析算法吧。我们可以先排序自行车的价格和私人的钱数。我们可以用拥有较多钱数的k个人去买,较便宜的k辆自行车。如果在这种情况下还买不了K辆则说明一定买不了k辆的自行车。当初我一开始的时候就是看错了题目,把题目误解成是在花费最少私人的钱数下,求最多的自行车数。于是贡献了多个wrong。说说正确的算法思路吧。
我们可以较为容易的得到二分的范围,即0~min(n,m)。我们先从小到大的给私人钱数和自行车的价格排序。然后用每个二分值进行判断是否符合标准。解释一下如何判断二分到的每辆自行车是否符合标准吧。假如此时自行车数位K,我们用最少花费的自行车k辆,与拥有最多的私人钱数的k个人进行判断是否满足要求,如果不满足就说明K辆自行车达不到要求(自己好好想想为什么?)
还有的细节就在代码中解释吧。
#include <iostream>
#include <algorithm>
#include <cstdio>
using namespace std;
typedef __int64 LL;
const int N = 1e5 + 10;
int n,m,a,b[N],p[N];
bool ok(int k)
{
int index = n - k;
int tmp = a;
for(int i = 0;i < k;++i,++index) //使用拥有最多私有钱数的k个人进行判断
{
if(b[i] <= p[index]){ // 私人钱数已经足够购买该辆自行车
continue;
}else if((b[i] > p[index])&&(b[i] <= p[index]+tmp)){ //判断在挪用公用钱数时候,是否够买
tmp -= (b[i]-p[index]);
}else //在挪用私人钱数还不够购买
{
return false;
}
}
return true;
}
int main()
{
while(~scanf("%d%d%d",&n,&m,&a))
{
for(int i = 0;i < n;++i){
scanf("%d",&p[i]);
}
for(int i = 0;i < m;++i){
scanf("%d",&b[i]);
}
sort(p,p+n);
sort(b,b+m);
int L = 0,R = min(n,m);
while(L <= R)
{
int mid = L + (R-L)/2;
if(ok(mid))
L = mid + 1;
else
R = mid - 1;
}
int ans = L - 1;
LL res = 0;
for(int i = 0;i < ans;++i){
res += b[i];
}
res = max(res-a,0LL);
printf("%d %I64d\n",ans,res);
}
return 0;
}