【ybtoj】二分算法-最小时间
最小时间
题目描述
有n个物品,第i个物品有两个属性k,b,表示它在时刻 的价值为k*x+b。
当前处于时刻0,你可以选择不超过m个物品,使得存在非负整数时刻t,你选择的所有物品的总价值大于等于S。
给出S,求t的最小值。
输入格式
第一行三个整数n,m,S。
接下来n行,第i行两个整数k,b。
输出格式
一行一个整数表示答案。
样例 1 输入
3 2 100 3 9 -2 50 4 1
样例 1 输出
13
样例 1 解释:
选择1,3号物品。
样例 2 输入
3 2 100 -1 49 -2 50 1 -998244353
样例 2 输出
998244453
样例 2 解释:
选择3号物品。
分析
选择任何一个集合,得到的收益和都可以表示为一个一次函数的形式.我们只关心这些一次函数的最大值,可以发现这个最大值一定是先降后升的(也有可能是单调递增或单调递减).
因此我们只需要check一下0时刻是否符合条件,如果不符合则进行二分.
注意check的时候我们只需要找出最大的m个即可,因此可以O(n)地做.具体做法是快排的时候只递归一边,当然你不需要手写,直接用STL的nth_element()即可
Code:
点击查看代码
#include<bits/stdc++.h> using namespace std; long long k[1000086],b[1000086],h[1000086]; bool cmp(long long x,long long y){//cmp排序 return x>y; } long long l=0,r=1e9; long long mid; long long sum=0; long long ans=0; int main(){ long long n,m,s; cin>>n>>m>>s; for (int i=1;i<=n;i++){ cin>>k[i]>>b[i]; } while(l<r){ mid=(l+r)/2; sum=0; for (int i=1;i<=n;i++){ h[i]=k[i]*mid+b[i]; } nth_element(h+1,h+m,h+1+n,cmp); for (int i=1;i<=m;i++){ if(h[i]<0)continue; sum+=h[i]; if(sum>=s){ ans=mid; r=mid; goto next; } } l=mid+1; next: ; } cout<<ans; return 0; } ``` ``` </details> 所谓的nth_element()作用就是是给定位置的值成为这个位置该有的值. 以后我会单独出一篇专门介绍nth_element文章 供各位学习与交流
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】