题目描述
假定有一个无限长的数轴,数轴上每个坐标上的数都是0。
现在,我们首先进行 n 次操作,每次操作将某一位置x上的数加c。
接下来,进行 m 次询问,每个询问包含两个整数l和r,你需要求出在区间[l, r]之间的所有数的和。
输入格式
第一行包含两个整数n和m。
接下来 n 行,每行包含两个整数x和c。
再接下里 m 行,每行包含两个整数l和r。
输出格式
共m行,每行输出一个询问中所求的区间内数字和。
数据范围
−109≤x≤109,
1≤n,m≤105,
−109≤l≤r≤109,
−10000≤c≤10000
5
样例
输入样例:
3 3
1 2
3 6
7 5
1 3
4 6
7 8
输出样例:
8
0
思想
存储所有出现的坐标值,然后排序,离散化到新数组,将坐标对应的值存入前缀和数组,根据lr在离散化数组中找到下标,然后根据前缀和计算差值。
1、利用TreeMap将所有的(x,c)存储起来平均O(nlogn)
2、区间l,r将他们作为键值存储到TreeMap;平均O(mlogm),他们所对应的值不变,并且将区间(l,r)作为查询键值对存储到集合O(m)
3、根据map的value值集合构造前缀和数组O(n + m)
4、根据map的key键集合构造查询数组O(n + m)
5、根据集合的键值对在查询数组中查找对应的离散化下标O(mlog(n+m))
6、根据前缀和进行计算
时间复杂度
总的时间复杂度O(nlogn) + O(nlogn) + O(m) + 2O(n + m) + O(mlog(n+m)) 抽象为 O(nlogn)
java 代码
//离散化
import java.io.*;
import java.lang.Integer;
import java.util.*;
class Node{//键值对相当于c++的pair<int, int>
public int first;
public int second;
public Node(int first, int second){
this.first = first;
this.second = second;
}
}
class Main{
static int N = 300010;
static int[] sum = new int[N];//离散数组,存储前缀和
static TreeMap<Integer, Integer> map = new TreeMap<>();//存储坐标和长度
static ArrayList<Node> query = new ArrayList<>();//用于查询 相当于c++的vector<pair<int,int>>
static int binserySearch(Integer[] index, int x){//二分查找
int l = 0, r = index.length - 1;
while(l < r){
int mid = l + r >> 1;
if(index[mid] < x)l = mid + 1;
else r = mid;
}
return l;
}
public static void main(String[] args)throws Exception{
BufferedReader buf = new BufferedReader(new InputStreamReader(System.in));
String[] params = buf.readLine().split(" ");
int n = Integer.valueOf(params[0]);
int m = Integer.valueOf(params[1]);
for(int i = 0; i < n; ++i){
String[] xc = buf.readLine().split(" ");
int x = Integer.valueOf(xc[0]);
int c = Integer.valueOf(xc[1]);
map.put(x, map.getOrDefault(x, 0) + c);
}
for(int i = 0; i < m; ++i){
String[] lr = buf.readLine().split(" ");
int l = Integer.valueOf(lr[0]);
int r = Integer.valueOf(lr[1]);
map.put(l, map.getOrDefault(l, 0));
map.put(r, map.getOrDefault(r, 0));
query.add(new Node(l, r));
}
int k = 1;
for(int num : map.values()){
sum[k] = sum[k - 1] + num;
k++;
}
Object[] obj = map.keySet().toArray();
Integer[] index = Arrays.copyOfRange(obj, 0, obj.length, Integer[].class);
for(Node node : query){
int x1 = binserySearch(index, node.first);
int x2 = binserySearch(index, node.second);
int res = sum[x2 + 1] - sum[x1];
System.out.printf("%d\n", res);
}
}
}
超时了