Cnoi2020 领域极限

发布时间 2023-07-20 18:34:56作者: Ender_32k

应该是最简单的做法,同时也是 AT 官方题解做法。

考虑计算 \(\min\sum\limits_{1\le i\le j\le n}|a_i-a_j|\),乘二即为答案。

考虑 \(n\) 个线段中使 \(l_x\) 最大的 \(x\) 以及使 \(r_y\) 最小的 \(y\)

  • \(l_x\le r_y\),那么 \(\forall i\in [1,n],l_i\le l_x,r_i\ge r_y\),则 \(a_i\)\([l_x,r_y]\) 之间的任意数即可,答案为 \(0\)
  • 否则 \(l_x>r_y\),画图发现此时任意 \([l_i,r_i]\) 都与 \([r_y,l_x]\) 有交。所以任意的 \(a_i\) 都能取到 \([r_y,l_x]\) 之间的某个值。所以 \(|a_i-a_x|+|a_i-a_y|=|a_x-a_y|\)

那么我们把 \([r_y,l_x]\) 的贡献拎出来单独考虑,设剩下的 \(n-2\)\(l_{\max},r_{\min}\) 的贡献为 \(T\),此时的答案为:

\[\begin{aligned}&T+|a_x-a_y|+\sum\limits_{i\neq x,y}(|a_i-a_x|+|a_i-a_y|)\\=\quad&T+(n-1)|a_x-a_y|\end{aligned} \]

由于 \(a_x,a_y\) 对后续的统计没有影响了,直接令 \(a_x=l_x,a_y=r_y\)

\[\text{ans}=T+(n-1)(l_x-r_y) \]

所以我们每次拿出一个 \(l_{\max},r_{\min}\),计算这对 \(l,r\) 的贡献,然后再把这对 \(l,r\) 从数组中删去,不断重复这个过程直到 \(l_{\max}\le r_{\min}\) 即可。

因为这个过程中 \([r_{\min},l_{\max}]\) 这个区间始终是不断缩紧的,所以每个剩下的 \(a_i\) 都能满足在任意时刻能取在 \([r_{\min},l_{\max}]\) 之间。

复杂度 \(O(n\log n)\),瓶颈在于排序。

const int N = 3e5 + 300;
int n, l[N], r[N];

int main() {
    n = rd();
    for (int i = 1; i <= n; i++)
        l[i] = rd(), r[i] = rd();
    sort(l + 1, l + n + 1, greater<int> ());
    sort(r + 1, r + n + 1);
    ll res = 0;
    for (int i = 1; i <= n; i++) {
        if (l[i] <= r[i]) break;
        res += 1ll * (l[i] - r[i]) * (n - 2 * i + 1);
    }
    wr(res * 2);
    return 0;
}