二分答案+贪心+longlong快读

Stressful Training

https://ac.nowcoder.com/acm/problem/113525

Stressful Training

题目描述:

Berland SU holds yet another training contest for its students today. nnn students came, each of them brought his laptop. However, it turned out that everyone has forgot their chargers!

Let students be numbered from 111 to nnn. Laptop of the iii-th student has charge aia_iai at the beginning of the contest and it uses bib_ibi of charge per minute (i.e. if the laptop has ccc charge at the beginning of some minute, it becomes c−bic - b_ic−bi charge at the beginning of the next minute). The whole contest lasts for kkk minutes.

Polycarp (the coach of Berland SU) decided to buy a single charger so that all the students would be able to successfully finish the contest. He buys the charger at the same moment the contest starts.

Polycarp can choose to buy the charger with any non-negative (zero or positive) integer power output. The power output is chosen before the purchase, it can't be changed afterwards. Let the chosen power output be xxx. At the beginning of each minute (from the minute contest starts to the last minute of the contest) he can plug the charger into any of the student's laptops and use it for some integer number of minutes. If the laptop is using bib_ibi charge per minute then it will become bi−xb_i - xbi−x per minute while the charger is plugged in. Negative power usage rate means that the laptop's charge is increasing. The charge of any laptop isn't limited, it can become infinitely large. The charger can be plugged in no more than one laptop at the same time.

The student successfully finishes the contest if the charge of his laptop never is below zero at the beginning of some minute (from the minute contest starts to the last minute of the contest, zero charge is allowed). The charge of the laptop of the minute the contest ends doesn't matter.

Help Polycarp to determine the minimal possible power output the charger should have so that all the students are able to successfully finish the contest. Also report if no such charger exists.

题意:

有n台电脑,一共要撑过k分钟
对于每台电脑,他的初始电量为ai,每分钟消耗电量为bi
问,至少需要一个功率(每分钟)为多大的充电器才能保证[0,k)时间内每一台电脑的电量都不为负

思路:

最大功率的最小值,很显然是二分

但是这个题的check函数极其不好写(╥﹏╥)

首先到底给哪个充电?这就是一个贪心,每次都找能坚持的时间最小的那个,如果坚持的时间相同,我们就选bi大的那个,如果bi也相同,我们就选ai小的那个

所以就需要用结构体来存每个电脑的ai,bi和ci(也就是ai / bi)

同时要用一个优先队列/小根堆来维护

维护的东西就是上面写的那个贪心,这里就要写结构体重载,不然塞不进优先队列

对于每次check(x)时,先选出来ci < k的放进优先队列q中,判断一下对列是否为空,空就返回true,从0循环到k-1(从0开始是因为可能有电脑一次都撑不住,k-1是因为最后一次即比赛结束时电量为多少就已经不在乎了),取出队首,扔出去,判断一下此时他的ci是否小于i,小于的话就说明它撑不到给他充电的时候(就是两个电脑同时缺电,但却只有一个充电器,无法撑住),就return false,然后将加上x的点亮的点重新放进优先队列,循环往复……

再就是会有-1的存在,也就是没有能满足的充电器,此时的check返回的是false,所以我们就在true的地放更新ans,对于没有充电器的情况,就不会运行到r = mid + 1 , 就不会改ans的值,就只需要初始化ans为-1即可

再就是这个题比较坑的就是,卡输入,不开快读会TLE,再就是输入的数是1e12,所有得开longlong,所以就得用longlong的快读╮( ̄▽ ̄"")╭

