Codeforces Round #681 (Div. 2, based on VK Cup 2019-2020 - Final) /1443C The Delivery Dilemma

题目链接:https://codeforces.com/contest/1422/problem/C

题目大意:小明过生日,想吃n盘菜,他有2个选择:①外卖员送,②自己去取

题目思路:外卖花费时间:所选择的菜的配送时间的最大值,自己花费时间:所选择的菜的自取时间的和,我们可以将外卖配送时间按从小到大排序,相同配送时间按自取时间从小到大,(pair<int, int> 针不戳) 并且将自取时间以前缀和的方式存起来,然后从头遍历,当遍历到第i个菜时,前i个菜的配送时间为a[i].first,后n-i个菜的自取时间为a[n].second - a[i].second,取这两者的最大值,这表明我其中一种的花费总时间,然后遍历对总时间取最小值即可。
注意当循环遍历到n时,a[n].second - a[i].second = 0,此时 max(a[i].first, a[n].second - a[i].second)) = a[n].first,即第n个总时间在遍历时一定是求的配送时间,但这不一定对,可能所有菜都是自取时可能花费时间会更少,所以最后需要单独对a[n].second进行判断

AC代码:

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <vector>
#include <map>
#include <string>
#include <cstring>
#include <set>
#include <stack>
#include <deque>
#include <queue>
using namespace std;
typedef long long ll;
typedef pair<int, int> PII;
typedef pair<ll, ll> PLL;
typedef unsigned long long ull;
const int INF = 0x3f3f3f3f;
const int N = 2e5 + 10, M = 5 * N;
int n, m, t, k;
PLL a[N];
int main()
{
    scanf("%d", &t);
    while (t--)
    {
        scanf("%d", &n);
        for (int i = 1; i <= n; ++i)
            scanf("%lld", &a[i].first);
        for (int i = 1; i <= n; ++i)
            scanf("%lld", &a[i].second);
        sort(a + 1, a + 1 + n);//pair<int, int>自带排序
        ll ans = INF;
        for (int i = 1; i <= n; ++i)
            a[i].second += a[i - 1].second;//前缀和
        for (int i = 1; i <= n; ++i)
            ans = min(ans, max(a[i].first, a[n].second - a[i].second));//对每个i的总时间取最小值
        ans = min(ans, a[n].second);//判断特例:所有菜都自取
        printf("%lld\n", ans);
    }
    return 0;
}

posted @ 2020-11-07 11:22  xiaopangpang7  阅读(128)  评论(0编辑  收藏  举报