题目链接: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;
}