#include <cstdio>
#include <cstring>
#include <string>
#include <cmath>
#include <iostream>
#include <algorithm>
#include <vector>
#include <stack>
#include <queue>
#include <stdlib.h>
#include <sstream>
#include <map>
#include <set>
using namespace std;
#define inf 0x3f3f3f3f
#define MAX 1000000 + 50
#define endl '\n'
#define seed 13331
#define mod 1000000007
#define io ios::sync_with_stdio(false); cin.tie(0); cout.tie(0)
#define mem(a,b) memset((a),(b),sizeof(a))
typedef  long long ll ;
//不开longlong见祖宗!
//inline __int128 read(){__int128 x = 0, f = 1;char ch = getchar();while(ch < '0' || ch > '9'){if(ch == '-'){f = -1;}ch = getchar();}while(ch >= '0' && ch <= '9'){x = x * 10 + ch - '0';ch = getchar();}return x * f;}
//inline void print(__int128 x){if(x < 0){putchar('-');x = -x;}if(x > 9){print(x / 10);}putchar(x % 10 + '0');}
inline ll llRead(){ll x(0), t(1);char o (getchar());while (o < '0' || o > '9') {if (o == '-') {t = -1;}o = getchar();}for (; o >= '0' && o <= '9'; o = getchar()) {x = (x << 1) + (x << 3) + (o ^ 48);}return x * t;}
inline int IntRead(){char ch = getchar();int s = 0, w = 1;while(ch < '0' || ch > '9'){if(ch == '-') w = -1;ch = getchar();}while(ch >= '0' && ch <= '9'){s = s * 10 + ch - '0';ch = getchar();}return s * w;}
inline void write(int x){if (x < 0) {x = ~x + 1; putchar('-');}if (x > 9){write(x / 10);}putchar(x % 10 + '0');}
ll qpow(ll a,ll n){ll ans=1,base=a%mod;while(n){if(n&1)ans=(ans*base)%mod;base=(base*base)%mod;n>>=1;}return ans;}
inline ll gcd(ll x, ll y) { return y ? gcd(y, x % y) : x; }

ll n, k, ans = -1;
struct ran{
    ll a, b, c;
    bool operator < (const ran &X)const{
        if(X.c != c)return c > X.c;
        else if(X.b != b)return b < X.b;
        return a > X.a;
    }
}tr[MAX], now, nextt;

bool check(ll x){
    priority_queue<ran>q;
    for(int i = 1; i <= n; ++i){
        if(tr[i].c < k)q.push(tr[i]);
    }
    if(q.empty())return true;
    for(int i = 0; i < k; ++i){
        now = q.top();q.pop();
        if(now.c < i)return false;
        if((now.a + x) / now.b < k){
            nextt.a = now.a + x;
            nextt.b = now.b;
            nextt.c = nextt.a / nextt.b;
            q.push(nextt);
        }
        if(q.empty())return true;
    }
    return true;
}

int main(){
    n = llRead();k = llRead();
    for(int i = 1; i <= n; ++i)tr[i].a = llRead();
    for(int i = 1; i <= n; ++i){
        tr[i].b = llRead();
        tr[i].c = tr[i].a / tr[i].b;
    }
    ll l = 0, r = 2e12;
    while (l <= r){
        ll mid = (l + r) / 2;
        if(check(mid)){
            ans = mid;
            r = mid - 1;
        }
        else l = mid + 1;
    }
    cout<<ans<<endl;
    return 0;
}
全部评论

相关推荐

大方的大熊猫准备进厂:1.教育背景:你希望从事什么专业的工作你的主修课就是什么;成绩优秀是你应该做的,没什么可描述的,成绩不优秀也许人家在大学忙着创业呢?(成绩优秀不一定是好事,只能说明多元化的大学你上成了高中,没有真正上明白大学,反而体现了你死板,不爱社交,没有别的突出能力) 2.实践经历:你想表达的意思没有说清楚。你是说你会个性化服务,还是你有实习经历。如果没有带来,经济收益,表彰,更好的发展前景,那你还不如说说提升了自己哪些技能。你说有人给你送锦旗我都能明白你优秀,但是你说你会xxxx,你说这话谁信,证据呢。 3.入伍经历:你描述的就是你的工作职责或者你应该做的,并没有体现出来你把这个事情做好了,而且入伍经历并不能证明你能干好你要应聘的工作,不如只写经历其余所有内容都不写。 4.荣誉技能:重点突出一下,但不要过多描述,这些荣誉的含金量懂得都懂。 重点:你要应聘什么工作(具体岗位,实习生不具体),你的期望薪资
点赞 评论 收藏
分享
头顶尖尖的程序员:我也是面了三四次才放平心态的。准备好自我介绍,不一定要背熟,可以记事本写下来读。全程控制语速,所有问题都先思考几秒,不要急着答,不要打断面试官说话。
点赞 评论 收藏
分享
评论
1
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务