zoukankan      html  css  js  c++  java
  • 2018 雅礼国庆集训

    Merchant

        有n个物品,第i个物品有两个属性ki , bi,表示它在时刻x的价值为ki × x + bi . 当前处于时刻0,你可以选择不超过m个物品,使得存在某个整数时刻t, t ≥ 0,你选择的 所有物品的总价值大于等于S. 给出S,求t的最小值。

       很容易想到几个物品加起来的时候,价值是一个一次函数(合并同类项)

       然后画一下图可以发现(然而我考试时并没有发现),在同一个x坐标下对应一个最大值,这个最大值是先减后增的。

       所以我们可以先判断一下0时刻,如果可以就输出0,不然就二分

      每一次判断的时候算出此时的价值,然后用一个骚操作nth_element, 可以求出前m个最大的,复杂度O(n)

    #include<bits/stdc++.h>
    #define REP(i, a, b) for(register int i = (a); i < (b); i++)
    #define _for(i, a, b) for(register int i = (a); i <= (b); i++)
    using namespace std;
    
    typedef long long ll;
    const int MAXN = 1e6 + 10;
    int k[MAXN], b[MAXN], n, m;
    ll c[MAXN], s;
    
    bool check(int t)
    {
    	ll sum = 0;
    	REP(i, 0, n) c[i] = 1ll * k[i] * t + b[i];
    	nth_element(c, c + m, c + n, greater<ll>()); //从大到小 
    	REP(i, 0, m) 
    		if((sum += c[i]) >= s) //注意可能后面的值为负,所以不一定全部加完才最大 
    		 return true;
    	return false;
    }
    
    int main()
    {
    	scanf("%d%d%lld", &n, &m, &s);
    	REP(i, 0, n) scanf("%d%d", &k[i], &b[i]);
    	if(check(0)) { puts("0"); return 0; }
    
    	int l = 0, r = 1e9 + 1;
    	while(l + 1 < r)
    	{
    		int m = (l + r) >> 1;
    		if(check(m)) r = m;
    		else l = m;
    	}
    	printf("%d
    ", r);
    
    	return 0;
    }

       

  • 相关阅读:
    python中的itertools模块简单使用
    SQLServer链接服务器
    @Valid和@Validated的区分总结
    禅道完成高成资本独家领投的数千万元融资
    青岛敏捷之旅,来了!
    linux主机互信操作
    小白学标准库之 mux
    小白学标准库之 flag
    音频截取分割打点标注工具
    大数据可能面试题
  • 原文地址:https://www.cnblogs.com/sugewud/p/9819312.html
Copyright © 2011-2022 走看看