区间和(离散化)

举报
irrational 发表于 2022/01/18 00:36:43 2022/01/18
【摘要】 假定有一个无限长的数轴,数轴上每个坐标上的数都是 0。 现在,我们首先进行 n次操作,每次操作将某一位置 x 上的数加 c。 接下来,进行 m次询问,每个询问包含两个整数 l 和 r,你需要求出在区间 [l,r] 之间的所有数的和。 输入格式 第一行包含两个整数 n和 m。 接下来 n行,每行包含两个整数 x 和 c。 再...

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

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

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

之间的所有数的和。

输入格式

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

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

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

输出格式

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

数据范围

−10^9≤x≤10^9,
1≤n,m≤10^5,
−10^9≤l≤r≤10^9,
−10000≤c≤10000

输入样例:


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

输出样例:


  
  1. 8
  2. 0
  3. 5

分析:这其实是一道离散化的板子题,没有什么难度,重点就在与发现其中的奥秘:

由于区间较大,开一个很长的数组没有什么意义,所以说需要利用离散化,把分得很开的数组聚合到一起,通过二分来找到你要找的元素,把这个下标的映射关系搞到手,仅此而已。


  
  1. #include <iostream>
  2. #include <vector>
  3. #include <algorithm>
  4. using namespace std;
  5. typedef pair<int, int> PII;
  6. const int N = 300010;
  7. int n, m;
  8. int a[N], s[N];
  9. vector<int> alls;
  10. vector<PII> add, query;
  11. int find(int x)
  12. {
  13. int l = 0, r = alls.size() - 1;
  14. while (l < r)
  15. {
  16. int mid = l + r >> 1;
  17. if (alls[mid] >= x) r = mid;
  18. else l = mid + 1;
  19. }
  20. return r + 1;
  21. }
  22. vector<int>::iterator unique(vector<int> &a)
  23. {
  24. int j = 0;
  25. for (int i = 0; i < a.size(); i ++ )
  26. if (!i || a[i] != a[i - 1])
  27. a[j ++ ] = a[i];
  28. // a[0] ~ a[j - 1] 所有a中不重复的数
  29. return a.begin() + j;
  30. }
  31. int main()
  32. {
  33. cin >> n >> m;
  34. for (int i = 0; i < n; i ++ )
  35. {
  36. int x, c;
  37. cin >> x >> c;
  38. add.push_back({x, c});
  39. alls.push_back(x);
  40. }
  41. for (int i = 0; i < m; i ++ )
  42. {
  43. int l, r;
  44. cin >> l >> r;
  45. query.push_back({l, r});
  46. alls.push_back(l);
  47. alls.push_back(r);
  48. }
  49. // 去重
  50. sort(alls.begin(), alls.end());
  51. alls.erase(unique(alls), alls.end());
  52. //unique将相同元素移到最后,返回最后一个不重复元素的地址\
  53. erase删除所给定区间+1的所有元素
  54. // 处理插入
  55. for (auto item : add)// c++11 for (auto:迭代器名称 要遍历的容器 )
  56. {
  57. int x = find(item.first);
  58. a[x] += item.second;
  59. }
  60. // 预处理前缀和
  61. for (int i = 1; i <= alls.size(); i ++ ) s[i] = s[i - 1] + a[i];
  62. // 处理询问
  63. for (auto item : query)
  64. {
  65. int l = find(item.first), r = find(item.second);
  66. cout << s[r] - s[l - 1] << endl;
  67. }
  68. return 0;
  69. }

文章来源: blog.csdn.net,作者:irrationality,版权归原作者所有,如需转载,请联系作者。

原文链接:blog.csdn.net/weixin_54227557/article/details/120604627

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。