The Delivery Dilemma

题目描述

Petya is preparing for his birthday. He decided that there would be nn different dishes on the dinner table, numbered from 11 to nn . Since Petya doesn't like to cook, he wants to order these dishes in restaurants.

Unfortunately, all dishes are prepared in different restaurants and therefore Petya needs to pick up his orders from nn different places. To speed up this process, he wants to order courier delivery at some restaurants. Thus, for each dish, there are two options for Petya how he can get it:

  • the dish will be delivered by a courier from the restaurant ii , in this case the courier will arrive in a_iai​ minutes,
  • Petya goes to the restaurant ii on his own and picks up the dish, he will spend b_ibi​ minutes on this.

Each restaurant has its own couriers and they start delivering the order at the moment Petya leaves the house. In other words, all couriers work in parallel. Petya must visit all restaurants in which he has not chosen delivery, he does this consistently.

For example, if Petya wants to order n = 4n=4 dishes and a = [3, 7, 4, 5]a=[3,7,4,5] , and b = [2, 1, 2, 4]b=[2,1,2,4] , then he can order delivery from the first and the fourth restaurant, and go to the second and third on your own. Then the courier of the first restaurant will bring the order in 33 minutes, the courier of the fourth restaurant will bring the order in 55 minutes, and Petya will pick up the remaining dishes in 1 + 2 = 31+2=3 minutes. Thus, in 55 minutes all the dishes will be at Petya's house.

Find the minimum time after which all the dishes can be at Petya's home.

输入格式

The first line contains one positive integer tt ( 1 \le t \le 2 \cdot 10^51≤t≤2⋅105 ) — the number of test cases. Then tt test cases follow.

Each test case begins with a line containing one integer nn ( 1 \le n \le 2 \cdot 10^51≤n≤2⋅105 ) — the number of dishes that Petya wants to order.

The second line of each test case contains nn integers a_1 \ldots a_na1​…an​ ( 1 \le a_i \le 10^91≤ai​≤109 ) — the time of courier delivery of the dish with the number ii .

The third line of each test case contains nn integers b_1 \ldots b_nb1​…bn​ ( 1 \le b_i \le 10^91≤bi​≤109 ) — the time during which Petya will pick up the dish with the number ii .

The sum of nn over all test cases does not exceed 2 \cdot 10^52⋅105 .

输出格式

For each test case output one integer — the minimum time after which all dishes can be at Petya's home.

题意翻译

你要去取菜,每一道菜属于不同的餐厅,对于每一种菜,你可以选择让餐厅送,也可以选择自己去拿。
第i道菜让餐厅送需要的时间为ai​,自己去拿需要的时间为bi​
问你最多需要多久可以把所有的菜都送到家里。

输入输出样例

输入 #1

4
4
3 7 4 5
2 1 2 4
4
1 2 3 4
3 3 3 3
2
1 2
10 10
2
10 10
1 2

输出 #1

5
3
2
3

上手懵逼,还好网上有大佬题解:大致思路参考了一位网友的题解思路

 ”如果在时间 t 能够把所有菜拿到家里,那么大于 t 的时间也都是可行的,所以我们可以二分答案,假设当前二分的答案为 p“,问题转化为判定问题,寻找第一个p,使得 在时间p内把所有的菜拿到家里,所以对于二分模板里面的“某条件”,需要写一个判定函数:

借鉴该网友的判定函数:

bool check(ll ans)
{
    for(int i=1;i<=n;i++)
        book[i]=false;
    for(int i=1;i<=n;i++)
    if(arr[i].a<=ans) book[i]=true;
    long long sum=0;
    for(int i=1;i<=n;i++)
    if(!book[i]) sum+=arr[i].b;
    return sum<=ans;
}

而我自己写的那个判定函数(AC不了),不能通过10 10

                                                                                  1   2   

这个数据,原本答案是3,我得出是2,百思不得其解。(破大防)有哪位大佬帮我看看我函数有什么问题,跪谢。

bool check(ll ans){
	int i;
	for(i=1;i<=n;++i){
		if(ans<=arr[i].a)
			break;
	}
	return ans>=sum[i+1];
}

完整AC代码:这个题解算是网友1的题解网友2的题解的综合版本

using namespace std;
const int maxn=2*1e5+10;

struct node{
	ll a;
	ll b;
}arr[maxn];
ll sum[maxn];
bool book[maxn]; 
int t,n;
bool cmp(node x,node y){
	return x.a<y.a;
}

bool check(ll ans)
{
    for(int i=1;i<=n;i++)
        book[i]=false;
    for(int i=1;i<=n;i++)
    if(arr[i].a<=ans) book[i]=true;
    long long sum=0;
    for(int i=1;i<=n;i++)
    if(!book[i]) sum+=arr[i].b;
    return sum<=ans;
}
int main(){

	scanf("%d",&t);
	while(t--){
		scanf("%d",&n);
		for(int i=1;i<=n;++i){
			scanf("%lld",&arr[i].a);
		}
		for(int i=1;i<=n;++i){
			scanf("%lld",&arr[i].b);
		}
		sort(arr+1,arr+1+n,cmp);//将array数组按照a从小到达排序
		 sum[n+1]=0;
		for(int i=n;i>=1;i--){
			sum[i]=sum[i+1]+arr[i].b;
		}
		ll left=1,right=1e9+10,mid;
		while(left<right){
			mid=(left+right)>>1;
			if(check(mid))
				right=mid;
			else
				left=mid+1;
		}
		printf("%lld\n",left);

	return 0;
}

网友1的题解只需要在上面的代码中把

ll left=1,right=1e9+10,mid;
		while(left<right){
			mid=(left+right)>>1;
			if(check(mid))
				right=mid;
			else
				left=mid+1;
		}
		printf("%lld\n",left);

改成:即可

	ll ans = 1e9 + 10;
	for(int i = 0;i <= n;i++){
			ll maxx = max(arr[i].a, sum[i + 1]);//计算答案 
			ans = min(ans, maxx);
		}
		printf("%lld\n", ans);

老实说,网友1的题解更简单

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值