AcWing802:详解

原题引出

AcWing802:详解_第1张图片

题解分析

首先毫无置疑的是本体需要用到离散化的知识,将输入的索引下标放到一个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 
#include 
#include 
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;
    }
}

图解:
AcWing802:详解_第2张图片

你可能感兴趣的:(c++,算法,开发语言)