离散化
- 题目
 
你会这个题 吗?
题目
假定有一个无限长的数轴,数轴上每个坐标上的数都是 0 0 0。
现在,我们首先进行 n n n 次操作,每次操作将某一位置 x x x 上的数加 c c c。
接下来,进行 m m m 次询问,每个询问包含两个整数 l l l 和 r r r,你需要求出在区间 [ l , r ] [l, r] [l,r] 之间的所有数的和。
输入格式
第一行包含两个整数 n n n 和 m m m。
接下来 n n n 行,每行包含两个整数 x x x 和 c c c。
再接下来 m m m 行,每行包含两个整数 l l l 和 r r r。
输出格式
共 m m m 行,每行输出一个询问中所求的区间内数字和。
数据范围
 
     
      
       
       
         − 
        
       
         1 
        
        
        
          0 
         
        
          9 
         
        
       
         ≤ 
        
       
         x 
        
       
         ≤ 
        
       
         1 
        
        
        
          0 
         
        
          9 
         
        
       
      
        -10^9 \le x \le 10^9 
       
      
    −109≤x≤109,
  
     
      
       
       
         1 
        
       
         ≤ 
        
       
         n 
        
       
         , 
        
       
         m 
        
       
         ≤ 
        
       
         1 
        
        
        
          0 
         
        
          5 
         
        
       
      
        1 \le n,m \le 10^5 
       
      
    1≤n,m≤105,
  
     
      
       
       
         − 
        
       
         1 
        
        
        
          0 
         
        
          9 
         
        
       
         ≤ 
        
       
         l 
        
       
         ≤ 
        
       
         r 
        
       
         ≤ 
        
       
         1 
        
        
        
          0 
         
        
          9 
         
        
       
      
        -10^9 \le l \le r \le 10^9 
       
      
    −109≤l≤r≤109,
  
     
      
       
       
         − 
        
       
         10000 
        
       
         ≤ 
        
       
         c 
        
       
         ≤ 
        
       
         10000 
        
       
      
        -10000 \le c \le 10000 
       
      
    −10000≤c≤10000
输入样例:
3 3
1 2
3 6
7 5
1 3
4 6
7 8
 
输出样例:
8
0
5
 
由于这个题目当中的位置(比如 x, l, r)的大小都是10的9次方的级别,开数组是开不了那么大的。
而这些需要用到的位置的个数加起来有 n + 2*m个的,n 和 m 都是10的5次方的级别的。
所以所有的数字都非常的 散 在 坐标轴上,密度非常低。
所以离散化就是将所有需要用到 的坐标挤在一起,中间没有一个空位。
准备阶段:
 
本题的思路是:
- 将所有用到的位置坐标存到alls容器,将n次操作的 x 和 c 存到adds容器当中,将m次询问的 l 和 r 存到query 容器当中
 - 将alls 容器内的元素 排序、去重。
 - 将alls容器内的位置映射到 数组a上
 - 遍历 adds 容器内元素 进行 n 次操作
 - 求数组 a 的前缀和数组 放到 数组 s 当中。
 - 遍历 query 容器,进行 m 次查询
 
操作1:
 
操作2:

 用到sort 和 unique 记得包含头文件
操作3:
对于映射操作我们需要写一个 find 函数,其功能是给一个 alls容器内一个位置,返回一个映射到数组 a 上的一个位置。

 这里其实就是 把 alls 容器里的 位置转换成了他们自己的坐标 + 1.
+1的原因是 因为后面要求前缀和,所以 从1开始会方便很多。
操作4:
 执行 n 次操作
 
操作5:
求前缀和数组
 
操作6:
执行 m 次询问 ,公式 s[ r ] - s[ l - 1 ]
 
完整代码如下:
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
const int N = 3e5+10;//需要用到位置的数量
int n, m;
int a[N], s[N];
typedef pair<int, int> PII;//省代码
vector<int> alls;//存储所有位置
vector<PII> adds;//存储n次操作
vector<PII> query;//存储m次询问
int find(int x)
{
    int i = 0, j = alls.size() - 1;
    while (i < j)
    {
        int mid = (i + j + 1) >> 1;
        if (alls[mid] <= x) i = mid;
        else j = mid - 1; 
    }
    return i+1;
}
int main()
{
    //存储
    scanf("%d%d", &n, &m);
    while (n --)
    {
        int x, c;
        scanf("%d%d", &x, &c);
        adds.push_back({x, c});
        alls.push_back(x);//alls 只需要位置
    }
    
    while (m --)
    {
        int l, r;
        scanf("%d%d", &l, &r);
        query.push_back({l, r});
        alls.push_back(l);
        alls.push_back(r);
    }
    //------------------------
    //排序、去重
    sort(alls.begin(), alls.end());//排序
    alls.erase(unique(alls.begin(), alls.end()), alls.end());
    //去重 unique 可以将重复的数字放到容器的后面并返回第一个
    //            重复的数字的迭代器
    
    
    //------------------------
    //执行 n 次操作
    for (auto seg: adds)
    {
        a[find(seg.first)] += seg.second;//一定注意要find
    }
    
    //求数组 a 的前缀和数组
    for (int i = 1; i <= alls.size(); i++) s[i] = s[i-1] + a[i];
    
    //执行 m 次询问
    for (auto seg: query)
    {
        int l = find(seg.first);
        int r = find(seg.second);
        printf("%d\n", s[r] - s[l-1]);
    }
    
    return 0;
    
}
 
完


















