(https://www.acwing.com/problem/content/804/)
假定有一个无限长的数轴,数轴上每个坐标上的数都是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
思路:离散化+前缀和
由于坐标的数据范围很大,那么将坐标离散化。排序去重后的新下标就是坐标离散化后的坐标。
#include <iostream> #include<algorithm> #include<vector> using namespace std; const int maxn = 3e5+10; typedef pair<int,int> pll; int a[maxn]; int s[maxn]; vector<pll> add,qu; vector<int> adds; int find1(int x) { int l=0,r=adds.size()-1; while(l<r) { int mid=l+r >> 1; if(adds[mid]>=x) r=mid; else l=mid+1; } return r+1; } int main() { std::ios::sync_with_stdio(false); int n,m; cin >> n >> m; for(int i=1;i<=n;i++) { int x,y; cin >> x >> y; add.push_back({x,y}); adds.push_back(x); } for(int i=1;i<=m;i++) { int l,r; cin >> l >> r; qu.push_back({l,r}); adds.push_back(l); adds.push_back(r); } sort(adds.begin(),adds.end()); adds.erase(unique(adds.begin(),adds.end()),adds.end()); for(auto i : add) { int x=find1(i.first); a[x]+=i.second; } for(int i=1;i<=adds.size();i++) { s[i]=s[i-1]+a[i]; } for(auto j : qu) { int l=find1(j.first),r=find1(j.second); cout << s[r]-s[l-1] << endl; } return 0; }