CF734C Anton and Making Potions 题解
题目大意
你需要做至少 \(n\) 瓶药水,每瓶药水需要用 \(x\) 秒制成。你还有两种法术,第一种法术共有 \(m\) 个,第 \(i\) 个需要用 \(b_i\) 点法力值,可以让每瓶药水的制作时长改为 \(a_i\) 秒;第二种法术共有 \(k\) 个,第 \(i\) 个需要用 \(d_i\) 点法力值,可以瞬间制作 \(c_i\) 瓶药水,且 \(c_i\) 和 \(d_i\) 非递减。但是每种法术只能用一个。你总共有 \(s\) 点法力值,求制作至少 \(n\) 瓶药水最少需要几秒。
算法分析
首先考虑不用法术和只用一种法术的情况,显然这里很好处理,直接枚举就行了。
然后考虑两种法术一起用的情况。注意到 \(c_i\) 和 \(d_i\) 非递减,也就是 \(c_i\) 和 \(d_i\) 有单调性,极易让人想到二分。所以我们先枚举第一种法术使用哪个,然后二分找到剩下的法力值所能使用的最优的第二种法术,这里的最优显然是最靠后的也就是 \(d_i\) 最大的。
#include<bits/stdc++.h>
#define int long long//记得开long long
using namespace std;
const int N=2e5+5;
int a[N],b[N],c[N],d[N];
signed main(){
ios::sync_with_stdio(0);
cin.tie(0),cout.tie(0);
int n,m,k,x,s;
cin>>n>>m>>k>>x>>s;
for(int i=1;i<=m;i++)cin>>a[i];
for(int i=1;i<=m;i++)cin>>b[i];
for(int i=1;i<=k;i++)cin>>c[i];
for(int i=1;i<=k;i++)cin>>d[i];
int ans=n*x;//不用法术
for(int i=1;i<=m;i++){//只用一种法术
if(b[i]>s)continue;
ans=min(ans,a[i]*n);
}
for(int i=1;i<=k;i++){
if(d[i]>s)continue;
ans=min(ans,x*max(0ll,n-c[i]));//这里要特判一下,因为题目只要求至少做n瓶,而不是刚好,所以多做几瓶没有问题
}
for(int i=1;i<=m;i++){
if(b[i]>=s)continue;
int st=upper_bound(d+1,d+1+k,s-b[i])-d-1;
//找到能使用的第二种法术中最优的一个
if(!st)continue;
ans=min(ans,a[i]*max(0ll,n-c[st]));
}
cout<<ans;
return 0;
}

浙公网安备 33010602011771号