区间和【离散化详讲】acwing802
由于坐标太长了,开数组这样的操作是肯定行不通的,离散化的原理就是将没有操作的地方全部抹去,然后再将抹去后的序列求前缀和,即可O(1)时间查询我们需要的区间信息,话不多说,直接上代码吧:
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define PII pair<int,int>
#define IOS ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
int n,m,x,c,l,r;
set<int> Point; //存储所有要用到的点,set用来去重
vector<int> AllPoint; //存储所有要用到的点
vector<PII> add; //存储要进行累加的操作,first表示位置,second表示加的值
vector<PII> Find; //存储查询的区间,first表示区间l值,second表示区间r值
int a[300005]; //存储最终的离散化操作后的数组
signed main(){
IOS
cin>>n>>m;
for(int i = 1;i <= n;++i)
cin>>x>>c,Point.insert(x),add.push_back(PII(x,c));
for(int i = 1;i <= n;++i)
cin>>l>>r,Point.insert(l),Point.insert(r),Find.push_back(PII(l,r));
for(auto it : Point)
AllPoint.push_back(it); //把去重后的点放在AllPoint中
for(int i = 0,j = add.size();i < j;++i){
int f = add[i].first,mid;
l = 0,r = AllPoint.size() - 1;
while(l <= r){
mid = l + r >> 1;
if(AllPoint[mid] < f) l = mid + 1;
else if(AllPoint[mid] > f) r = mid - 1;
else break;
}
a[mid] += add[i].second;
}
for(int i = 1,j = AllPoint.size();i < j;++i)
a[i] += a[i - 1];
//以上是求前缀和
for(int i = 0;i < m;++i){
int f = Find[i].first,t = Find[i].second,mid;
l = 0,r = AllPoint.size() - 1;
while(l <= r){
mid = l + r >> 1;
if(AllPoint[mid] > f) r = mid - 1;
else if(AllPoint[mid] < f) l = mid + 1;
else break;
}
f = mid;
l = 0,r = AllPoint.size() - 1;
while(l <= r){
mid = l + r >> 1;
if(AllPoint[mid] > t) r = mid - 1;
else if(AllPoint[mid] < t) l = mid + 1;
else break;
}
t = mid;
if(f == 0)
cout<<a[t]<<"\n";
else
cout<<a[t] - a[f - 1]<<"\n";
}
return 0;
}