Codeforces Round #681 (Div. 2, based on VK Cup 2019-2020 - Final)
题意:张三今天过生日,需要准备n个菜,可是他又懒得做,每道菜有两种选择,1.点外卖(ai分钟送达)2.自己去拿(花费bi分钟)。
点的所有外卖在张三第一次离开家的同时开始计算。张三一次亲自只能去拿一道菜。求张三备齐所有菜需要的最小时间。
解题分析:贪心,思维题点外卖花费的时间是时间最长的外卖时间,自取花费的时间是所有自取菜品的时间和。
总时间为两者的较大值。解题关键:最大外卖花费为a时,外卖时间小于等于a的外卖都不需要自取。
所以我们只需要对ai升序排序,用前缀和求外卖时间大于a的总自取时间 ans=min(ans,max(c[i].a,sum[n]-sum[i]));
注意:此题由bi求和最大10的14次 要开long long才能过。
代码一:思维贪心
#include<iostream>
#include<algorithm>
#include<iomanip>
#include<set>
#include<queue>
#include<stack>
#include<vector>
#include<map>
#include<string.h>
#include<string>
#include<math.h>
#define INF 0x7fffffff
#define IOS; {ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);}
#define debug(x) {cout<<"<<<<"<<(x)<<endl;}
#define print(x) {cout<<(x)<<endl;}
const int N = 2e5+5;
typedef long long ll;
using namespace std;
struct node
{
ll a=0,b=0;
}c[N];
bool cmp(node x,node y)
{
return x.a<y.a;
}
ll sum[N];
int main() {
IOS;
int t;cin>>t;
while(t--)
{
int n;cin>>n;
for(int i=1;i<=n;i++)
cin>>c[i].a;
for(int i=1;i<=n;i++)
cin>>c[i].b;
sort(c+1,c+1+n,cmp);
for(int i=1;i<=n;i++)
{
sum[i]=sum[i-1]+c[i].b;
}
ll ans=sum[n];
for(int i=1;i<=n;i++)
ans=min(ans,max(c[i].a,sum[n]-sum[i]));
cout<<ans<<endl;
}
return 0;
}
代码二:二分答案
#include<iostream>
#include<algorithm>
#include<iomanip>
#include<set>
#include<queue>
#include<stack>
#include<vector>
#include<map>
#include<string.h>
#include<string>
#include<math.h>
#define INF 0x7fffffff
#define IOS; {ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);}
#define debug(x) {cout<<"<<<<"<<(x)<<endl;}
#define print(x) {cout<<(x)<<endl;}
const int N = 2e5+5;
typedef long long ll;
using namespace std;
ll a[N];
ll b[N];
int n;
bool check(ll x)
{
ll sum=0;
for(int i=1;i<=n;i++)
{
if(a[i]>x)
sum+=b[i];
}
return sum<=x;
}
int main() {
IOS;
int t;cin>>t;
while(t--)
{
cin>>n;
for(int i=1;i<=n;i++)cin>>a[i];
for(int i=1;i<=n;i++)cin>>b[i];
ll l=1;
ll r=0;
for(int i=1;i<=n;i++)
r+=b[i];
while(l<r)
{
ll mid=(l+r)/2;
if(check(mid))r=mid;
else l=mid+1;
}
cout<<r<<endl;
}
return 0;
}