离散化
化大为小
离散化的本质是建立了一段数列到自然数之间的映射关系(value -> index),通过建立新索引,来缩小目标区间,使得可以进行一系列连续数组可以进行的操作比如二分,前缀和等…
化大为小,把稀疏离散化简为稠密连续的一段
模板:
vector<int> alls; // 存储所有待离散化的值(一般是将所有需要用到的下标存入) sort(alls.begin(), alls.end()); // 将所有值排序 alls.erase(unique(alls.begin(), alls.end()), alls.end()); // 去掉重复元素 // 二分求出x对应的离散化的值 //原理:排序后大的还是在前,小的还是在后,通过返回其值(x)对应的下标以达到离散化 int find(int x) // 找到第一个大于等于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 r + 1; // 映射到1, 2, ...n }
题目:
#include <iostream> #include <vector> #include <algorithm> using namespace std; typedef pair<int, int> PII; const int N = 3e5 + 10; int n, m; int a[N], s[N];// 存的数 前缀和 vector<int> alls;// 需要离散化的值,对应着有序坐标 vector<PII> adds, query; // 实际的下标和值存在add里,alls用来对下标离散化 //求x离散化后的结果 //原理:排序后大的还是在前,小的还是在后,通过返回其值(x)对应的下标以达到离散化 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 r + 1; } //将输入和询问的稀疏下标通过离散化变成紧密的 int main() { cin >> n >> m; for (int i = 0; i < n; i++) { int x, c; cin >> x >> c; adds.push_back({x, c}); alls.push_back(x);//导入输入下标 } for (int i = 0; i < m; i++) { int l, r;; 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 item : adds) {//在离散化后的坐标轴上加上要加的数 int x = find(item.first); a[x] += item.second; } //前缀和 for (int i = 1; i <= alls.size(); i++) s[i] = s[i - 1] + a[i]; //处理询问 for (auto item : query) { int l = find(item.first), r = find(item.second); cout << s[r] - s[l - 1] << endl; } return 0; }
本文作者:-37-
本文链接:https://www.cnblogs.com/-37-/p/17661131.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步