CF1907D 题解
题意:
有 \(n\) 条线段,初始时在原点。每次可以任意条长度不超过 \(k\) 的一步,但是要满足跳了第 \(i\) 步之后要站在第 \(i\) 条线段上,求最小的 \(k\) 使得可以把所有线段跳完。
题解:
易于发现的,如果已经证明 \(k=x\) 时满足,大于 \(x\) 的一定成立,即答案具有单调性。
考虑二分答案,判断是否合法时,我们维护当前可以跳到的最左的位置和最右的位置,初值为 \(l=r=0\),这样可以维护出下一步的区间,更改时与 \(l,r\) 直接取 \(\max\) 或 \(min\) 即可。
这样判断的复杂度明显 \(O(n)\),所以是 \(O(n\log w)\)。
#include<algorithm>
#include<iostream>
const int inf = 1e9;
int t, n, l[200005], r[200005];
inline bool ck(int x){
int ls = 0, rs = 0;
for(int i = 1; i <= n; i++){
ls = std::max(0, ls - x);
rs = std::min(inf, rs + x);
if(l[i] > rs || r[i] < ls) return 0;
ls = std::max(ls, l[i]);
rs = std::min(rs, r[i]);
} return 1;
}
int main(){
std::ios::sync_with_stdio(false);
std::cin.tie(0);std::cout.tie(0);
std::cin >> t;
while(t--){
std::cin >> n;
for(int i = 1; i <= n; i++)
std::cin >> l[i] >> r[i];
int ls = 0, rs = inf, as;
while(ls <= rs){
int md = ls + rs >> 1;
if(ck(md)) as = md, rs = md - 1;
else ls = md + 1;
}
std::cout << as << '\n';
}
}

浙公网安备 33010602011771号