分析
比较简单的贪心题。我们考虑到二分一个答案 。那么存在 也是成立的。所以这个是具有单调性的。那么为了让所有的点都是合法的。那么肯定要拿出最近一个将要不合法的节点让他的电量 。那么当第 次充电时发现最近的节点没电的时间在 之前,则是个非法答案。那么我们算法就是如果快速找到第一个将要不合法的点。这里考虑用 来维护就好了。那么总的复杂度为 。
- 还有一些减枝的小技巧,就看代码了。
代码
#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; }