802. 区间和

假设有一个无限长的数轴,数轴上每个坐标上的数都是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≤105
1≤n,m≤105
,
−109≤l≤r≤109
−109≤l≤r≤109
,
−10000≤c≤10000
−10000≤c≤10000

#include<bits/stdc++.h>

using namespace std;

typedef pair<int,int> P;//存储询问区间L,R的值

const int N = 300010;//插入10w个,查询左右区间所以有20w个,共需要30w个映射值
int n,m;
int a[N],s[N];//a存储映射后坐标处插入的值,s存储前缀和
vector<int> alls;//存储映射后的坐标
vector<P> add,query;//存储插入和查询的数据

int find(int x)//用二分找到映射后的值
{
    int l = 0,r = alls.size() - 1;
    while(l < r)
    {
        int mid = l + r >> 1;
        if(alls[mid] >= x) r = mid;
        else l = mid + 1;
    }
    return r + 1;//前缀和使用自然数1,2,3,若从0开始会有边界问题
}

int main()
{
    cin >> n >> m;
    while(n --)
    {
        int x,c;
        cin >> x >> c;
        add.push_back({x,c});//插入需要的数据放入add
        alls.push_back(x);//坐标数据存入alls
    }
    while(m --)
    {
        int l,r;
        cin >> l >> r;
        query.push_back({l,r});//查询需要的数据放入query
        alls.push_back(l);//坐标数据放入alls
        alls.push_back(r);
    }
    //给alls中坐标去重
    sort(alls.begin(),alls.end());//排序
    //alls.erase(a,b)删除a--b的数据,unique()返回没重复值的个数
    alls.erase(unique(alls.begin(),alls.end()),alls.end());
    //处理插入
    for(auto item:add)
    {
        int x = find(item.first);//找到映射值
        a[x] += item.second;//将值加进a数组
    }
    //处理前缀和
    for(int i = 1; i <= alls.size(); i ++)
    {
        s[i] = s[i - 1] + a[i];
    }
    //处理询问
    for(auto item:query)
    {
        int l = find(item.first);//找到l,r映射的坐标
        int r = find(item.second);
        cout << s[r] - s[l - 1] << endl;;
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值