二分答案+贪心+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; }