1、离散化
值域大而数值稀疏的题目,通常先将需要操作的数映射到一个数组中,再做后续操作,可以大大减少时间复杂度。
以AcWing.802为例,是一个典型的前缀和问题,但问题在于,若仅仅使用前缀和算法,时间复杂度会很高,因此需要先做离散化映射。
题目要求如下:
假定有一个无限长的数轴,数轴上每个坐标上的数都是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
#include <iostream> #include <map> #include <vector> #include <algorithm> using namespace std; const int N = 3e5 + 10; typedef pair<int, int> PII; vector<PII> add; multimap<int, int> query; vector<int> alls; int a[N], s[N]; //找到alls对应的x, l, r元素的首个下标,二分查找 int find(int x) { int l = 0, r = alls.size() - 1; while (l < r) { int mid = (l + r) >> 1; if (alls[mid] >= x) r = mid; else l = mid + 1; } return l; } int main() { int n, m; cin >> n >> m; int x, c; while (n--) { cin >> x >> c; add.push_back(make_pair(x, c)); alls.push_back(x); } int l, r; while (m--) { cin >> l >> r; query.insert({ l, r }); alls.push_back(l); alls.push_back(r); } //alls排序、去重 sort(alls.begin(), alls.end()); alls.erase(unique(alls.begin(), alls.end()), alls.end()); //生成前缀和 for (auto _a : add) { int idx = find(_a.first); a[idx + 1] += _a.second; } for (int i = 1; i <= alls.size(); i++) { s[i] = s[i - 1] + a[i]; } for (auto _q : query) { int _r = find(_q.second) + 1; int _l = find(_q.first) + 1; cout << s[_r] - s[_l - 1] << endl; } return 0; }
标签:10,int,基础,back,mid,离散,算法,alls,include From: https://www.cnblogs.com/karinto/p/17736534.html