分析
比较简单的贪心题。我们考虑到二分一个答案 。那么存在
也是成立的。所以这个是具有单调性的。那么为了让所有的点都是合法的。那么肯定要拿出最近一个将要不合法的节点让他的电量
。那么当第
次充电时发现最近的节点没电的时间在
之前,则是个非法答案。那么我们算法就是如果快速找到第一个将要不合法的点。这里考虑用
来维护就好了。那么总的复杂度为
。
- 还有一些减枝的小技巧,就看代码了。
代码
#include<bits/stdc++.h>
using namespace std;
#define LL long long
const LL N = 2e5 + 100;
struct Node{
LL a,b,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;
}
};
LL read() {
LL x = 0,f = 0;char ch = getchar();
while(!isdigit(ch)) {if(ch == '-')f = 1;ch = getchar();}
while(isdigit(ch)) {x = x * 10 + ch - '0';ch = getchar();}
return f ? -x : x;
}
LL n,m,a[N],b[N];
bool check(LL mid) {
priority_queue<Node> Q;
for(LL i = 1;i <= n;i++) {
if(a[i] / b[i] < m) Q.push((Node){a[i],b[i],a[i]/b[i]});
}
if(Q.empty()) return true;
for(LL i = 0;i < m;i++) {
Node x = Q.top();Q.pop();
if(x.c < i) return false;
if((x.a + mid) / x.b < m) Q.push((Node){x.a + mid,x.b,(x.a + mid)/x.b});
if(Q.empty()) return true;
}
return true;
}
int main() {
n = read();m = read();
for(LL i = 1;i <= n;i++) a[i] = read();
for(LL i = 1;i <= n;i++) b[i] = read();
LL l = 0,r = 2e12,ans = -1;
while(l <= r) {
LL mid = l + r >> 1;
if(check(mid)) ans = mid,r = mid - 1;
else l = mid + 1;
}
printf("%lld\n",ans);
return 0;
}
京公网安备 11010502036488号