[关闭]
@ZCDHJ 2019-10-23T06:20:36.000000Z 字数 2141 阅读 512

HAOI2012 高速公路

DP 线段树


其实就是要求维护一个区间里面所有子qujian区间的和的总和,那么单独考虑维护每个点的贡献,,用线段树维护三个值的总和,分别是 。具体实现就是在区间加的同时还多维护一个系数和。

  1. #include <iostream>
  2. #include <cstdio>
  3. typedef long long LL;
  4. #define int LL
  5. const int MAXN = 1e5;
  6. int n, m;
  7. inline int read() {
  8. register int x = 0, v = 1;
  9. register char ch = getchar();
  10. while (!isdigit(ch)) {
  11. if (ch == '-') v = -1;
  12. ch = getchar();
  13. }
  14. while (isdigit(ch)) {
  15. x = x * 10 + ch - '0';
  16. ch = getchar();
  17. }
  18. return x * v;
  19. }
  20. namespace Segtree {
  21. struct Node {
  22. int sumv, sumc, sumr, sumg, sumf;
  23. int lazy;
  24. Node *ch[2];
  25. Node() : sumv(0), sumc(0), sumr(0), sumg(0), sumf(0), lazy(0) {
  26. ch[0] = ch[1] = NULL;
  27. }
  28. } *root;
  29. void push_up(Node *o) {
  30. o -> sumv = o -> ch[0] -> sumv + o -> ch[1] -> sumv;
  31. o -> sumc = o -> ch[0] -> sumc + o -> ch[1] -> sumc;
  32. o -> sumr = o -> ch[0] -> sumr + o -> ch[1] -> sumr;
  33. o -> sumg = o -> ch[0] -> sumg + o -> ch[1] -> sumg;
  34. o -> sumf = o -> ch[0] -> sumf + o -> ch[1] -> sumf;
  35. }
  36. void push_down(Node *o, int l, int r) {
  37. if (o -> lazy) {
  38. int mid = (l + r) >> 1;
  39. o -> ch[0] -> sumv += (mid - l + 1) * o -> lazy;
  40. o -> ch[1] -> sumv += (r - mid) * o -> lazy;
  41. o -> ch[0] -> sumc += o -> ch[0] -> sumg * o -> lazy;
  42. o -> ch[1] -> sumc += o -> ch[1] -> sumg * o -> lazy;
  43. o -> ch[0] -> sumr += o -> ch[0] -> sumf * o -> lazy;
  44. o -> ch[1] -> sumr += o -> ch[1] -> sumf * o -> lazy;
  45. o -> ch[0] -> lazy += o -> lazy;
  46. o -> ch[1] -> lazy += o -> lazy;
  47. o -> lazy = 0;
  48. }
  49. }
  50. void build(Node *&o, int l, int r) {
  51. o = new Node;
  52. if (l == r) {
  53. o -> sumg = l;
  54. o -> sumf = l * l;
  55. return;
  56. }
  57. int mid = (l + r) >> 1;
  58. build(o -> ch[0], l, mid);
  59. build(o -> ch[1], mid + 1, r);
  60. push_up(o);
  61. }
  62. void update(Node *o, int l, int r, int ql, int qr, int v) {
  63. if (ql <= l && r <= qr) {
  64. o -> sumv += (r - l + 1) * v;
  65. o -> sumc += o -> sumg * v;
  66. o -> sumr += o -> sumf * v;
  67. o -> lazy += v;
  68. return;
  69. }
  70. int mid = (l + r) >> 1;
  71. push_down(o, l, r);
  72. if (ql <= mid) update(o -> ch[0], l, mid, ql, qr, v);
  73. if (mid < qr) update(o -> ch[1], mid + 1, r, ql, qr, v);
  74. push_up(o);
  75. }
  76. int query(Node *o, int l, int r, int ql, int qr) {
  77. if (ql <= l && r <= qr) return o -> sumv * (qr - ql - ql * qr + 1) + o -> sumc * (qr + ql) - o -> sumr;
  78. int mid = (l + r) >> 1, res = 0;
  79. push_down(o, l, r);
  80. if (ql <= mid) res = query(o -> ch[0], l, mid, ql, qr);
  81. if (mid < qr) res += query(o -> ch[1], mid + 1, r, ql, qr);
  82. return res;
  83. }
  84. }
  85. using namespace Segtree;
  86. int gcd(int x, int y) {
  87. return y ? gcd(y, x % y) : x;
  88. }
  89. signed main() {
  90. n = read();
  91. m = read();
  92. build(root, 1, n);
  93. while (m--) {
  94. char opt[10];
  95. scanf("%s", opt);
  96. if (*opt == 'C') {
  97. int l = read(), r = read() - 1, v = read();
  98. update(root, 1, n, l, r, v);
  99. } else {
  100. int l = read(), r = read() - 1;
  101. int a = query(root, 1, n, l, r), b = (r - l + 2) * (r - l + 1) / 2, c = gcd(a, b);
  102. printf("%lld/%lld\n", a / c, b / c);
  103. }
  104. }
  105. return 0;
  106. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注