离散化操作
有一些问题的数值个数不多,但跨度却很大。举个例子,我们若要统计100个人的身高,记录每个身高的人数(精确到num),我们总不能开一个10^10级别的数组来存吧,这样做显然是不现实的,毕竟待统计的人数不是那么多,只是跨度较大而已,这个时候我们就要用到离散化了,下面给出一个具体的例子:
假定有一个无限长的数轴,数轴上每个坐标上的数都是 0。
现在,我们首先进行 n 次操作,每次操作将某一位置 x 上的数加 c。
接下来,进行 m 次询问,每个询问包含两个整数 l 和 r,你需要求出在区间 [l,r] 之间的所有数的和。
输入格式
第一行包含两个整数 n 和 m。
接下来 n 行,每行包含两个整数 x 和 c。
再接下来 m 行,每行包含两个整数 l 和 r。
输出格式
共 m 行,每行输出一个询问中所求的区间内数字和。
数据范围
−10^9≤x≤10^9,
1≤n,m≤10^5,
−10^9≤l≤r≤10^9,
−10000≤c≤10000
输入样例:
3 3
1 2
3 6
7 5
1 3
4 6
7 8
输出样例:
8
0
5
通过分析这道题的数据范围我们就能看出跨度为2*10^9,显然直接开数组实现是不太可能了,再看一下数值量,总共有10^5个数值,显然就要用到离散化了
下面是代码:
#include<bits/stdc++.h> using namespace std; int a[400002],sum[400002];//用于处理前缀和的数组 typedef pair<int,int> PII; vector<int> p;//待离散化数组 vector<PII> add,query; int find(int x)//查找操作 { int l=0,r=p.size()-1; while(l<r) { int mid=l+r>>1; if(p[mid]>=x) r=mid; else l=mid+1; } return l+1; } int main() { int n,m; cin>>n>>m; int l,r,x,c; while(n--) { cin>>x>>c; add.push_back(make_pair(x,c)); p.push_back(x);//将所有要待离散化的数都要存到vector数组里面 } while(m--) { cin>>l>>r; query.push_back(make_pair(l,r)); p.push_back(l);p.push_back(r); } sort(p.begin(),p.end());//为待离散化数组排序 p.erase(unique(p.begin(),p.end()),p.end());//去重 for(int i=0;i<add.size();i++) { int x=find(add[i].first); a[x]+=add[i].second; } for(int i=1;i<=p.size();i++) { sum[i]=sum[i-1]+a[i]; } for(int i=0;i<query.size();i++) { int l=find(query[i].first); int r=find(query[i].second); printf("%d\n",sum[r]-sum[l-1]); } return 0; }
希望大家能够喜欢!
心中所爱,山海可平