CF981F 二分+Hall定理

对于一个二分的答案

假设存在一个点集使得不满足Hall定理

题中给定的信息说明 左边每个点对应的右边点是一个区间

如果当前点集对应的右边区间是若干个不相交的区间组成的话说明我们还可以找到一个更小的点集使得其也不满足Hall定理

假设我们当前找到了一个极小的不满足Hall定理的点集 其对应的右边区间如上所证一定是一段连续的区间

如果这个极小的点集不是一段连续的区间的话 我们可以加入一些点 使得左边的点集变成连续的一段区间而右边对应的点集不变

得证:在题中,如果有一个点集不满足Hall定理 则必定存在一个区间也不满足Hall定理

则对于任意的i,j(i<j) 要有R[j]-L[i]>=j-i

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int n, L;
ll a[400005];
ll b[800005];
bool check(int x)
{
    int maxn = -INT_MAX;
    int l = 1, r = 1;
    for (int i = 1; i <= 2 * n; i++) {
        while (l <= 4 * n && b[l] < a[i] - x) {
            l++;
        }
        while (r <= 4 * n && b[r] <= a[i] + x) {
            r++;
        }
        maxn = max(l - i, maxn);
        if (r - i - 1 < maxn) {
            return false;
        }
    }
    return true;
}
int main()
{
    scanf("%d %d", &n, &L);
    for (int i = 1; i <= n; i++) {
        scanf("%lld", &a[i]);
    }
    for (int i = 1; i <= n; i++) {
        scanf("%lld", &b[i]);
    }
    sort(a + 1, a + 1 + n);
    sort(b + 1, b + 1 + n);
    for (int i = 1; i <= n; i++) {
        a[i] += L, a[i + n] = a[i] + L;
    }
    for (int i = 1; i <= 3 * n; i++) {
        b[i + n] = b[i] + L;
    }
    int l = -1, r = L;
    while (l < r - 1) {
        int mid = (l + r) >> 1;
        if (check(mid)) {
            r = mid;
        } else {
            l = mid;
        }
    }
    printf("%d
", r);
}
View Code
原文地址:https://www.cnblogs.com/Aragaki/p/10645636.html