栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

day8区间和(离散化)

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

day8区间和(离散化)

区间和

假定有一个无限长的数轴,数轴上每个坐标上的数都是 0。
现在,我们首先进行 n 次操作,每次操作将某一位置 x 上的数加 c。
接下来,进行 m 次询问,每个询问包含两个整数 l 和 r,你需要求出在区间 [l,r] 之间的所有数的和。
输入格式
第一行包含两个整数 n 和 m。
接下来 n 行,每行包含两个整数 x 和 c。
再接下来 m 行,每行包含两个整数 l 和 r。
输出格式
共 m 行,每行输出一个询问中所求的区间内数字和。
数据范围
−109≤x≤109,
1≤n,m≤105,
−109≤l≤r≤109,
−10000≤c≤10000
输入样例:
3 3
1 2
3 6
7 5
1 3
4 6
7 8
输出样例:
8
0
5
AC代码:

#include 
#include 
#include 
using namespace std;
const int N = 3 * 100010;
vector alls;
typedef pair PII;
vector add, query;
int a[N], s[N];
int find(int x){ //二分查找
    int l = 0, r = alls.size() - 1;
    while(r > l){
        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;
    PII temp;
    cin >> n >> m;
    for(int i = 0; i < n; i++){ //处理输入
        cin >> x >> c; //x代表位置,c代表数值
        temp.first = x;
        temp.second = c;
        add.push_back(temp);
        alls.push_back(x);
    }
    for(int i = 0; i < m; i++){ //处理输入
        cin >> l >> r;
        alls.push_back(l);
        alls.push_back(r);
        temp.first = l;
        temp.second = r;
        query.push_back(temp);
    }
    sort(alls.begin(), alls.end()); //排序
    alls.erase(unique(alls.begin(), alls.end()), alls.end()); //去重
    for(auto t : add)   a[find(t.first)] += t.second; //处理插入,find函数完成映射
    for(int i = 1; i <= alls.size(); i++)   s[i] += s[i - 1] + a[i]; //计算前缀和数组的值
    for(auto t : query) cout << s[find(t.second)] - s[find(t.first) - 1] << endl; //输出结果
    return 0;
}

理解:这个题目真的快到天花板了,我这个菜鸡看了好长时间才勉强理解。乍一看,想着用之前做过的前缀和的知识来做,但是数轴范围是10的-9次方到10的9次方,不能申请这么大的数组(内存超限)而且还有负数,需要经过一定的处理。
其基本思路就是将无限长的数轴的一部分下标映射到有限的数组内,具体映射哪些元素下标呢?就是将需要加上c的位置下标,和每次查询范围l,r这两个下标,将所有的这些下标映射到数组内,再设置一个find函数,这个函数是映射的关键,就是通过原始位置来查找到映射之后的下标,本质上就是一个二分查找算法,找到这个下标之后,就将这个下标所对应的元素加上c,这样就完成了初始化操作。接下来的操作就简单了,利用前缀和的知识,计算出这个序列的前缀和数组,用s[N]保存起来,再利用find函数将l,r映射到a[N]对应的下标,然后再求这对下标对应的区间前缀和就行了。
思路还是挺难想的,而且用到了STL的知识,都不是很熟悉,希望继续努力,希望能有突破!
说的不对的地方还请多多指教,谢谢

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/629151.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号