[关闭]
@ZCDHJ 2019-08-03T14:56:01.000000Z 字数 2602 阅读 475

ZJOI2010 基站选址

未分类


的 DP 很简单,设 为第 个村庄建造第 个基站,只考虑前 个村庄的花费。 其中 表示 中间的村庄需要赔偿的总额。考虑在 逐渐变大的时候,如果有一个村庄的可被覆盖范围 满足 ,以后的所有 都会加一。这个是一个区间加的形式,可以用线段树来维护每个 就是每次不断增大的状态中的第二个变量。每个区间只会被用作加法一次(在一个阶段内),所以总复杂度为

  1. #include <iostream>
  2. #include <cstdio>
  3. #include <cstring>
  4. #include <algorithm>
  5. typedef long long LL;
  6. const int MAXN = 2e4;
  7. const int MAXK = 1e2;
  8. int n, K, ans;
  9. int c[MAXN | 1], dp[MAXK | 1][MAXN | 1], sum[MAXN | 1];
  10. LL d[MAXN | 1];
  11. struct Range {
  12. int l, r;
  13. LL w;
  14. Range() : l(0), r(0), w(0) {}
  15. friend bool operator< (const Range &lhs, const Range &rhs) {
  16. return lhs.r < rhs.r;
  17. }
  18. } range[MAXN | 1];
  19. inline int read() {
  20. register int x = 0;
  21. register char ch = getchar();
  22. while (!isdigit(ch)) ch = getchar();
  23. while (isdigit(ch)) {
  24. x = x * 10 + ch - '0';
  25. ch = getchar();
  26. }
  27. return x;
  28. }
  29. void find(int x) {
  30. int l, r, mid;
  31. l = 1;
  32. r = x;
  33. while (l <= r) {
  34. mid = (l + r) >> 1;
  35. if (d[x] - d[mid] <= range[x].w) {
  36. r = mid - 1;
  37. range[x].l = mid;
  38. } else l = mid + 1;
  39. }
  40. l = x;
  41. r = n;
  42. while (l <= r) {
  43. mid = (l + r) >> 1;
  44. if (d[mid] - d[x] <= range[x].w) {
  45. l = mid + 1;
  46. range[x].r = mid;
  47. } else r = mid - 1;
  48. }
  49. }
  50. struct Node {
  51. int minv, lazy;
  52. Node *ch[2];
  53. Node() : minv(0), lazy(0) {
  54. ch[0] = ch[1] = NULL;
  55. }
  56. } *root;
  57. void pushUp(Node *o) {
  58. o -> minv = std::min(o -> ch[0] -> minv, o -> ch[1] -> minv);
  59. }
  60. void pushDown(Node *o) {
  61. if (o -> lazy != 0) {
  62. o -> ch[0] -> minv += o -> lazy;
  63. o -> ch[1] -> minv += o -> lazy;
  64. o -> ch[0] -> lazy += o -> lazy;
  65. o -> ch[1] -> lazy += o -> lazy;
  66. o -> lazy = 0;
  67. }
  68. }
  69. void build(Node *&o, int l, int r, int id) {
  70. if (o == NULL) o = new Node;
  71. else o -> lazy = 0;
  72. if (l == r) {
  73. o -> minv = dp[id][l];
  74. o -> lazy = 0;
  75. return;
  76. }
  77. int mid = (l + r) >> 1;
  78. build(o -> ch[0], l, mid, id);
  79. build(o -> ch[1], mid + 1, r, id);
  80. pushUp(o);
  81. }
  82. void modify(Node *o, int l, int r, int ql, int qr, int v) {
  83. if (ql <= l && r <= qr) {
  84. o -> minv += v;
  85. o -> lazy += v;
  86. return;
  87. }
  88. int mid = (l + r) >> 1;
  89. pushDown(o);
  90. if (ql <= mid) modify(o -> ch[0], l, mid, ql, qr, v);
  91. if (mid < qr) modify(o -> ch[1], mid + 1, r, ql, qr, v);
  92. pushUp(o);
  93. }
  94. int query(Node *o, int l, int r, int ql, int qr) {
  95. if (ql <= l && r <= qr) return o -> minv;
  96. int mid = (l + r) >> 1, res = 1e9;
  97. pushDown(o);
  98. if (ql <= mid) res = query(o -> ch[0], l, mid, ql, qr);
  99. if (mid < qr) res = std::min(res, query(o -> ch[1], mid + 1, r, ql, qr));
  100. return res;
  101. }
  102. int main() {
  103. n = read();
  104. K = read();
  105. build(root, 1, n, 0);
  106. for (int i = 2; i <= n; ++i) scanf("%lld", d + i);
  107. for (int i = 1; i <= n; ++i) c[i] = read();
  108. for (int i = 1; i <= n; ++i) {
  109. scanf("%lld", &range[i].w);
  110. find(i);
  111. }
  112. for (int i = 1; i <= n; ++i) range[i].w = read();
  113. d[++n] = 1e9;
  114. ans = 1e9;
  115. int pot = 1;
  116. ++K;
  117. for (int i = 1; i <= n; ++i) {
  118. dp[1][i] = c[i];
  119. for (int j = 1; j < i; ++j) if (range[j].l > i || range[j].r < i) dp[1][i] += range[j].w;
  120. }
  121. ans = dp[1][n];
  122. std::sort(range + 1, range + 1 + n);
  123. for (int i = 2; i <= K; ++i) {
  124. build(root, 1, n, i - 1);
  125. memset(sum, 0, sizeof(sum));
  126. pot = 1;
  127. for (int j = i; j <= n; ++j) {
  128. while (pot <= n && range[pot].r < j) {
  129. if (i <= range[pot].l) modify(root, 1, n, i - 1, range[pot].l - 1, range[pot].w);
  130. ++pot;
  131. }
  132. dp[i][j] = query(root, 1, n, i - 1, j - 1) + c[j];
  133. }
  134. ans = std::min(ans, dp[i][n]);
  135. }
  136. printf("%d\n", ans);
  137. return 0;
  138. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注