CF #681 Div.2 C. The Delivery Dilemma

describe:

小明点了n个菜,每个菜都在不同的餐馆,他可以选择送餐和自取两种方式。
自取只能一件一件拿

给出两个数组,a,b分别表示n个菜送餐的时间和n个菜自取的时间。求出最短需要时间。

输入t 和 n ,表示t组数据,n表示a,b数组的长度

For example, if Petya wants to order n=4 dishes and a=[3,7,4,5], and 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 3 minutes, the courier of the fourth restaurant will bring the order in 5 minutes, and Petya will pick up the remaining dishes in 1+2=3 minutes. Thus, in 5 minutes all the dishes will be at Petya’s house.

Input:

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

Output:

5
3
2
3

方法一:

使用结构体排序,对送餐时间排序,对自取时间求前缀和。
为了时间最短:

  1. 送餐是可以所有外卖同时进行的,所以需要送餐5分钟的到达,那么1,2,3,4分钟的也都到了,则不需要自取。
  2. 如果前五分钟内的都送餐,与此同时我们取餐需要一件一件的取,为了得到其他食物自取需要的时间,则用一个前缀和就好。
  3. 接下来一分钟一分钟的遍历,找到时间最短的
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
 
struct Node{
    long long x,y;
}node[200006];
 
bool cmp(const Node &a,Node &b){
    return a.x < b.x;
}
 
long long sum[200006];
int main()
{
    int t,a,b,n,m;
    ios::sync_with_stdio(false);
    cin>>t;
    while (t--)
    {
        cin>>n;
        for(int i = 0;i<n;i++){
            cin>>node[i].x;
        }
        for(int i = 0;i<n;i++){
            cin>>node[i].y;
        }
        sort(node,node+n,cmp);
        sum[0] = node[0].y;
        for(int i = 1;i<n;i++){
            sum[i] = sum[i-1] + node[i].y;
        }
        long long ans = sum[n-1];
        for(int i = 0;i<n;i++) {
            ans = min(ans, max(node[i].x,sum[n-1]-sum[i]));
        }
        cout<<ans<<endl;
    }
    return 0;
}

注意ans的初始化


方法二:
使用二分:首先,对于时间是单调有序递增的,那么比最短时间长的时间肯定可以完成,且比他短的时间必定不可以完成,所以可以使用二分法。

#include<bits/stdc++.h>
using namespace std;
#define int long long

int a[200006], b[200006];
signed main()
{
    int t;
    cin >> t;
    while(t--){
        int n;
        cin >> n;
        for(int i = 1; i <= n; i++)
            cin >> a[i];
        for(int i = 1; i <= n; i++)
            cin >> b[i];
        int l = 1, r = 1e10;
        int ans;
        while(l <= r)
        {
            int mid = (l+r) >> 1;
            int sum = 0;
            for(int i = 1; i <= n; i++)
            {
                if(a[i] > mid)
                {
                    sum += b[i];
                }
            }
            if(sum <= mid) {ans = mid;r = mid - 1;}
            else l = mid + 1;
        }
        cout << ans << endl;
    }
}
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值