1 条题解

  • 0
    @ 2025-8-24 22:25:52

    自动搬运

    查看原文

    来自洛谷,原作者为

    avatar Sampson_YW
    你弱归你弱,YW比你弱。

    搬运于2025-08-24 22:25:52,当前版本为作者最后更新于2023-07-08 19:45:46,作者可能在搬运后再次修改,您可在原文处查看最新版

    自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多

    以下是正文


    首先按 ll 从小到大排序。

    最小化最大值,考虑二分答案。那么就要对当前二分的答案 midmid 构造一组方案。

    我们从小到大依次枚举每个位置,并确定这个位置应该选哪个区间。

    假设当前枚举到位置 ii, 如果选择一个区间,那么其他与它有交的区间能填的位置不能超过 i+midi+mid

    fxf_x 表示区间 xx 最远能填哪里,记 sk=x=1n[fx=k]s_k = \sum_{x=1}^n[f_x=k]

    我们找到最小的 jj 使得 k=ijsk=ji+1\sum_{k=i}^j s_k = j - i + 1,显然所有 ff 值在 [i,j][i, j] 之间的区间都必须填到 [i,j][i,j] 中。

    那么无解的条件就是存在一个 pp 使得 k=ipsk>pi+1\sum_{k=i}^p s_k > p - i + 1

    我们贪心地选择区间,从 ff 值在 [i,j][i,j] 之间的区间中选择 rr 最小的区间填到位置 ii 上,因为这样会使与位置 ii 相交的区间越少,受限制的区间数量就越少。

    这样即可在 O(n2)O(n^2) 的时间内完成一次答案的构造。使用两棵线段树分别查找最小的 jj 和右端点最小的区间可优化至 O(nlogn)O(n\log n)

    具体地,对于查找最小的 jj,先将每个 sis_i 减一,那么对于一个 ii,要找的 jj 就满足 k=ijsk=0\sum_{k = i}^j s_k = 0,线段树维护区间和与区间前缀和的最小值,线段树上二分即可做到 O(nlogn)O(n \log n)

    对于找 rr 最小的区间,要满足 ff 值不超过 jj

    由于序列按照 ll 排序,所以每次填一个区间 [Lx,Rx][L_x, R_x],都会对 lRxl\leq R_x 的前缀产生限制。所以排序后序列的 ff 值是单调不降的。我们直接对这个前缀 chkmin 即可。那么会不会出现与 [Lx,Rx][L_x, R_x] 无交的区间被 chkmin\text{chkmin} 使得答案变劣呢?答案是不会的。

    因为我们贪心地让 rr 小的尽量往前填,所以 lRxl \leq R_x 的区间,要么与 [Lx,Rx][L_x, R_x] 有交,要么在之前就填过了。否则就会出现一个与 [Lx,Rx][L_x, R_x] 无交且没有填的区间 [Ly,Ry][L_y, R_y],满足 LyLxL_y\leq L_x,那么显然 RyRxR_y\leq R_x。由于 [Lx,Rx][L_x,R_x] 能填且序列的 ff 值单调不降,所以 fyfxjf_y \leq f_x \leq j,即 [Ly,Ry][L_y, R_y] 也能填且更优,这与我们的贪心策略矛盾,所以不会出现无交且没填的区间。

    第二棵线段树维护序列中没有被填过且 rr 最小的区间。

    由于我们从小到大填,所以每个 ff 每个只会被 chkmin\text{chkmin} 一次,用一个指针 tt 维护第一个还没被 chkmin\text{chkmin} 的位置,设 gig_i 表示最后一个 f=if=i 的位置。

    对于要填的位置 ii,我们用第一棵线段树找到 jj,然后在第二棵线段树上查前缀 gjg_jrr 最小的区间 [Lx,Rx][L_x, R_x],然后将 xx 删除,向后移动指针,更新 ftf_t 并修改第一棵线段树,直到 Lt>RxL_t>R_x,此时更新 gi+mid=t1g_{i + mid} = t - 1

    总复杂度 O(nlog2n)O(n\log^2 n)Code

    此题弱化版:CF309E Sheepn2000n\leq 2000

    • 1

    信息

    ID
    6173
    时间
    10000ms
    内存
    128MiB
    难度
    6
    标签
    递交数
    0
    已通过
    0
    上传者