补一下去年集训的题目。
AtCoder Problems 评分: 1853 \color{Blue}{1853} 1853。
看到最小值最大,考虑二分答案。
先按横坐标从小到大排序,横坐标相同按纵坐标从小到大排序。
二分一个答案 m i d mid mid,考虑双指针进行 check。 l l l 为双指针维护的左端点, r r r 为右端点,首先跳 r r r 保证 ∣ x r − x l ∣ ≥ m i d \left| x_r - x_l\right| \ge mid ∣xr−xl∣≥mid 始终成立。再跳 l l l 记录 y l y_l yl 的最小值与最大值。对于每个 r r r,当 l l l 不能再跳的时候比较一下 y l y_l yl 的最小值和最大值与 y r y_r yr 的差值是否大于等于 m i d mid mid,如果是,返回 1 1 1。当 r r r 跳到 n n n 时还没有返回,返回 0 0 0。
check 代码:
bool check (LL delta)
{
LL minv = 1e14, maxv = 0;
for (int l = 1, r = 1; r <= n; r++)
{
while (l < r && a[r].x - a[l].x >= delta)
{
minv = min (minv, a[l].y);
maxv = max (maxv, a[l].y);
l++;
}
if (maxv - a[r].y >= delta) return true;
if (a[r].y - minv >= delta) return true;
}
return false;
}
二分代码:
LL l = 0, r= 1e14;
while (l < r)
{
LL mid = (l + r + 1) >> 1;
if (check(mid)) l = mid;
else r = mid - 1;
}
printf("%lld", l);
完整代码,时间复杂度 O ( n log V ) O(n\log V) O(nlogV), V V V 为 x , y x,y x,y 的值域。