CF1132D Stressful Training
题目大意
有台电脑,一共要撑过
分钟
对于每台电脑,他的初始电量为,每分钟消耗电量为
问,至少需要一个功率(每分钟)为多大的充电器才能保证的电量都不为负
分析
按照贪心的思想,对于每一分钟,充电器应该用给那个还能坚持的时间最小的那个
这一定是一个必要操作,正确性显然
对于初始电量可以撑过分钟的电脑,可以忽略不管
那么对于两种功率的充电器,可以简单证明,如果
可以满足条件,则
一定满足条件
这满足二分答案的性质
所以就可以用二分答案来求得需要的答案(二分右界设为无穷大)
对于操作,可以用一个优先队列/小根堆之类的东西来维护
首先表示的是这台电脑能用多久,显然是要
小的在堆顶
然后弹出堆顶,给他冲的电量,在丢回堆
对于相等的电脑,是要让
大的在前面;
对于都相等的电脑,就是让
小的在前面
这样的贪心应该不需要多解释了
于是,在函数中,就可以枚举时间
只要在某一时刻,堆顶的小于了当前时间,即可
return false
只要在某一时刻,堆中没有元素了,即可return true
然后,给堆顶的电脑冲点电,整理一下堆,就可以了
时间复杂度
Code
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 2e5 + 10;
const int mod = 1e9 + 7;
inline ll __read()
{
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;
}
int n, k;
ll a[maxn], b[maxn];
ll l(0), r(2e12), ans(-1);
struct Node {
ll a, b, c;
Node () {}
Node (ll a, ll b, ll c) : a(a), b(b), c(c) {}
bool operator < (const Node &T) const {
if (c ^ T.c) return c > T.c;
else if (b ^ T.b) return b < T.b;
return a > T.a;
}
};
inline bool Check(ll x)
{
priority_queue <Node> Q;
for (int i = 1; i <= n; ++i)
if (a[i] / b[i] < k) Q.push(Node(a[i], b[i], a[i] / b[i]));
if (Q.empty()) return 1;
for (int i = 0; i < k; ++i) {
Node temp = Q.top();
Q.pop();
if (temp.c < i) return 0;
if ((temp.a + x) / temp.b < k) Q.push(Node(temp.a + x, temp.b, (temp.a + x) / temp.b));
if (Q.empty()) return 1;
}
return 1;
}
signed main()
{
n = __read(), k = __read();
for (int i = 1; i <= n; ++i) a[i] = __read();
for (int i = 1; i <= n; ++i) b[i] = __read();
while (l <= r) {
ll mid ((l + r) >> 1);
if (Check(mid)) ans = mid, r = mid - 1;
else l = mid + 1;
}
printf ("%lld\n", ans);
system("pause");
} 
京公网安备 11010502036488号