1 条题解
-
0
自动搬运
来自洛谷,原作者为

离散小波变换°
有志不在年高,无志空长百岁搬运于
2025-08-24 22:43:18,当前版本为作者最后更新于2022-11-27 09:01:05,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
题解
贪心题。
假设 次操作后,剩下来的数字的值域为 。那么原来 数列里,所有严格小于 的数字肯定都被操作了,同时所有严格大于 的数字肯定也被操作了。
设 里面一共有 个数严格小于 ;有 个数严格大于 。
断言:所需要的操作次数至少为 ,并且可以取到。
证明:如果一个位置在操作后,它的值还在 之外,那么后面某个时候肯定还要把它进行操作。容易发现,至少前 次操作肯定都无法让结果变到 内。因此执行完这至少 次操作后肯定还要再把这 个数都操作一遍,这是容易做到的(通过 次操作,你总能把此时值域的下界提升到 或者把上界降低到 )。所以最优决策肯定不会小于 次。
那么这题怎么做呢?
直接将 数组从小到大排序。考虑枚举 ,计算出最小的 ,一定有 。容易发现随着 的增大, 肯定是单调不减的。因此首先预处理 ,接着随着 的增大找到可以满足条件的最小的 。显然当 时就不存在这样的 了。
时间复杂度为 ,瓶颈在于排序。
参考代码
版本 :
#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; }版本 :
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
信息
- ID
- 8144
- 时间
- 1000ms
- 内存
- 512MiB
- 难度
- 3
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者