2021 12-1 序列查询
- 题解1
- 题解2
- 区别
- 第一种算法:
- 第二种算法:
题解1
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
// 输入n表示商品数目,N表示总数
int n = sc.nextInt();
int N = sc.nextInt();
int[] A = new int[n + 1]; // 存储价格的数组,注意要多一个位置用于存储0
// 输入n个商品的价格
for (int i = 1; i <= n; i++) {
A[i] = sc.nextInt();
}
int sum = 0; // 存储 sum(A) 的值
int curMax = 0; // 当前最大值的下标,初始化为0
// 遍历 [0, N) 的范围
for (int x = 0; x < N; x++) {
// 找到小于等于x的最大值的下标
while (curMax + 1 <= n && A[curMax + 1] <= x) {
curMax++;
}
sum += curMax; // 将当前最大值的下标累加到sum中
}
System.out.println(sum); // 输出结果
sc.close();
}
}
题解2
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
// 输入n表示商品数目,N表示总数
int n = sc.nextInt();
int N = sc.nextInt();
int[] arr = new int[n + 1]; // 存储价格的数组,注意要多一个位置用于存储0
// 输入n个商品的价格
for (int i = 1; i <= n; i++) {
arr[i] = sc.nextInt();
}
int sum = 0; // 存储 sum(A) 的值
int temp = 0; // 暂存当前最大值的下标
// 遍历 [0, N) 的范围
for (int i = 0; i < N; i++) {
if (i < arr[n]) {
// 如果i小于数组中的最大值,且等于arr[temp+1]时,temp加1
if (i == arr[temp + 1]) {
temp++;
}
sum += temp; // 将temp累加到sum中
} else {
// 如果i大于等于数组中的最大值,计算剩余的值并加到sum中,跳出循环
sum += (N - arr[n]) * (temp + 1);
break;
}
}
System.out.println(sum); // 输出结果
sc.close();
}
}
区别
第一种算法:
使用了差分数组的思想,通过差分数组记录了每个时间段内的能出行的个数。
遍历每个出行计划,将每个计划对应的时间段进行标记,标记出行计划所需的时间段。
根据差分数组的性质,对于每个时间点,差分数组记录了该时间点前面的出行计划所覆盖的时间段个数,从而实现了查询时间点时的高效计算。
第二种算法:
在对每个时间点进行查询时,遍历了商品价格的数组,根据当前时间点和商品价格的关系来计算sum。
在遍历过程中,记录了当前最大值的下标temp,并根据temp来确定sum的值,即根据每个时间点对应的商品价格来确定sum的值。
总的来说,第一种算法更加直接且高效,通过差分数组记录时间段的出行计划个数,从而实现了O(1)时间复杂度内的查询。而第二种算法则需要对每个时间点都遍历整个商品价格数组来计算sum,效率较低。