

这道题很容易就想到暴力的三层循环,但是根据输入描述中的范围描述,可以知道如果在暴力三层循环下的最坏情况可以到达10^25,这是一定会超时的,因此我们必须来进行优化,它的优化方法是我在网上看到的,我今天就是来进行一个解释,各位网友也可以去看看别人写的,基本上都是这么做的。
import java.util.*;
// 1:无需package
// 2: 类名必须Main, 不可修改
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
//在此输入您的代码...
int N = sc.nextInt();
int[] A = new int[N];
int[] B = new int[N];
int[] C = new int[N];
for(int i = 0; i < N; i++){
A[i] = sc.nextInt();
}
for(int i = 0; i < N; i++){
B[i] = sc.nextInt();
}
for(int i = 0; i < N; i++){
C[i] = sc.nextInt();
}
Arrays.sort(A);
Arrays.sort(B);
Arrays.sort(C);
long sum = 0;
int p = 0;
int q = 0;
for(int i = 0; i < N; i++){
while(p < N && A[p] < B[i]){
p++;
}
while(q < N && C[q] <= B[i]){
q++;
}
sum += 1L * p * (N - q);
}
System.out.print(sum);
sc.close();
}
}
在这里是采取的将三个数组都进行排序,这是很容易想到的一个优化办法,但是仅仅只是靠这个优化是远远起不到效果的,重头戏是在while循环里。
通过采取将B数组作为中间枢纽,循环遍历每一个B数组中的数,分别从A数组中找到比B小的数,在C数组中,这里是通过侧面来寻找,因为sort排序后数组里的数都是从小到大排的,因此我们只能从侧面先找到比B数组中小或等于的数的个数来找到大于B数组中的数,最后在总和起来,有一个很重要的一点,就是为什么要把p和q写在while循环外,事实上,这也是一个优化点,因为所有的数组都是排好序了的,因此在遍历到B数组后面的数的时候,假如说是B[j],因为B[j]大于B[j-1],因此原来在A数组中小于B[j-1]的数现在仍然小于B[j],继续往后遍历,原来大于B[j-1]的数现在可能是小于B[j]中的数,直接在原有的基础上继续累加就可以了,同理对于C数组也是这也样,原来小于等于B[j-1]的数现在仍然是小于B[j]的,但是原来大于B[j-1]的数现在不一定大于B[j],因此也是要在原来的基础上来进行计算。
上面的每一个优化点都缺一不可,少了一个可能导致超时之类的错误。
以上便是我对此题代码的解释,希望能给大家提供到了帮助,如果有不对的地方,请大家指出。