当一个集合里,个数少,但是值的范围大,并且我们做题需要利用这些值为下标。比如我们总不可能开一个长度为10的9次方的数组。此时我们就需要离散化。 也就是将长度为10的5次方个数,且范围在10的9次方以内映射到一个连续的数组里。
此时我们需要做的就是:
int b[]; b[0]=1; b[1]=20; b[2]=55; .....这里存在俩个问题: 1,a中可能存在重复元素(需要去重) java去重方式:
//这里我之前试了hashset去重,但是会超时。这里建议先排序再在有序的情况下for循环去重 //注意,这里的list参数已经Collections.sort(list);排序了!!! public static ArrayList<Integer> paichong(ArrayList<Integer> list) { ArrayList<Integer> linkedList = new ArrayList(); linkedList.add(list.get(0)); for (int i = 1; i < list.size(); i++) { if (list.get(i - 1) != list.get(i)) linkedList.add(list.get(i)); } return linkedList; }2,如何快速算出,也就是55在b中的下标是多少(二分)
public static int find(int x){//快速找到x在映射的数组下标 int l=0,r=list.size()-1; while(l<r){ int mid=(l+r)>>1; if(list.get(mid)>=x)r=mid; else l=mid+1; } return r; }假定有一个无限长的数轴,数轴上每个坐标上的数都是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 输入样例: 3 3 1 2 3 6 7 5 1 3 4 6 7 8 输出样例: 8 0 5
//package No1; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.io.PrintWriter; import java.io.StreamTokenizer; import java.util.ArrayList; import java.util.Collections; public class Main { public static void main(String[] args) throws IOException { StreamTokenizer in = new StreamTokenizer(new BufferedReader( new InputStreamReader(System.in))); PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out)); in.nextToken(); int n = (int) in.nval; in.nextToken(); int m = (int) in.nval; long arr[] = new long[3 * 1000 * 100 + 10];// 存储值 ArrayList<operate> oper = new ArrayList();// 存储添加操作 ArrayList<query> que = new ArrayList();// 存储查询操作 ArrayList<Integer> alls = new ArrayList();// 存储所有要离散化的下标 for (int i = 0; i < n; i++) { in.nextToken(); int index = (int) in.nval; in.nextToken(); int val = (int) in.nval; oper.add(new operate(index, val)); alls.add(index); } for (int i = 0; i < m; i++) { in.nextToken(); int l = (int) in.nval; in.nextToken(); int r = (int) in.nval; que.add(new query(l, r)); alls.add(l); alls.add(r); } Collections.sort(alls);// 排序 alls = paichong(alls); for (operate t : oper) { arr[find(alls, t.index)] += t.val; } for (int i = 1; i < arr.length; i++) { arr[i] += arr[i - 1]; } // for (Integer t : alls) { // arr[find(alls, t)] += arr[find(alls, t) - 1]; // } for (query t : que) { out.println(arr[find(alls, t.r)] - arr[find(alls, t.l) - 1]); } out.flush(); } public static ArrayList<Integer> paichong(ArrayList<Integer> list) { ArrayList<Integer> linkedList = new ArrayList(); linkedList.add(list.get(0)); for (int i = 1; i < list.size(); i++) { if (list.get(i - 1) != list.get(i)) linkedList.add(list.get(i)); } return linkedList; } public static int find(ArrayList<Integer> alls, int x) {// 根据x找到arr的下标 int l = 0, 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; } } class query {// 查询 int l, r; public query(int l, int r) { this.l = l; this.r = r; } } class operate {// 操作的值 int index, val; public operate(int index, int val) { this.index = index; this.val = val; } }