【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
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=s){
				ans=mid;
				r=mid;
				goto next; 
			}
		}
		l=mid+1;
		next: ;
	}
	cout<

所谓的nth_element()作用就是是给定位置的值成为这个位置该有的值.

以后我会单独出一篇专门介绍nth_element文章
供各位学习与交流