2 条题解

  • 1
    @ 2026-9-30 16:13:26

    对于每对 (xi,yi)(x_i,y_i),可以看成一个区间 [xi,yi][x_i,y_i],问让所有的 cic_i 至少属于一个 [xj,yj][x_j,y_j],求∑yi−xi\sum{y_i-x_i}。

    对于每个相邻的 cic_i 到 ci+1c_{i+1},如果它们被分到了不同的区间里,那么这两个区间之间就不需要覆盖这段空隙,相当于从总长度里省掉了 ci+1−cic_{i+1}-c_i

    所以问题就变成了:排序后,把 nn 个点分成至多 kk 段,每段用一个区间覆盖,代价是这一段的最大值减最小值。要最小化总代价。

    先把 cc 从小到大排序。现在有 kk 个区间,相当于把序列切成 kk 段。每切一刀,就会少覆盖一个相邻空隙。

    总代价可以写成:

    (cn−c1)−∑被切掉的相邻空隙(c_n-c_1)-\sum \text{被切掉的相邻空隙}

    我们要让总代价最小,也就是要让被切掉的相邻空隙之和最大。因为最多切成 kk 段,所以最多只能切 k−1k-1 刀。于是贪心地选最大的 k−1k-1 个相邻空隙切掉即可。

    所以最终答案:

    $$ans=(c_n-c_1)-\sum_{i=1}^{k-1} \text{第 } i \text{ 大的相邻差}$$

    如果 k≥nk\ge n,每个点都可以单独用一个长度为 00 的区间覆盖,答案就是 00。

        if(k>=n){puts("0");return 0;} 
        sort(c+1,c+1+n);
        for(int i=1;i<n;i++)
            l[i]=c[i+1]-c[i];
        sort(l+1,l+1+n,cmp);
        long long ans=c[n]-c[1];
        for(int i=1;i<=k-1;i++) ans-=l[i];
        cout<<ans;
    

    这里 l[i]l[i] 就是相邻两个点之间的距离,排序后,前 k−1k-1 个就是最大的 k−1k-1 个空隙。 注意答案要用 long long,因为 cic_i 可以到 10910^9,总长度可能到 101410^{14} 级别。

    • -2
      @ 2026-9-29 17:16:00

      题解

      1. 把题目翻译成“区间覆盖”

      题目要求:

      xi≤yix_i\le y_i

      并且对于每个 cic_i,至少存在一个 jj,满足:

      xj≤ci≤yjx_j\le c_i\le y_j

      注意:

      xj≤ci≤yjx_j\le c_i\le y_j

      就等价于:

      ci∈[xj,yj]c_i\in[x_j,y_j]

      所以每一对 (xj,yj)(x_j,y_j) 就可以看成一个区间:

      [xj,yj][x_j,y_j]

      题目实际上是在问:

      用kk 个区间覆盖所有的 cic_i,使这些区间长度之和最小。

      2. 先把所有 cic_i 排序

      假设排序后:

      a1≤a2≤⋯≤ana_1\le a_2\le\cdots\le a_n

      相同的数没有必要重复考虑,所以可以去重:

      a1<a2<⋯<ama_1<a_2<\cdots<a_m

      例如:

      原序列:
      -5 0 10 4 0
      
      排序:
      -5 0 0 4 10
      
      去重:
      -5 0 4 10
      

      3. 一个区间覆盖哪些数?

      假设一个区间:

      [x,y][x,y]

      覆盖了 (a_l) 和 (a_r)。

      因为:

      al≤al+1≤⋯≤ara_l\le a_{l+1}\le\cdots\le a_r

      所以中间所有数也一定满足:

      x≤ai≤yx\le a_i\le y

      也就是说:

      一个区间覆盖排序后的数时,它覆盖的一定是一段连续的数。

      例如:

      -5   0   4   10
      |---------|
      

      如果覆盖 -5 和 4,那么 0 也必然被覆盖。


      4. 一个区间覆盖一段数时,最优怎么取?

      假设一个区间负责:

      al,al+1,…,ara_l,a_{l+1},\dots,a_r

      那么必须有:

      x≤alx\le a_l

      以及:

      y≥ary\ge a_r

      我们要最小化:

      y−xy-x

      所以显然应该让区间刚好贴住两边:

      x=al,y=arx=a_l,\qquad y=a_r

      此时贡献:

      y−x=ar−aly-x=a_r-a_l

      因此:

      覆盖一段数的最小代价,就是这一段最大值减最小值。


      5. 分段

      这是这题最重要的一步。

      题目允许不同区间互相重叠,例如:

      [1,5][1,5]

      和

      [4,10][4,10]

      假设:

      x1≤x2≤y1≤y2x_1\le x_2\le y_1\le y_2

      两个区间为:

      [x1,y1],[x2,y2][x_1,y_1],\quad[x_2,y_2]

      它们有重叠部分。

      原来的代价:

      (y1−x1)+(y2−x2)(y_1-x_1)+(y_2-x_2)

      把它们合并成:

      [x1,y2][x_1,y_2]

      代价:

      y2−x1y_2-x_1

      两者之差:

      (y1−x1)+(y2−x2)−(y2−x1)=y1−x2(y_1-x_1)+(y_2-x_2)-(y_2-x_1) =y_1-x_2

      因为:

      x2≤y1x_2\le y_1

      所以:

      y1−x2≥0y_1-x_2\ge0

      因此:

      y2−x1≤(y1−x1)+(y2−x2)y_2-x_1 \le (y_1-x_1)+(y_2-x_2)

      也就是说:

      两个重叠区间合并之后,答案不会变差。

      所以我们总能找到一个最优方案,使有效区间之间没有重叠。

      于是排序后的:

      a1,a2,…,ama_1,a_2,\dots,a_m

      就可以看成被分成若干连续段。

      例如:

      a1 a2 a3 | a4 a5 | a6 a7
      

      每一段对应一个区间。

      而且如果最后只用了少于 kk 个区间,多出来的区间可以取:

      x=yx=y

      它的长度是 (0),不会影响答案。

      所以实际上是:

      最多使用 kk 段。


      6. 一个区间

      如果只使用一个区间,那么它必须覆盖:

      a1,…,ama_1,\dots,a_m

      所以区间就是:

      [a1,am][a_1,a_m]

      答案:

      am−a1a_m-a_1

      例如:

      -5  0  4  10
      

      一个区间:

      [-5,10]
      

      代价:

      10−(−5)=1510-(-5)=15

      7. 如果增加一个区间呢?

      现在允许使用两个区间。

      假设在:

      ai, ai+1a_i,\ a_{i+1}

      之间切一刀:

      a1 a2 ... ai | ai+1 ... am
      

      那么两个区间的代价:

      (ai−a1)+(am−ai+1)(a_i-a_1)+(a_m-a_{i+1})

      原来一个区间的代价:

      am−a1a_m-a_1

      两者相差:

      (am−a1)−[(ai−a1)+(am−ai+1)](a_m-a_1) - [(a_i-a_1)+(a_m-a_{i+1})]

      整理:

      =ai+1−ai=a_{i+1}-a_i

      所以:

      在 aia_i 和 ai+1a_{i+1} 之间切一刀,可以节省 ai+1−aia_{i+1}-a_i。


      8. 应该在哪里切?

      我们有:

      a1<a2<⋯<ama_1<a_2<\cdots<a_m

      相邻差分别是:

      $$a_2-a_1,\quad a_3-a_2,\quad \dots,\quad a_m-a_{m-1}$$

      如果允许使用 kk 个区间,就最多可以切:

      k−1k-1

      刀。

      每切一刀,就节省一个相邻差。

      所以为了让最终答案最小,我们应该选择:

      最大的 k−1 个相邻差\boxed{\text{最大的 }k-1\text{ 个相邻差}}

      9. 为什么选最大的?

      假设所有相邻差为:

      5  4  6
      

      如果只能切一刀:

      • 切 5,答案减少 5
      • 切 4,答案减少 4
      • 切 6,答案减少 6

      当然应该选择 6。

      所以就是:

      $$\text{答案} = (a_m-a_1) - \text{最大的 }k-1\text{ 个相邻差之和}$$

      如果不同的数只有 (m) 个,那么最多只能切 (m-1) 刀,因此实际切刀数为:

      min⁡(k−1,m−1)\min(k-1,m-1)

      10

      具体做法非常简单:

      1. 读入所有 (c_i)。
      2. 排序。
      3. 扫一遍,跳过重复元素。
      4. 计算相邻不同元素之间的差值。
      5. 将这些差值从大到小排序。
      6. 初始答案为最大值减最小值。
      7. 减去最大的 (k-1) 个差值。
      8. 如果不同元素数量不足 (k),就全部切掉。
      • @ 2026-9-30 15:55:54

        AITJ? 太长了很啰嗦。

      • @ 2026-10-2 14:15:32

        @ 确实很长

    • 1

    信息

    ID
    2766
    时间
    1000ms
    内存
    128MiB
    难度
    4
    标签
    (无)
    递交数
    16
    已通过
    11
    上传者