zoukankan      html  css  js  c++  java
  • 【基础算法】区间和-------离散化

    假定有一个无限长的数轴,数轴上每个坐标上的数都是0。

    现在,我们首先进行 n 次操作,每次操作将某一位置x上的数加c。

    接下来,进行 m 次询问,每个询问包含两个整数l和r,你需要求出在区间[l, r]之间的所有数的和。

    输入格式

    第一行包含两个整数n和m。

    接下来 n 行,每行包含两个整数x和c。

    再接下里 m 行,每行包含两个整数l和r。

    输出格式

    共m行,每行输出一个询问中所求的区间内数字和。

    数据范围

    109x109−109≤x≤109,
    1n,m1051≤n,m≤105,
    109lr109−109≤l≤r≤109,
    10000c10000−10000≤c≤10000

    输入样例:

    3 3
    1 2
    3 6
    7 5
    1 3
    4 6
    7 8
    

    输出样例:

    8
    0
    5

    思路:

    离散化的思路,因为我们的坐标有2e9这么大的数值,而我们用到的只有3e5这么点数值,对于这种类型的,我们就要想到离散化,将各个散开的点用映射到下标(1,2,3,4.......)上,这要如何做呢?我们首先要将输入的数据进行保存,将出现的过的坐标存到数组中,用于映射,进行排序和去重,坐标对应数组的下标就是我们要的映射。然后就进行常规操作,前缀和求区间和。

    详细代码解析:

    #include<iostream>
    #include<vector>
    #include<algorithm>
    using namespace std;
    
    typedef pair<int, int>  PII;
    const int N = 300010;
    int a[N], s[N];//储存映射出来的下标保存的值和前缀和。
    vector<PII> add, query;//保存数据。
    vector<int> alls;//储存所有用到的坐标值。
    
    //二分查找,找出x在alls中的下标。
    int find(int x) {
        int l = 0, r = alls.size() - 1, m;
        while (l < r) {
            m = l + r >> 1;
            if (alls[m] >= x) r = m;
            else l = m + 1;
        }
    
        return l + 1;
    }
    
    int main() {
        //保存输入输出的结果。处理输入输出
        int n, m, x, c, l, r;
        cin >> n >> m;
    
        for (int i = 0;i < n;i++) {
            cin >> x >> c;
            add.push_back({ x,c });
            alls.push_back(x);
        }
    
        for (int i = 0;i < m;i++) {
            cin >> l >> r;
            query.push_back({ l,r });
            alls.push_back(l), alls.push_back(r);
        }
    
        //去除重复的坐标值
        sort(alls.begin(), alls.end());
        //unique函数不停的把后面不重复的元素移到前面来,返回最后一个不重复元素的下标
        //erase函数,删除操作。
        alls.erase(unique(alls.begin(), alls.end()), alls.end());
    
        //对映射的值进行处理
        for (auto item : add) a[find(item.first)] += item.second;
    
        //求前缀和
        for (int i = 1;i <= alls.size();i++) s[i] = a[i] + s[i - 1];
    
        //求区间和
        for (auto item : query)
            cout << s[find(item.second)] - s[find(item.first) - 1] << endl;
    
        return 0;
    }
     
  • 相关阅读:
    基于Adaboost的人脸检测算法
    操作系统笔试题及答案
    eclipse Maven plugin 配置
    网站服务管理系统系列教程之五
    2017第4周日
    2017春节~人生智慧箴言
    2017年初夕
    2017农历二十九
    王国维收藏真伪
    2017第3周二假期里该做的事
  • 原文地址:https://www.cnblogs.com/Attacking-vincent/p/12957893.html
Copyright © 2011-2022 走看看