【基础算法】区间和-------离散化
假定有一个无限长的数轴,数轴上每个坐标上的数都是0。
现在,我们首先进行 n 次操作,每次操作将某一位置x上的数加c。
接下来,进行 m 次询问,每个询问包含两个整数l和r,你需要求出在区间[l, r]之间的所有数的和。
输入格式
第一行包含两个整数n和m。
接下来 n 行,每行包含两个整数x和c。
再接下里 m 行,每行包含两个整数l和r。
输出格式
共m行,每行输出一个询问中所求的区间内数字和。
数据范围
−109≤x≤109−109≤x≤109,
1≤n,m≤1051≤n,m≤105,
−109≤l≤r≤109−109≤l≤r≤109,
−10000≤c≤10000−10000≤c≤10000
输入样例:
3 3
1 2
3 6
7 5
1 3
4 6
7 8
输出样例:
8
0
5
思路:
离散化的思路,因为我们的坐标有2e9这么大的数值,而我们用到的只有3e5这么点数值,对于这种类型的,我们就要想到离散化,将各个散开的点用映射到下标(1,2,3,4.......)上,这要如何做呢?我们首先要将输入的数据进行保存,将出现的过的坐标存到数组中,用于映射,进行排序和去重,坐标对应数组的下标就是我们要的映射。然后就进行常规操作,前缀和求区间和。
详细代码解析:
#include<iostream> #include<vector> #include<algorithm> using namespace std; typedef pair<int, int> PII; const int N = 300010; int a[N], s[N];//储存映射出来的下标保存的值和前缀和。 vector<PII> add, query;//保存数据。 vector<int> alls;//储存所有用到的坐标值。 //二分查找,找出x在alls中的下标。 int find(int x) { int l = 0, r = alls.size() - 1, m; while (l < r) { m = l + r >> 1; if (alls[m] >= x) r = m; else l = m + 1; } return l + 1; } int main() { //保存输入输出的结果。处理输入输出 int n, m, x, c, l, r; cin >> n >> m; for (int i = 0;i < n;i++) { cin >> x >> c; add.push_back({ x,c }); alls.push_back(x); } for (int i = 0;i < m;i++) { cin >> l >> r; query.push_back({ l,r }); alls.push_back(l), alls.push_back(r); } //去除重复的坐标值 sort(alls.begin(), alls.end()); //unique函数不停的把后面不重复的元素移到前面来,返回最后一个不重复元素的下标 //erase函数,删除操作。 alls.erase(unique(alls.begin(), alls.end()), alls.end()); //对映射的值进行处理 for (auto item : add) a[find(item.first)] += item.second; //求前缀和 for (int i = 1;i <= alls.size();i++) s[i] = a[i] + s[i - 1]; //求区间和 for (auto item : query) cout << s[find(item.second)] - s[find(item.first) - 1] << endl; return 0; }