Description

You have \(N\) integers, \(A_1, A_2, ... , A_N\). You need to deal with two kinds of operations. One type of operation is to add some given number to each number in a given interval. The other is to ask for the sum of numbers in a given interval.

Input

The first line contains two numbers \(N\) and \(Q\). \(1 ≤ N,Q ≤ 100000\).

The second line contains \(N\) numbers, the initial values of \(A_1, A_2, ... , A_N\). \(-1000000000 \le A_i \le 1000000000\).

Each of the next \(Q\) lines represents an operation.

"\(C\ a\ b\ c\)" means adding c to each of \(A_a, A_{a+1}, \ ...\ , A_b\). \(-10000 \le c \le 10000\).

"\(Q\ a\ b\)" means querying the sum of \(A_a, A_{a+1}, \ ...\ , A_b\).

Output

You need to answer all \(Q\) commands in order. One answer in a line.

Sample Input

  1. 10 5
  2. 1 2 3 4 5 6 7 8 9 10
  3. Q 4 4
  4. Q 1 10
  5. Q 2 4
  6. C 3 6 3
  7. Q 2 4

Sample Output

  1. 4
  2. 55
  3. 9
  4. 15

Hint

The sums may exceed the range of 32-bit integers.

Solution

题意

给定 \(n\) 个数和 \(q\) 个询问,询问包含两种:\(C\ a\ b\ c\) 代表区间 \([a, b]\) 的每个数加上 \(c\),\(Q\ a\ b\) 输出区间 \([a, b]\) 的和。

题解

分块

区间更新模板题,本题可以使用树状数组、线段树和分块解决,这里使用的是分块。

  1. #include <cstdio>
  2. #include <iostream>
  3. #include <cmath>
  4. using namespace std;
  5. typedef long long ll;
  6. const int maxn = 1e5 + 10;
  7. ll a[maxn], sum[maxn], add[maxn]; // add[] 是增量标记
  8. int L[maxn], R[maxn]; // 存放每个块的左右边界
  9. int block[maxn]; // 存放下标为 i 的元素的块号
  10. int n, q;
  11. int block_size; // 块的大小
  12. // 分块 + 预处理
  13. void init() {
  14. block_size = sqrt(n);
  15. for(int i = 1; i <= block_size; ++i) {
  16. L[i] = (i - 1) * block_size + 1;
  17. R[i] = i * block_size;
  18. }
  19. // 处理最后一块
  20. if(R[block_size] < n) {
  21. ++block_size;
  22. L[block_size] = R[block_size - 1] + 1;
  23. R[block_size] = n;
  24. }
  25. // 预处理每个块的区间和
  26. for(int i = 1; i <= block_size; ++i) {
  27. for(int j = L[i]; j <= R[i]; ++j) {
  28. block[j] = i;
  29. sum[i] += a[j];
  30. }
  31. }
  32. }
  33. // 将区间 [l, r] 内的所有元素加 c
  34. void change(int l, int r, ll c) {
  35. int p = block[l], q = block[r]; // 取出左右区间所在的块号
  36. if(p == q) {
  37. // 在同一块直接块内暴力
  38. for(int i = l; i <= r; ++i) {
  39. a[i] += c;
  40. }
  41. sum[p] += c * (r - l + 1);
  42. } else {
  43. // 不在同一块,块内暴力,块间整块处理
  44. for(int i = p + 1; i <= q - 1; ++i) {
  45. add[i] += c;
  46. }
  47. // 块内暴力
  48. for(int i = l; i <= R[p]; ++i) {
  49. a[i] += c;
  50. }
  51. sum[p] += c * (R[p] - l + 1);
  52. for(int i = L[q]; i <= r; ++i) {
  53. a[i] += c;
  54. }
  55. sum[q] += c * (r - L[q] + 1);
  56. }
  57. }
  58. ll query(int l, int r) {
  59. int p = block[l], q = block[r]; // 取出左右区间所在的块号
  60. ll ans = 0;
  61. if(p == q) {
  62. for(int i = l; i <= r; ++i) {
  63. ans += a[i];
  64. }
  65. ans += add[p] * (r - l + 1);
  66. } else {
  67. // 块间暴力
  68. for(int i = p + 1; i <= q - 1; ++i) {
  69. ans += sum[i] + add[i] * (R[i] - L[i] + 1); // 注意不是乘以 block_size
  70. }
  71. // 块内暴力
  72. for(int i = l; i <= R[p]; ++i) {
  73. ans += a[i];
  74. }
  75. ans += add[p] * (R[p] - l + 1);
  76. for(int i = L[q]; i <= r; ++i) {
  77. ans += a[i];
  78. }
  79. ans += add[q] * (r - L[q] + 1);
  80. }
  81. return ans;
  82. }
  83. int main() {
  84. scanf("%d%d", &n, &q);
  85. for(int i = 1; i <= n; ++i) {
  86. scanf("%lld", &a[i]);
  87. }
  88. init();
  89. for(int i = 0; i < q; ++i) {
  90. char op;
  91. getchar(); scanf("%c", &op);
  92. int l, r;
  93. scanf("%d%d", &l, &r);
  94. if(op == 'C') {
  95. ll c;
  96. scanf("%lld", &c);
  97. change(l, r, c);
  98. } else {
  99. printf("%lld\n", query(l, r));
  100. }
  101. }
  102. return 0;
  103. }

