1 条题解

  • 0
    @ 2025-8-24 22:43:18

    自动搬运

    查看原文

    来自洛谷,原作者为

    avatar 离散小波变换°
    有志不在年高,无志空长百岁

    搬运于2025-08-24 22:43:18,当前版本为作者最后更新于2022-11-27 09:01:05,作者可能在搬运后再次修改,您可在原文处查看最新版

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

    以下是正文


    题解

    贪心题。

    假设 mm 次操作后,剩下来的数字的值域为 [l,r][l,r]。那么原来 aa 数列里,所有严格小于 ll 的数字肯定都被操作了,同时所有严格大于 rr 的数字肯定也被操作了。

    aa 里面一共有 uu 个数严格小于 ll;有 vv 个数严格大于 rr

    断言:所需要的操作次数至少为 u+v+min(u,v)u+v+\min(u,v),并且可以取到。

    证明:如果一个位置在操作后,它的值还在 [l,r][l,r] 之外,那么后面某个时候肯定还要把它进行操作。容易发现,至少前 min(u,v)\min(u,v) 次操作肯定都无法让结果变到 [l,r][l,r] 内。因此执行完这至少 min(u,v)\min(u,v) 次操作后肯定还要再把这 u+vu+v 个数都操作一遍,这是容易做到的(通过 min(u,v)\min(u,v) 次操作,你总能把此时值域的下界提升到 ll 或者把上界降低到 rr)。所以最优决策肯定不会小于 u+v+min(u,v)u+v+\min(u,v) 次。

    那么这题怎么做呢?

    直接将 aa 数组从小到大排序。考虑枚举 l=ail=a_i,计算出最小的 r=ajr=a_j,一定有 (i1)+(nj)+min(i1,nj)m(i-1)+(n-j)+\min(i-1,n-j)\le m。容易发现随着 ii 的增大,jj 肯定是单调不减的。因此首先预处理 j=1j=1,接着随着 ii 的增大找到可以满足条件的最小的 jj。显然当 i>min(n,m+1)i> \min(n,m+1) 时就不存在这样的 jj 了。

    时间复杂度为 O(nlogn)\mathcal O(n\log n),瓶颈在于排序。

    参考代码

    版本 11

    #include<bits/stdc++.h>
    #define up(l, r, i) for(int i = l, END##i = r;i <= END##i;++ i)
    #define dn(r, l, i) for(int i = r, END##i = l;i >= END##i;-- i)
    using namespace std;
    typedef long long i64;
    const int INF = 2147483647;
    int qread(){
        int w=1,c,ret;
        while((c = getchar()) >  '9' || c <  '0') w = (c == '-' ? -1 : 1); ret = c - '0';
        while((c = getchar()) >= '0' && c <= '9') ret = ret * 10 + c - '0';
        return ret * w;
    }
    const int MAXN = 1e5 + 3;
    int A[MAXN], ans = INF;
    int main(){
        int n = qread(), m = qread();
        up(1, n, i) A[i] = qread();
        sort(A + 1, A + 1 + n);
        int j = 1;
        up(1, min(n, m + 1), i){
            j = max(i, j);
            while((i - 1) + (n - j) + min(i - 1, n - j) > m) ++ j;
            ans = min(ans, A[j] - A[i]);
        }
        printf("%d\n", ans);
        return 0;
    }
    

    版本 22

    import java.util.Scanner;
    import java.util.Arrays;
    
    public class Main {
        
        public static int[] a = new int[100005];
    
        public static void main(String[] args) {
            Scanner scanner = new Scanner(System.in);
            int n = scanner.nextInt(), m = scanner.nextInt();
            for (int i = 1; i <= n; ++i)
                a[i] = scanner.nextInt();
            Arrays.sort(a, 1, n + 1);
            int j = 1, ans = Integer.MAX_VALUE;
            for (int i = 1; i <= Math.min(n, m + 1); ++i) {
                j = Math.max(j, i);
                while((i - 1) + (n - j) + Math.min(i - 1, n - j) > m) 
                    ++j;
                ans = Math.min(ans, a[j] - a[i]);
            }
            System.out.println(ans);
        }
    }
    
    • 1

    [传智杯 #5 初赛] D-莲子的物理热力学

    信息

    ID
    8144
    时间
    1000ms
    内存
    512MiB
    难度
    3
    标签
    递交数
    0
    已通过
    0
    上传者