CodeForce-801C Voltage Keepsake(二分)

题目大意:有n个装备,每个设备耗能为每单位时间耗能ai,初始能量为bi;你有一个充电宝,每单位时间可以冲p能量,你可以在任意时间任意拔冲。

如果可以所有设备都可以一直工作下去,输出-1;否则,输出所有设备都同时工作的最长时间。

思路提示:想象这样一个场景,每当一个设备没电时,你就拔掉你正在充电的设备,冲到这个设备上。可是,天有不测风云,突然某一刻,有2个以上设备同时没电,那至少有一个设备得停止工作。这一刻也就是答案,让我们来看一看这一刻的状况,设这一刻为t,充电宝总共供能t*p,这时t*p==sum(a[i]*t)-sum(b[i]);当t*p<sum(a[i]*t)-sum(b[i])说明t比答案大;当t*p>sum(a[i]*t)-sum(b[i])说明,t比答案小。

方法:在实数域上二分,不断逼近答案。

#include<iostream>
#include<cstdio>
#define ll long long
using namespace std;
const int N=1e5+5;
const double eps=1e-4;//精度
int n,p;
int a[N],b[N];
int check(double mid)
{
    double E=mid*p;
    for(int i=0;i<n;i++)
    {
        double e=b[i]-a[i]*mid;
        if(e<0)E+=e;
        if(E<0)return 0;//如果充电宝的能量不足以供应,说明mid太大
    }
    return 1;//否则mid太小
}
int main()
{
    cin>>n>>p;
    ll sum=0;
    for(int i=0;i<n;i++)
    {
        cin>>a[i]>>b[i];
        sum+=a[i];
    }
    if(sum<=p)
    {
        cout<<-1<<endl;
        return 0;
    }
    double low=0,high=1e18;
    double mid;
    while(high-low>=eps)//实数域上的二分不可能为0,只能以精度控制
    {
        mid=(high+low)/2;
        if(check(mid))low=mid;
        else high=mid;
    }
    cout<<mid<<endl;
    return 0;
}
时间: 2024-08-28 18:06:25

CodeForce-801C Voltage Keepsake(二分)的相关文章

Codeforces 772A Voltage Keepsake - 二分答案

You have n devices that you want to use simultaneously. The i-th device uses ai units of power per second. This usage is continuous. That is, in λ seconds, the device will use λ·ai units of power. The i-th device currently has bi units of power store

Codeforces 801C Voltage Keepsake 结构体sort排序+贪心

#include <bits/stdc++.h> using namespace std; struct In{ long long a, b; double t; }s[100005]; bool cmp(In p, In q) { if(p.t < q.t) return true; else if(p.t == q.t && p.a < q.a) return true; return false; } int main() { long long n, p;

codeforce 702C Cellular Network 二分答案

http://codeforces.com/contest/702 题意:n个村庄,m个机站,问机站最短半径覆盖完所有村庄 思路:直接二分答案 二分太弱,调了半天..... 1 // #pragma comment(linker, "/STACK:102c000000,102c000000") 2 #include <iostream> 3 #include <cstdio> 4 #include <cstring> 5 #include <s

Codeforces Round #409 (Div. 2)

这是一次血崩的cf,脑子不好使了.读题读错...代码写错...查不出错...WAWAWA 这次题比较常规.前二题很简单,第三题二分,第四题数学. A - Vicious Keyboard[暴力模拟] 题意: 改变最多一个字符,让字符串中出现最多的"VK". PS: 比赛时做法是先走一遍字符串找"VK",标记已经构成"VK"的位置.再跑一遍字符串, 如果出现a[i]和a[i-1]都没标记过,而且a[i-1]=='V' 或a[i]=='K'时,结果+

CodeForces 801C 二分,浮点数

CodeForces 801C 题意: n个设备,第 i个设备每秒用电a[i],原本储存电量b[i].只有一个充电器,每秒可给一个设备充电 p.所有的设备要同时工作,问最多可以工作多长时间? tags:就是二分,但写挂了好多发.. 坑点: 1.右边界会爆1e9 ... 2.担心 double 会丢失精度,用了 long double. 然后long double ,头文件 #include <iomanip.h> .一开始用 printf("%.6Lf\n", r)输出,在

Codeforce 371C Hamburgers (二分答案)

题目链接 Hamburgers 二分答案,贪心判断即可. 1 #include <bits/stdc++.h> 2 3 using namespace std; 4 5 #define REP(i,n) for(int i(0); i < (n); ++i) 6 #define LL long long 7 8 char str[1010]; 9 LL len; 10 LL b, c, s, nb, nc, ns, pb, pc, ps; 11 LL money; 12 13 bool

Codeforce 487B Strip 动归+二分+线段树

写完之后的第一感觉就是我又写麻烦了...写了两棵线段树维护信息... dp[i] 表示[1,i]这段前缀的最优解,若dp[i] = INF,表示无解. 特殊的,dp[0] = 0. 那么,有一个思路就是我们有一些长度为设dp[i]已知且dp[i] != INF,那么设我们知道一个位置R,满足[i+1,R]这一段区间可以划分到一段,i+1 <= R <= n,且R-i >= l. 那么我们将dp[i+1],dp[i+2]...dp[R]分别更新为min(dp[i+1],dp[i]+1),m

二分题 D - Salary Changing codeforce

题意:给出n个人(n是奇数),s钱:s为总的可以付工钱的钱: 每一个工人有一个付工钱的区间,只要在这个区间范围内,随便一个数都可以当作给这个工人付了钱: 老板要付给每个工人钱,并且付钱的中位数要尽可能大: 问:最大的中位数是多少: 思路:贪心+思维+二分: 我们以中位数为主体进行二分.那么就需要n/2+1个大于等于中位数的数: 这个时候我们先给钱排序,按第一个数从大到小排: 然后check部分,从1到n遍历,如果满足x在区间范围内,就取x这个数: 那么,为什么就要取这个数呢,因为我们迟早要凑到n

codeforce 285 div2 D 题解

codeforce 285 div2 D 题解 说明 这道题目是看了思路分析才知道的,关键问题在于数据量过大,需要快速检索的同时不能辅助空间过大. 因此利用了下面3种方法结合解决该问题 康拓展开与逆康拓展开 树状数组 二分查找 代码 /** * @brief Codeforces Round #285 (Div. 2) d * @file d.cpp * @author mianma * @created 2015/01/27 18:18 * @edited 2015/01/29 22:45 *