这里只说一下离散化的简单思路(还不会难的(T _ T))
离散化的就是将大范围的缩小到小范围来表示,这类问题一般是数的范围很大,但是个数不多,
具体的思路是,将他们用一个数组来表示,查找其原位置时用二分查找即可。
一个模板题:区间和
假定有一个无限长的数轴,数轴上每个坐标上的数都是0。
现在,我们首先进行 n 次操作,每次操作将某一位置x上的数加c。
接下来,进行 m 次询问,每个询问包含两个整数l和r,你需要求出在区间[l, r]之间的所有数的和。
输入格式
第一行包含两个整数n和m。
接下来 n 行,每行包含两个整数x和c。
再接下里 m 行,每行包含两个整数l和r。
输出格式
共m行,每行输出一个询问中所求的区间内数字和。
数据范围
−10^9≤x≤10^9 −10^9≤x≤10^9,1≤n,m≤10^5 1≤n,m≤10^5,−10^9≤l≤r≤10^9 −10^9≤l≤r≤10^9,−10000≤c≤10000 −10000≤c≤10000
输入样例:
3 3
1 2
3 6
7 5
1 3
4 6
7 8
输出样例:
8
0
5
分析:数的范围很大,但是个数却不多,可以用一个数组来存。
代码如下:
1 #include<cstdio>
2 #include<algorithm>
3 using namespace std;
4 const int N=3e5+10;
5 int n,m,q[N];
6 struct node{
7 int id,x;
8 }s[N],e[N];
9 bool cmp(node a,node b)
10 {
11 return a.id<b.id;
12 }
13 int er1(int x)//二分查左端点
14 {
15 int l=1,r=n+2*m,mid;
16 while(l<r)
17 {
18 mid=l+r>>1;
19 if(s[mid].id>=x)
20 r=mid;
21 else
22 l=mid+1;
23 }
24 return l;
25 }
26 int er2(int x)//二分查右端点
27 {
28 int l=1,r=n+2*m,mid;
29 while(l<r)
30 {
31 mid=l+r+1>>1;
32 if(s[mid].id<=x)
33 l=mid;
34 else
35 r=mid-1;
36 }
37 return l;
38 }
39 int main()
40 {
41 int k=0;
42 scanf("%d%d",&n,&m);
43 for(int i=1;i<=n;i++) scanf("%d%d",&s[i].id,&s[i].x);
44 for(int i=n+1;i<=n+2*m;i++)
45 {
46 int l,r;
47 scanf("%d%d",&l,&r);
48 s[i].id=l;s[i].x=0;
49 i++;
50 s[i].id=r;s[i].x=0;
51 e[k].id=l;e[k].x=r;
52 k++;
53 }
54 sort(s+1,s+n+2*m+1,cmp);
55 for(int i=1;i<=n+2*m;i++) q[i]=q[i-1]+s[i].x;
56 for(int i=0;i<k;i++)
57 {
58 //printf("%d %d\n",e[i].id,e[i].x);
59 int l=er1(e[i].id);
60 int r=er2(e[i].x);
61 //printf("%d %d\n",l,r);
62 printf("%d\n",q[r]-q[l-1]);
63 }
64 return 0;
65 }