目录
题目链接
挖矿https://www.lanqiao.cn/problems/19717/learning/
问题描述
小蓝正在数轴上挖矿,数轴上一共有 n 个矿洞,第 i 个矿洞的坐标为 ai 。 小蓝从 0 出发,每次可以向左或向右移动 1 的距离,当路过一个矿洞时,就会进行挖矿作业,获得 1 单位矿石,但一个矿洞不能被多次挖掘。小蓝想知道在移动距离不超过 m 的前提下,最多能获得多少单位矿石?
输入格式
输入的第一行包含两个正整数 n,m,用一个空格分隔。
第二行包含 n 个整数 a1,a2,⋯,an,相邻整数之间使用一个空格分隔。
输出格式
输出一行包含一个整数表示答案。
样例输入
5 4
0 -3 -1 1 2
样例输出
4
样例说明
路径:0→−1→0→1→2,可以对 0,−1,1,2 四个矿洞挖掘并获得最多 4 块矿石。
评测用例规模与约定
对于 20% 的评测用例,1≤n≤103;
对于所有评测用例,1≤n≤105,−106≤ai≤106,1≤m≤2×106 。
运行限制
语言 | 最大运行时间 | 最大运行内存 |
---|---|---|
C++ | 1s | 256M |
C | 1s | 256M |
Java | 3s | 512M |
Python3 | 10s | 512M |
PyPy3 | 3s | 512M |
Go | 5s | 512M |
JavaScript | 5s | 512M |
代码思路
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
public class Main {
static BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
static PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out));
public static void main(String[] args) throws Exception {
String[] s = in.readLine().split(" ");
int n = Integer.parseInt(s[0]);
int m = Integer.parseInt(s[1]);
// 记录每个坐标有几个矿石
int[] z = new int[1000005];
int[] f = new int[1000005];
// 前缀和数组
int[] sumz = new int[m + 1];
int[] sumf = new int[m + 1];
// 记录坐标零位置有几个矿石
int a0 = 0;
s = in.readLine().split(" ");
for (int i = 0; i < n; i++) {
int t = Integer.parseInt(s[i]);
if (t > 0)
z[t]++;
else if (t < 0)
f[-t]++;
else
a0++;
}
// 计算前缀和
for (int i = 1; i <= m; i++) {
sumz[i] = z[i] + sumz[i - 1];
sumf[i] = f[i] + sumf[i - 1];
}
// 枚举找出最大值
int max = Math.max(sumz[m], sumf[m]);
for (int i = 0; 2 * i <= m && i < m; i++) {
max = Math.max(sumz[i] + sumf[m - 2 * i], max);
max = Math.max(sumf[i] + sumz[m - 2 * i], max);
}
System.out.println(max + a0);
}
}