基础算法:离散化实现
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 <vector> #include <algorithm> using namespace std; const int N = 3e5 + 10; typedef pair<int, int> PII; vector<PII> add; vector<PII> 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.push_back({ 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; }
对以上代码进行整理,我们可以实现更优雅的写法:
#include <iostream> #include <vector> #include <map> #include <algorithm> using namespace std; using PII = pair<int, int>; map<int, int> add; vector<PII> query; vector<int> alls; const int N = 3 * 1e5 + 10; int a[N], s[N]; int bfind_1(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 + 1; } int main() { int n, m; cin >> n >> m; int x, c; while (n--) { cin >> x >> c; add[x] += c; alls.push_back(x); } int l, r; while (m--) { cin >> l >> r; query.push_back({ l, r }); alls.push_back(l); alls.push_back(r); } sort(alls.begin(), alls.end()); alls.erase(unique(alls.begin(), alls.end()), alls.end()); for (auto it = add.begin(); it != add.end(); it++) { int idx = bfind_1(it->first); a[idx] = it->second; //a[idx] += it->second; } for (int k = 1; k <= alls.size(); k++) { s[k] = s[k - 1] + a[k]; } for (auto q : query) { int l = bfind_1(q.first); int r = bfind_1(q.second); cout << s[r] - s[l - 1] << endl; } return 0; }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探