POJ 3468 A Simple Problem with Integers //线段树的成段更新

迷南。 2022-09-20 15:27 253阅读 0赞

A Simple Problem with Integers

















Time Limit: 5000MS   Memory Limit: 131072K
Total Submissions: 59046   Accepted: 17974
Case Time Limit: 2000MS

Description

You have N integers, A1, A2, … , AN. 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 A1, A2, … , AN. -1000000000 ≤ Ai ≤ 1000000000.
Each of the next Q lines represents an operation.
“C a b c“ means adding c to each of Aa, Aa+1, … , Ab. -10000 ≤ c ≤ 10000.
“Q a b“ means querying the sum of Aa, Aa+1, … , Ab.

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.

Source

POJ Monthly—2007.11.25, Yang Yi

  1. /*
  2. 区间更新的lazy操作。
  3. */
  4. #include <stdio.h>
  5. struct node
  6. {
  7. int l, r;
  8. __int64 sum;
  9. __int64 lazy; //当成段更新时,往往不用更新到单个的点。lazy操作大大节省了时间。
  10. }tree[300005];
  11. int h[100005];
  12. __int64 sum; //int超限
  13. void build(int l, int r, int n)
  14. {
  15. int mid;
  16. tree[n].l = l;
  17. tree[n].r = r;
  18. tree[n].lazy = 0; //赋初值
  19. if(l==r)
  20. {
  21. tree[n].sum = h[l];
  22. return ;
  23. }
  24. mid = (l+r)/2;
  25. build(l, mid, 2*n);
  26. build(mid+1, r, 2*n+1);
  27. tree[n].sum = tree[2*n].sum+tree[2*n+1].sum;
  28. }
  29. void add(int l, int r, __int64 k, int n)
  30. {
  31. int mid;
  32. if(tree[n].l==l && tree[n].r==r) //当需要更新的段 与 结点对应的段吻合时,直接把此结点的lazy值更新即可,不需要再向下更新。
  33. {
  34. tree[n].lazy += k;
  35. return;
  36. }
  37. tree[n].sum += k*(r-l+1); //当此区间包含需要更新的区间,但不吻合时,需要向下继续查找,此时需要更新这个父节点的sum值。
  38. mid = (tree[n].l + tree[n].r)/2;
  39. if(r <= mid)
  40. add(l, r, k, 2*n);
  41. else if(l >=mid+1)
  42. add(l, r, k, 2*n+1);
  43. else
  44. {
  45. add(l, mid, k, 2*n);
  46. add(mid+1, r, k, 2*n+1);
  47. }
  48. }
  49. void qu(int l, int r, int n)
  50. {
  51. int mid;
  52. if(tree[n].l==l && tree[n].r==r)
  53. {
  54. sum += tree[n].sum + (r-l+1)*tree[n].lazy; //当查找的段与 此结点的段吻合时,sum 值等于这个结点的sum加上lazy乘区间长度的值。
  55. return ;
  56. }
  57. if(tree[n].lazy!=0 && tree[n].l!=tree[n].r) //当查找区间为此结点对应区间的子集时,需要将此结点对应的lazy值下放到其子节点,并把此结点的lazy值置为0。
  58. {
  59. add(tree[2*n].l, tree[2*n].r, tree[n].lazy, n);
  60. add(tree[2*n+1].l, tree[2*n+1].r, tree[n].lazy, n);
  61. tree[n].lazy = 0;
  62. }
  63. mid = (tree[n].l + tree[n].r)/2;
  64. if(l >= mid+1)
  65. qu(l, r, 2*n+1);
  66. else if(r <= mid)
  67. qu(l, r, 2*n);
  68. else
  69. {
  70. qu(l, mid, 2*n);
  71. qu(mid+1, r, 2*n+1);
  72. }
  73. }
  74. int main()
  75. {
  76. int n, q;
  77. int i;
  78. int a, b, c;
  79. char ch[10];
  80. scanf("%d%d", &n, &q);
  81. for(i=1; i<=n; i++)
  82. scanf("%d", &h[i]);
  83. build(1, n, 1);
  84. while(q--)
  85. {
  86. scanf("%s", ch);
  87. if(ch[0]=='Q')
  88. {
  89. scanf("%d%d", &a, &b);
  90. sum = 0;
  91. qu(a, b, 1);
  92. printf("%I64d\n", sum);
  93. }
  94. else
  95. {
  96. scanf("%d%d%d", &a, &b, &c);
  97. add(a, b, c, 1);
  98. }
  99. }
  100. return 0;
  101. }

发表评论

表情:
评论列表 (有 0 条评论,253人围观)

还没有评论,来说两句吧...

相关阅读