题目链接:https://vjudge.net/problem/CodeForces-1132D
题意:给n个笔记本,每个笔记本有初始电量ai和每个时间点耗电量bi,要求在整个会议k个时间内,给出最小单位时间充电量x来保证每台笔记本在每个时间点都是有电的(电量>=0),每个时间点只可以给一台笔记本充x电量。
解题思路:先求出每个笔记本在什么时候电量耗尽需要充电,即ai/bi+1,然后按需要充电的时间点从小到大排序,即最需要充电的放在前面,这里直接利用优先队列就可以,遍历每个时间点1到k,如果当前笔记本需要充电的最晚时间比i小的话,那么就说明无法满足。但当前的笔记本最晚充电时间已经超过了k或者遍历了每个时间点没有出现不满足条件的情况,那么说明所有的笔记本都能够满足条件。
PS:注意没有一台笔记本需要充电的情况
然后利用二分利用上面的思路去寻找需要的最合适的答案即可,ans初始化为-1(方便找不到答案时候-1的直接输出),L=0,R=max(bi)*k或者取一个特别大的数比如1e13也可以。
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<queue>
#include<vector>
using namespace std;
#define maxn 210000
#define ll long long
struct node{
ll a;
ll b;
ll cnt;
}lt[maxn];
ll maxr;
int n,k;
int len;
struct cmp{
bool operator ()(const node a,const node b) const{
return a.cnt>b.cnt;
}
};
int check(ll x){
priority_queue<node,vector<node>,cmp> q;
for(int i=1;i<=n;i++){
if(lt[i].cnt<=k)
q.push(lt[i]);
}
if(q.empty())
return 1;
for(int i=1;i<=k;i++){
node tmp=q.top();
q.pop();
if(tmp.cnt>k)
return 1;
if(tmp.cnt<i){
return 0;
}
tmp.a+=x;
tmp.cnt=tmp.a/tmp.b+1;
q.push(tmp);
}
return 1;
}
int main(){
scanf("%d%d",&n,&k);
for(int i=1;i<=n;i++)
scanf("%lld",<[i].a);
for(int i=1;i<=n;i++){
scanf("%lld",<[i].b);
lt[i].cnt=lt[i].a/lt[i].b+1;
maxr=max(maxr,lt[i].b*k);
}
ll L=0;
ll R=maxr;
ll ans=-1;
while(L<=R){
ll mid=(L+R)/2;
if(check(mid)){
R=mid-1;
ans=mid;
}
else
L=mid+1;
}
printf("%lld\n",ans);
return 0;
}