概述:
区间和是在无限长度的数轴上,稀疏的排布若干点,点的总数与数轴的范围相差甚大。求任意一个区间内所有点的和即位区间和。
思路:
采用映射的思想。将数轴上的每个点都映射到一个连续的空间内,然后使用二分的方法去查找到映射的索引,使用前缀和的思想去存储区间内的值。
具体步骤如下:
代码如下:
package cn.liyi.day08;
import java.util.*;
public class Demo802 {
public static void main(String[] args) {
int N = 300010;
int[] a = new int[N];
int[] s = new int[N];
List<Integer> alls = new ArrayList<>();
List<PIIs> adds = new ArrayList<>(); //在那个索引值位置插入,并且插入了哪个值
List<PIIs> query = new ArrayList<>(); //询问区间的边界,左边界和右边界
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int m = sc.nextInt();
for (int i = 0; i < n; i++) {
int x = sc.nextInt(); //这是需要插入的坐标
int c = sc.nextInt(); //这是插入的值
adds.add(new PIIs(x, c));
alls.add(x);
}
for (int i = 0; i < m; i++) {
int l = sc.nextInt();
int r = sc.nextInt();
query.add(new PIIs(l, r));
alls.add(l);
alls.add(r);
}
//去重
Collections.sort(alls);
System.out.println("排序之后为:");
for(int i = 0; i < alls.size(); i ++) {
System.out.print(alls.get(i) + " ");
}
System.out.println("======================");
int unique = unique(alls);
alls = alls.subList(0, unique);
for(int i = 0; i < alls.size(); i ++) {
System.out.print(alls.get(i) + " ");
}
System.out.println("======================");
//找到映射好的坐标,然后将C加上坐标上
for (PIIs items : adds) {
int x = find(items.getFirst(), alls);
System.out.println("此时find找到的是:" + x);
a[x] += items.getSecond();
}
for(int i = 1; i <= alls.size(); i ++){
s[i] += s[i - 1] + a[i];
System.out.println(s[i]);
}
System.out.println("====================");
for(PIIs items : query) {
int l = find(items.getFirst(), alls);
int r = find(items.getSecond(), alls);
System.out.println("此时找到的左右边界对应的s索引为:" + l + " " + r);
System.out.println(s[r] - s[l - 1]);
}
}
//返回的是整个List中有多少个不重复的元素
public static int unique(List<Integer> list) {
int j = 0;
for(int i = 0; i < list.size(); i ++){
if(i == 0 || list.get(i) != list.get(i - 1)){
list.set(j ++, list.get(i));
}
}
return j;
}
public static int find(int x, List<Integer> alls) {
int l = 0;
int r = alls.size() - 1;
while (l < r) {
int mid = l + r >> 1;
if(alls.get(mid) >= x){
r = mid;
}else{
l = mid + 1;
}
}
return r + 1;
}
}