- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
目标
我正在解决 this问题:
Little Girl and Maximum Sum
The little girl loves the problems on array queries very much.
One day she came across a rather well-known problem: you've got an array of n elements (the elements of the array are indexed starting from 1); also, there are q queries, each one is defined by a pair of integers li, ri (1 ≤ li ≤ ri ≤ n). You need to find for each query the sum of elements of the array with indexes from li to ri, inclusive.
The little girl found the problem rather boring. She decided to reorder the array elements before replying to the queries in a way that makes the sum of query replies maximum possible. Your task is to find the value of this maximum sum.
Input The first line contains two space-separated integers n (1 ≤ n ≤ 2·105) and q (1 ≤ q ≤ 2·105) — the number of elements in the array and the number of queries, correspondingly.
The next line contains n space-separated integers ai (1 ≤ ai ≤ 2·105) — the array elements.
Each of the following q lines contains two space-separated integers li and ri (1 ≤ li ≤ ri ≤ n) — the i-th query.
Output In a single line print a single integer — the maximum sum of query replies after the array elements are reordered.
r
和
l
值)。
200000 200000
189622 189286 194361 184457 182376 183471 197548 184736 195806 ... 200,000 integers
188738 290041
33738 90041
122738 390041
... 200,000 line
import java.util.Arrays;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int n = scanner.nextInt();
int q = scanner.nextInt();
int[] array = new int[n];
for (int i=0; i<n; i++) {
array[i] = scanner.nextInt();
}
int[][] qArray = new int[q][2];
for (int i=0; i<q; i++) {
qArray[i][0] = scanner.nextInt();
qArray[i][1] = scanner.nextInt();
}
int[] index = new int[n];
Arrays.sort(array);
for (int i=0; i<q; i++) {
for (int j = qArray[i][0]-1; j<qArray[i][1]; j++) {
index[j]++;
}
}
Arrays.sort(index);
long sum =0;
for (int i = 0; i<n; i++) {
sum += index[i]*array[i];
}
System.out.println(sum);
}
}
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;
public class Main {
public static void main(String[] args) {
try {
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
String input = bufferedReader.readLine();
String[] SplitInput = input.split(" ");
int n = Integer.parseInt(SplitInput[0]);
int q = Integer.parseInt(SplitInput[1]);
String input2 = bufferedReader.readLine();
int[][] qArray = new int[q][2];
for (int i=0; i<q; i++) {
input = bufferedReader.readLine();
SplitInput = input.split(" ");
qArray[i][0] = Integer.parseInt(SplitInput[0]);
qArray[i][1] = Integer.parseInt(SplitInput[1]);
}
String[] SplitInput2 = input2.split(" ");
int[] array = new int[n];
for(int i=0; i<n; i++){
array[i] = Integer.parseInt(SplitInput2[i]);
}
int[] index = new int[n];
Arrays.sort(array);
for (int i=0; i<q; i++) {
for (int j = qArray[i][0]-1; j<qArray[i][1]; j++) {
index[j]++;
}
}
Arrays.sort(index);
long sum = 0;
for (int i=0; i<n; i++) {
sum += index[i]*array[i];
}
System.out.println(sum);
}
catch (NumberFormatException ex) {
System.out.println("Not a number !");
}
catch (IOException e) {
e.printStackTrace();
}
}
}
7 Time: 2000 ms, memory: 20612 KB Verdict: TIME_LIMIT_EXCEEDED
7 Time: 2000 ms, memory: 41340 KB Verdict: TIME_LIMIT_EXCEEDED
最佳答案
免责声明,我说我能够帮助你,我是,但我不能为你解决。我无法将其限制在 2 秒以内,因为我没有正确理解问题本身。我理解你的算法在技术上的作用,但我在概念上理解它有问题,这让我无法找到 大优化。我发现了很大的优化。见答案底部。
备注:我已经在测试页面上看到了较小测试的结果,并且绝对没有理由为什么您的第一次测试持续 200+ 毫秒。我就是不明白。它们在我的计算机上的运行时间始终低于 2 毫秒(使用 Java 内部 System.nanotime()
方法)。我相信测试包括JVM的启动。如果确实如此,我是否建议您改用更优化的语言,例如 C 或 C++ ?这意味着该测试在某种程度上是针对解释性语言的。
算法
第一个问题是你的算法本身。它很慢:您实际上是在迭代 200,000 × x
int
s(这是您文件中的平均高值)。在最坏的情况下,您将迭代 200,000 × 200,000 = 40,000,000,000 个整数。难怪你有 20 秒左右的时间。
那太过分了。理想情况下,您应该能够使用优化(例如使用 map )来减少双循环。您可以使用大量内存 (256 MB),请使用它。你已经做到了;多做。
最大的优化就在这里。我相信,不是通过索引递增索引,您应该通过跳过此索引机制并使用更好的机制来找到另一种优化。我相信这就是问题存在的原因:找到那个算法而不是其他算法。我不喜欢那样,但我不评判它。
读取数据
我测试了通过输入读取数据,你的方法很慢。我责怪你使用了 Scanner
.
我建议您使用这种结构和这种拆分方法,它们在我的计算机上运行总时间小于 100 毫秒,并带有您的大测试文件(我坚持认为……我的计算机不是您的计算机,我们的计算机也不是您评估测试的计算机) .我相信它可以进一步减少,但我会说它已经足够好了。这不是我们正在寻找的大优化,但我相信它是第二个。
try (BufferedReader reader = new BufferedReader(new InputStreamReader(System.in))) {
int[] counts = split(reader.readLine(), new int[2]);
int n = c[0], q = c[1];
int[] array = split(reader.readLine(), new int[n]);
int[][] queries = new int[q][]; // Note, no size in the second part of the array creation.
for (int i = 0; i < q; i++) {
queries[i] = split(reader.readLine(), new int[2]);
}
...
}
static int[] split(String s, int[] a) {
int n = 0, aIndex = 0;
for (int sIndex = 0, sLength = s.length(); sIndex < sLength; sIndex++) {
char c = s.charAt(sIndex);
if (c == ' ') { // Separator
a[aIndex++] = n;
n = 0;
} else if ('0' <= c && c <= '9') { // Number
n = n * 10 + (c - '0'); // Add a digit to the current number
}
}
a[aIndex] = n;
return a;
}
for (int i = 0; i < q; i++) {
// Fill qArray
}
for (int i = 0; i < q; i++) {
// Work with index.
}
qArray
的需要。 .您读取数据,然后直接处理它。如果循环彼此相邻,这并不重要,但是在第一次尝试对数组中的内容进行排序之间,并且在第二次尝试中对数组进行排序和解析输入之间。这一方面使您的数据远离 CPU 缓存,但另一方面您正在处理 I/O。我不知道哪个更好。
sum += (long)(index[i]) * array[i];
public static void main(String[] args) throws IOException {
long nanos = System.nanoTime();
myMain();
nanos = System.nanoTime() - nanos;
System.out.printf("Time: %sms%n", MILLISECONDS.convert(nanos, NANOSECONDS));
}
static void myMain() throws IOException {
try (BufferedReader reader = new BufferedReader(new InputStreamReader(System.in))) {
int[] counts = split(reader.readLine(), new int[2]);
int n = counts[0], q = counts[1];
int[] array = split(reader.readLine(), new int[n]);
int[] indices = new int[n];
for (int i = 0; i < q; i++) {
int[] query = split(reader.readLine(), new int[2]);
indices[query[0] - 1]++;
if (query[1] < n) {
indices[query[1]]--;
}
}
for (int i = 1; i < n; i++) {
indices[i] += indices[i - 1];
}
sort(array, 200_000);
sort(indices, 200_000);
long sum = 0;
for (int i = 0; i < n; i++) {
sum += (long)array[i] * indices[i];
}
System.out.println(sum);
}
}
static void sort(int[] array, int n) {
int[] counts = new int[n+1];
for (int element: array) {
counts[element]++;
}
int current = 0;
for (int i = 0; i < counts.length; i++) {
Arrays.fill(array, current, current + counts[i], i);
current += counts[i];
}
}
static int[] split(String s, int[] a) {
int n = 0, aIndex = 0;
for (int sIndex = 0, sLength = s.length(); sIndex < sLength; sIndex++) {
char c = s.charAt(sIndex);
if (c == ' ') {
a[aIndex++] = n;
n = 0;
} else if ('0' <= c && c <= '9') {
n = n * 10 + (c - '0');
}
}
a[aIndex] = n;
return a;
}
关于java - 在不到 2 秒的时间内从控制台读取 600,000 个输入,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36521853/
您好,我是使用 xampp 的 PHPmyadmin 新手,没有 MYSQL 背景。当我喜欢研究它是如何工作的时,我的脑海中浮现出一个想法,它让我一周都无法休眠,因为我似乎无法弄清楚如何使用 MIN(
Go docs say (强调): Programs using times should typically store and pass them as values, not pointers.
我有一组用户在 8 月 1 日有一个条目。我想找到在 8 月 1 日有条目但在 8 月 2 日没有做任何事情的用户。 现在是 10 月,所以事件已经过去很久了。 我有限的知识说: SELECT * F
我有以下代码,主要编码和取消编码时间结构。这是代码 package main import ( "fmt" "time" "encoding/json" ) type chec
您能详细解释一下“用户 CPU 时间”和“系统 CPU 时间”吗?我读了很多,但我不太理解。 最佳答案 区别在于时间花在用户空间还是内核空间。用户 CPU 时间是处理器运行程序代码(或库中的代码)所花
应用程序不计算东西,但做输入/输出、读取文件、使用网络。我希望探查器显示它。 我希望像 callgrind 中的东西一样,在每个问题中调用 clock_gettime。 或者像 oprofile 那样
目前我的 web 应用程序接收 websocket 数据来触发操作。 这会在页面重新加载时中断,因此我需要一个能够触发特定事件的客户端解决方案。 这个想法可行吗? 假设你有 TimeX = curre
很难说出这里问的是什么。这个问题是含糊的、模糊的、不完整的、过于宽泛的或修辞性的,无法以目前的形式得到合理的回答。如需帮助澄清此问题以便重新打开它,visit the help center 。 已关
我有一个 Instant (org.joda.time.Instant) 的实例,我在一些 api 响应中得到它。我有另一个来自 (java.time.Instant) 的实例,这是我从其他调用中获得
如何集成功能 f(y) w.r.t 时间;即 'y'是一个包含 3000 个值和值 time(t) 的数组从 1 到 3000 不等。所以,在整合 f(y) 后我需要 3000 个值. 积分将是不确定
可以通过 CLI 创建命名空间,但是如何使用 Java SDK 来创建命名空间? 最佳答案 它以编程方式通过 gRPC API 完成由服务公开。 在 Java 中,生成的 gRPC 客户端可以通过 W
我有一个函数,它接受 2 组日期(开始日期和结束日期),这些日期将用于我的匹配引擎 我必须知道start_date1和end_date1是否在start_date2和end_date2内 快进:当我在
我想从 Python 脚本运行“time”unix 命令,以计算非 Python 应用程序的执行时间。我会使用 os.system 方法。有什么方法可以在Python中保存这个输出吗?我的目标是多次运
我正在寻找一种“漂亮的数字”算法来确定日期/时间值轴上的标签。我熟悉 Paul Heckbert's Nice Numbers algorithm . 我有一个在 X 轴上显示时间/日期的图,用户可以
在 PowerShell 中,您可以格式化日期以返回当前小时,如下所示: Get-Date -UFormat %H 您可以像这样在 UTC 中获取日期字符串: $dateNow = Get-Date
我正在尝试使用 Javascript 向父子窗口添加一些页面加载检查功能。 我的目标是“从父窗口”检测,每次子窗口完全加载然后执行一些代码。 我在父窗口中使用以下代码示例: childPage=wi
我正在尝试设置此 FFmpeg 命令的 drawtext 何时开始,我尝试使用 start_number 但看起来它不会成功。 ffmpeg -i 1.mp4 -acodec aac -keyint_
我收到了一个 Excel (2010) 电子表格,它基本上是一个文本转储。 单元格 - J8 具有以下信息 2014 年 2 月 4 日星期二 00:08:06 EST 单元格 - L8 具有以下信息
我收到的原始数据包含一列具有以下日期和时间戳格式的数据: 2014 年 3 月 31 日凌晨 3:38 单元格的格式并不一致,因为有些单元格有单个空格,而另一些单元格中有两个或三个字符之间的空格。所以
我想知道是否有办法在我的 Grails 应用程序顶部显示版本和构建日期。 编辑:我应该说我正在寻找构建应用程序的日期/时间。 最佳答案 在您的主模板中,或任何地方。 Server version:
我是一名优秀的程序员,十分优秀!