原题引出
题解分析
首先毫无置疑的是本体需要用到离散化的知识,将输入的索引下标放到一个vector当中存起来,在该vector当中,利用其本身的索引我们对称构造两个数组a和s(用于求前缀和)。那么最关键的一个问题就是如何通过输入的索引得到vector本身的索引?这就可以通过差分来实现:如图所示即find函数,注意我们这里返回的是r+1,为的就是待会求前缀和比较方便。
int find(int x)
{
int l=0,r=alls.size()-1;
while (l<r)
{
int mid=(l+r)/2;
if(alls[mid]>=x)r=mid;
else l=mid+1;
}
return r+1;
}
因此我们在求前缀和数组时,范围应该是 1 < = i < = a l l s . s i z e ( ) 1 <= i <= alls.size() 1<=i<=alls.size()(alls数组的下标索引仍是 0 < = i < = a l l s . s i z e ( ) − 1 0 <= i <= alls.size()-1 0<=i<=alls.size()−1)
for (int i = 1; i <= alls.size(); i++)
{
s[i]=s[i-1]+a[i];
}
总的代码如下所示:
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
vector<int>alls;
vector<pair<int,int>> add;
vector<pair<int,int>> query;
int a[301000],s[301000];
int find(int x)
{
int l=0,r=alls.size()-1;
while (l<r)
{
int mid=(l+r)/2;
if(alls[mid]>=x)r=mid;
else l=mid+1;
}
return r+1;
}
int main()
{
int n,m,x,c,l,r;
cin>>n>>m;
for(int i=0;i<n;i++)
{
cin>>x>>c;
alls.push_back(x);
add.push_back({x, c});
}
for(int i=0;i<m;i++)
{
cin>>l>>r;
alls.push_back(l);
alls.push_back(r);
query.push_back({l,r});
}
sort(alls.begin(),alls.end());
alls.erase(unique(alls.begin(),alls.end()),alls.end());
for(auto item:add)
{
int x_map=find(item.first);
a[x_map]+=item.second;
}
for (int i = 1; i <= alls.size(); i++)
{
s[i]=s[i-1]+a[i];
}
for(auto item:query)
{
int l_map=find(item.first);
int r_map=find(item.second);
cout<<s[r_map]-s[l_map-1]<<endl;
}
}
图解: