题解 CF538H 【Summer Dichotomy】

· · 题解

CF538H Summer Dichotomy

题意

题解

先不考虑 t,T 的限制,可以证明 n_1 = \min_{i=1}^n r_in_2 = \max_{i=1}^n l_i 是最优的。

证明如下:

将所有 [l_i, r_i] 当作一条数轴上的线段,那么有三种情况:

  1. 有三条线段两两不交,则无解。
  2. 所有线段两两有交,即有 n_1 \ge n_2,则在这种情况下,每个老师都可以随意的选择小组。

因此 n_1 = \min_{i=1}^n r_in_2 = \max_{i=1}^n l_i 一定是最优的。

如果考虑 t,T 的限制呢?可以发现,若 n_1 + n_2 < t,则无论哪种情况下,只增大 n_2 是最优的;若 n_1 + n_2 > T,则无论哪种情况下,只减小 n_1 的最优的。

因此我们可以直接求出最优的 n_1,n_2,最后做一次二分图染色即可。

时间复杂度 \mathcal O(n+m)

代码

#define Fail return prints("IMPOSSIBLE"), 0

const int N = 1e5 + 7;
int t, T, n, m, l[N], r[N], n1 = 1e9 + 1, n2 = -1, c[N];
vi e[N];

inline bool pd(int x, int i) {
    return l[i] <= x && x <= r[i];
}

bool dfs(int x) {
    for (auto y : e[x])
        if (!c[y]) {
            c[y] = 3 - c[x];
            if (!dfs(y)) return 0;
        } else if (c[x] == c[y]) return 0;
    return 1;
}

int main() {
    rd(t), rd(T), rd(n), rd(m);
    for (int i = 1; i <= n; i++)
        rd(l[i]), rd(r[i]), n1 = min(n1, r[i]), n2 = max(n2, l[i]);
    if (n1 + n2 < t) n2 = t - n1;
    if (n1 + n2 > T) n1 = T - n2;
    if (n1 < 0 || n2 < 0) Fail;
    for (int i = 1; i <= n; i++) {
        bool o1 = pd(n1, i), o2 = pd(n2, i);
        if (!o1 && !o2) Fail;
        if (o1 && !o2) c[i] = 1;
        if (!o1 && o2) c[i] = 2;
    }
    for (int i = 1, x, y; i <= m; i++)
        rd(x), rd(y), e[x].pb(y), e[y].pb(x);
    for (int i = 1; i <= n; i++) if (c[i] && !dfs(i)) Fail;
    for (int i = 1; i <= n; i++)
        if (!c[i]) {
            c[i] = 1;
            if (!dfs(i)) Fail;
        }
    string ans = "";
    for (int i = 1; i <= n; i++) ans += c[i] + '0';
    prints("POSSIBLE"), print(n1, ' '), print(n2), prints(ans); 
    return 0;
}