https://codeforces.com/contest/1132/problem/D
题题意是有n台笔记本,要同时使用k个时间,每个时间可以给一台电脑充电x电量,求最小的x使得n台笔记本可以度过k时间。
显然 x越大越好,如果有答案,一定在某个值刚好成立,线性问题,直接二分x。
首先想法是维护一个还能使用时间最小的电脑(a[i]/b[i])最小,然后模拟,贪心的给能存活时间最短的电脑优先充电。
坑的地方是,multiset不能过(直接卡到22组,预先sort卡到27组),
优先队列或线段树(维护最小值)可以过。 (???)
https://blog.csdn.net/ccsu_cat/article/details/88310531(线段树也几乎是卡死)
贴优先队列代码(小心数据范围可能有爆的地方)
复杂度(O(K*log(ans)*log(n))
#include<bits/stdc++.h>
using namespace std;
#define LL long long
struct no{
LL a;
LL b;
LL c;
}lap[200005];
bool operator<(const no &x,const no &y){
return x.c>y.c;
}
int n,k;
bool check(LL mid){
priority_queue<no> q;
for(int i=1;i<=n;i++) q.push(lap[i]);
for(LL i=1;i<k;i++){
no cur=q.top();q.pop();
cur.a=cur.a+mid;
cur.c=cur.a/cur.b;
q.push(cur);
if(q.top().c<i) return 0;
}
return 1;
}
LL binary(){
LL l=0,r=1e13;
LL ans=LLONG_MAX;
while(l<=r){
LL mid=(l+r)/2;
if(check(mid)){
ans=mid;
r=mid-1;
}
else l=mid+1;
}
return ans;
}
int main(){
ios::sync_with_stdio(false);
cin>>n>>k;
for(int i=1;i<=n;i++) cin>>lap[i].a;
for(int i=1;i<=n;i++) {
cin>>lap[i].b;
lap[i].c=lap[i].a/lap[i].b;
}
LL ans=binary();
if(ans==LLONG_MAX) cout<<-1;
else cout<< ans;
return 0;
}
题解有一种复杂度(O(K*log(ans))的做法
用vector维护小于生命期小于k的电脑的编号。 v[i] 里面放 当前生命期为i天的 电脑编号,然后模拟一遍写check。
By RSHS, contest: Educational Codeforces Round 61 (Rated for Div. 2), problem: (D) Stressful Training, Accepted, #
#include<bits/stdc++.h>
using namespace std;
#define LL long long
const int maxn=2*1e5+5;
int n,k;
LL a[maxn],b[maxn];
vector<int> v[maxn];
bool check(LL mid){
for(int i=0;i<=k;i++) v[i].clear();
LL cnt[maxn];
for(int i=1;i<=n;i++){
LL x=a[i]/b[i];
if(x>=k) continue;
cnt[i]=a[i]%b[i];
v[x].push_back(i);
}
int p=0;
for(LL i=0;i<k;i++){
while(v[p].size()==0&&p<k)
p++;
if(p==k) break;
int u=v[p].back();
v[p].pop_back();
LL newa=p*b[u]+cnt[u]+mid;
LL uu=newa/b[u];
if(uu<k){
v[uu].push_back(u);
cnt[u]=newa%b[u];
}
if(v[i].size()!=0) return false;
}
return true;
}
LL binary(){
LL l=0,r=1e15;
LL ans=LLONG_MAX;
while(l<=r){
LL mid=(l+r)/2;
if(check(mid)){
ans=mid;
r=mid-1;
}
else l=mid+1;
}
return ans;
}
int main(){
ios::sync_with_stdio(false);
cin>>n>>k;k--;
for(int i=1;i<=n;i++) cin>>a[i];
for(int i=1;i<=n;i++) cin>>b[i];
LL ans=binary();
if(ans==LLONG_MAX) cout<<-1;
else cout<< ans;
return 0;
}
优先队列(几乎卡死)
vector模拟优化