CF #211 (Div. 2)--D. Renting Bikes


链接:http://codeforces.com/problemset/problem/363/D

题解:

363D - Renting Bikes

Let's do a binary search over the number of boys that can rent a bike. So let's say that we want to check whether it possible for k boys to rent bikes. If some k boys can rent a bike, then the k "richest" boys (with the most amount of personal money) also can do that. It is easy to see that if they can rent bikes, they can rent k cheapest bikes (if we first sort the bikes in increasing order of price, it will be just the first k bikes).

So, take k richest boys and try to match them with k cheapest bikes, spending as much common budget as possible. The following algorithm works (try to understand and prove it before asking questions): take the boy with least number of money (of course, among the considered k richest) and try to give him the cheapest bike. If the boy has ehough personal money to rent this bike, use his money to do this. Otherwise, use all his money and take some money from the common budget. Continue this process with the second cheapest bike and the second "poorest among the richest" boys. This process can end in two ways: we will either run out of budget and fail to rent kbikes, or we will successfully rent these bikes.

好牛的二分。。涨知识了。。

代码:

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<algorithm>
#include<queue>
#include<stack>
using namespace std;
#define ll __int64
int i,j;
int n,m,k;

int a[100100];
ll b[100100];

ll sum,money;
bool check(int p)
{
	int i=0;
	sum=0;
	money=k;
	int pb=1,pa=n-p+1;
	while(i!=p)
	{
		if(a[pa]>=b[pb])
			sum+=b[pb];
		else
		{
			if(money>=b[pb]-a[pa])
			{
				money-=b[pb]-a[pa];
				sum+=a[pa];
			}
			else
				return 0;
		}
		pa++;
		pb++;
		i++;
	}
	return 1;
}

int main()
{
	scanf("%d%d%d",&n,&m,&k);
	for(i=1;i<=n;i++)
		scanf("%d",&a[i]);
	for(i=1;i<=m;i++)
		scanf("%I64d",&b[i]);
	sort(a+1,a+n+1);
	sort(b+1,b+m+1);
	int l=0,r=min(n,m);
	while(l<r)
	{
		int mid=(r+l+1)/2;
		if(check(mid))
			l=mid;
		else
			r=mid-1;
	}
	ll tt=0;
	for(i=1;i<=l;i++)
		tt+=b[i];
	tt-=k;
	if(tt<=0) tt=0;
	printf("%d %I64d\n",l,tt);
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值