Reference

《算法竞赛进阶指南》 李煜东 著

POJ 3468 A Simple Problem with Integers (分块)的更多相关文章

  1. POJ 3468 A Simple Problem with Integers(分块入门)

    题目链接:http://poj.org/problem?id=3468 A Simple Problem with Integers Time Limit: 5000MS   Memory Limit ...

  2. POJ.3468 A Simple Problem with Integers(线段树 区间更新 区间查询)

    POJ.3468 A Simple Problem with Integers(线段树 区间更新 区间查询) 题意分析 注意一下懒惰标记,数据部分和更新时的数字都要是long long ,别的没什么大 ...

  3. poj 3468 A Simple Problem with Integers 【线段树-成段更新】

    题目:id=3468" target="_blank">poj 3468 A Simple Problem with Integers 题意:给出n个数.两种操作 ...

  4. 线段树(成段更新) POJ 3468 A Simple Problem with Integers

    题目传送门 /* 线段树-成段更新:裸题,成段增减,区间求和 注意:开long long:) */ #include <cstdio> #include <iostream> ...

  5. POJ 3468 A Simple Problem with Integers(线段树功能:区间加减区间求和)

    题目链接:http://poj.org/problem?id=3468 A Simple Problem with Integers Time Limit: 5000MS   Memory Limit ...

  6. poj 3468 A Simple Problem with Integers(线段树+区间更新+区间求和)

    题目链接:id=3468http://">http://poj.org/problem? id=3468 A Simple Problem with Integers Time Lim ...

  7. poj 3468 A Simple Problem with Integers 线段树区间加,区间查询和

    A Simple Problem with Integers Time Limit: 1 Sec  Memory Limit: 256 MB 题目连接 http://poj.org/problem?i ...

  8. poj 3468 A Simple Problem with Integers 线段树区间加,区间查询和(模板)

    A Simple Problem with Integers Time Limit: 1 Sec  Memory Limit: 256 MB 题目连接 http://poj.org/problem?i ...

  9. poj 3468:A Simple Problem with Integers(线段树,区间修改求和)

    A Simple Problem with Integers Time Limit: 5000MS   Memory Limit: 131072K Total Submissions: 58269   ...

随机推荐

  1. java遇到的问题

    1.java 初始化泛型数组 public static <T> T[] toArray(java.util.List<T> src, Class<T> type) ...

  2. nodeType介绍及应用示例

    一,DOM中的节点类型介绍 DOM将一份文档抽象为一棵树,而树又由众多不同类型的节点构成. 元素节点是DOM中的最小单位节点,它包括了各种标签,比如表示段落的p,表示无序列表的ul等. 文本节点总是被 ...

  3. 跨域篇--JSONP原理

    一篇文章让你明白 jsonp原理详解 什么是JSONP? 先说说JSONP是怎么产生的: 其实网上关于JSONP的讲解有很多,但却千篇一律,而且云里雾里,对于很多刚接触的人来讲理解起来有些困难,着用自 ...

  4. Python面试题之下面代码会输出什么

    def f(x,l=[]): for i in range(x): l.append(i*i) print l f(2) f(3,[3,2,1]) f(3) 答案: [0, 1] [3, 2, 1, ...

  5. ARC103

    ARC103E Tr/ee 首先没有叶子显然不科学,\(s_n\)是1也不怎么科学,\(s_i != s_{n-i}\)同样不怎么科学 特判掉上述情况后先把root记为1,链接(root,i+1)如果 ...

  6. java虚拟机规范(se8)——java虚拟机的编译(二)

    3.3 算术运算 java虚拟机通常在操作数栈上进行算术运算(例外情况是iinc指令,它直接增加一个局部变量的值).例如下面的align2grain()方法,它的作用是将int值对齐到2的指定次幂: ...

  7. 复习下KMP&e-KMP

    KMP算法的核心思想是next数组. 接下来,我来谈谈我对KMP数组的理解. KMP算法是用来匹配有多少相同字串的一种算法. 1.next数组记录前缀与后缀相等的位置,然后跳到这. 2.数组即记录后缀 ...

  8. Python之OS(系统操作)模块常用函数

    mkdir(path[, mode=0777]) makedirs(name,mode=511) rmdir(path) removedirs(path) listdir(path) getcwd() ...

  9. css 深入理解

    场景一.边框半透明,背景绿色 默认情况下背景会延伸到边框所在的下边 css2 中我们只能接受  css3 中我们可以通过 background-clip 属性来实现 border: 10px soli ...

  10. MySQL中的触发器insert、update

    以下为MySQL 触发器insert 的3个示例演示(update类似) delimiter // create trigger InsertUser before insert on user fo ...