[关闭]
@qq290637843 2021-03-22T10:14:46.000000Z 字数 27331 阅读 315

2019上海

题目见https://ac.nowcoder.com/acm/contest/4370

A、Mr. Panda and Dominoes

首先预处理出每个块上下左右四个方向分别有多少个块。
考虑型的数法,将块按照的值分类,那么自然地,以形作为插入,以形作为查询点,就变成插入一些区间,以及查询一些区间,当且仅当时插入区间和查询区间耦合,此问题考虑按照区间右端点从大到小排列,于是对每一个查询区间只需要考虑其内有多少个插入区间的左端点。

  1. #include <bits/stdc++.h>
  2. using ul = std::uint32_t;
  3. using li = std::int32_t;
  4. using ull = std::uint64_t;
  5. using ll = std::int64_t;
  6. ul T;
  7. ul n;
  8. const ul maxn = 1e6;
  9. class data {
  10. public:
  11. ul xp = 0;
  12. ul yp = 0;
  13. ul xm = 0;
  14. ul ym = 0;
  15. };
  16. data map[maxn + 1];
  17. ul tot1;
  18. ull stack1[maxn + 1];
  19. ul calcxp(ul x, ul y)
  20. {
  21. ull v = ull(x) << 32 | y;
  22. auto it = std::lower_bound(stack1 + 1, stack1 + tot1 + 1, v) - stack1;
  23. if (it == tot1 + 1 || stack1[it] != v) {
  24. return 0;
  25. } else if (map[it].xp) {
  26. return map[it].xp;
  27. } else {
  28. return map[it].xp = calcxp(x + 1, y) + 1;
  29. }
  30. }
  31. ul calcyp(ul x, ul y)
  32. {
  33. ull v = ull(x) << 32 | y;
  34. auto it = std::lower_bound(stack1 + 1, stack1 + tot1 + 1, v) - stack1;
  35. if (it == tot1 + 1 || stack1[it] != v) {
  36. return 0;
  37. } else if (map[it].yp) {
  38. return map[it].yp;
  39. } else {
  40. return map[it].yp = calcyp(x, y + 1) + 1;
  41. }
  42. }
  43. ul calcxm(ul x, ul y)
  44. {
  45. ull v = ull(x) << 32 | y;
  46. auto it = std::lower_bound(stack1 + 1, stack1 + tot1 + 1, v) - stack1;
  47. if (it == tot1 + 1 || stack1[it] != v) {
  48. return 0;
  49. } else if (map[it].xm) {
  50. return map[it].xm;
  51. } else {
  52. return map[it].xm = calcxm(x - 1, y) + 1;
  53. }
  54. }
  55. ul calcym(ul x, ul y)
  56. {
  57. ull v = ull(x) << 32 | y;
  58. auto it = std::lower_bound(stack1 + 1, stack1 + tot1 + 1, v) - stack1;
  59. if (it == tot1 + 1 || stack1[it] != v) {
  60. return 0;
  61. } else if (map[it].ym) {
  62. return map[it].ym;
  63. } else {
  64. return map[it].ym = calcym(x, y - 1) + 1;
  65. }
  66. }
  67. ul tree[1 << 22];
  68. ul sz;
  69. ul query(ul l, ul r)
  70. {
  71. ul ret = 0;
  72. for (l = l - 1 | sz, r = r + 1 | sz; l ^ r ^ 1; l >>= 1, r >>= 1) {
  73. if (~l & 1) {
  74. ret += tree[l ^ 1];
  75. }
  76. if (r & 1) {
  77. ret += tree[r ^ 1];
  78. }
  79. }
  80. return ret;
  81. }
  82. void change(ul pos, ul v)
  83. {
  84. for (pos |= sz; pos; pos >>= 1) {
  85. tree[pos] += v;
  86. }
  87. }
  88. class seg {
  89. public:
  90. ul f = 0;
  91. ul b = 0;
  92. bool insert = false;
  93. seg()=default;
  94. seg(ul x, ul y, bool z): f(x), b(y), insert(z) {}
  95. };
  96. ul datas[maxn + maxn + 1];
  97. ul tot;
  98. ul stack2[maxn + maxn + 1];
  99. ul tot2;
  100. std::vector<seg> blobs[maxn + maxn + 1];
  101. std::vector<seg>& at(ul v)
  102. {
  103. return blobs[std::lower_bound(stack2 + 1, stack2 + tot2 + 1, v) - stack2];
  104. }
  105. int main()
  106. {
  107. std::scanf("%u", &T);
  108. for (ul Case = 1; Case <= T; ++Case) {
  109. std::scanf("%u", &n);
  110. tot1 = 0;
  111. tot2 = 0;
  112. for (ul i = 1; i <= n; ++i) {
  113. ul x, y;
  114. std::scanf("%u%u", &x, &y);
  115. ++tot1;
  116. stack1[tot1] = ull(x) << 32 | y;
  117. map[tot1] = data();
  118. }
  119. std::sort(stack1 + 1, stack1 + tot1 + 1);
  120. for (ul it = 1; it <= tot1; ++it) {
  121. ull tmp = stack1[it];
  122. calcxp(tmp >> 32, tmp);
  123. calcyp(tmp >> 32, tmp);
  124. calcxm(tmp >> 32, tmp);
  125. calcym(tmp >> 32, tmp);
  126. }
  127. ul ans = 0;
  128. tot2 = 0;
  129. for (ul it = 1; it <= tot1; ++it) {
  130. ul x = stack1[it] >> 32;
  131. ul y = stack1[it];
  132. ++tot2;
  133. stack2[tot2] = x + x + y;
  134. ++tot2;
  135. stack2[tot2] = x + x + y + 1;
  136. }
  137. std::sort(stack2 + 1, stack2 + tot2 + 1);
  138. tot2 = std::unique(stack2 + 1, stack2 + tot2 + 1) - stack2 - 1;
  139. for (ul i = 1; i <= tot2; ++i) {
  140. blobs[i].resize(0);
  141. }
  142. for (ul it = 1; it <= tot1; ++it) {
  143. ul x = stack1[it] >> 32;
  144. ul y = stack1[it];
  145. at(x + x + y).push_back(seg(x, x + std::min(map[it].xp, map[it].ym >> 1) - 1, true));
  146. at(x + x + y + 1).push_back(seg(x - std::min(map[it].xm, map[it].yp >> 1) + 1, x, false));
  147. }
  148. for (ul it = 1; it <= tot2; ++it) {
  149. std::sort(blobs[it].begin(), blobs[it].end(), [](const seg& a, const seg& b){return a.b != b.b ? a.b > b.b : a.insert > b.insert;});
  150. tot = 0;
  151. for (const auto& s : blobs[it]) {
  152. ++tot;
  153. datas[tot] = s.f;
  154. datas[tot] = s.b;
  155. }
  156. std::sort(datas + 1, datas + tot + 1);
  157. tot = std::unique(datas + 1, datas + tot + 1) - datas - 1;
  158. sz = 1;
  159. while (sz < tot + 2) {
  160. sz <<= 1;
  161. }
  162. std::memset(tree, 0, sizeof(ul) * (sz << 1));
  163. for (const auto& s : blobs[it]) {
  164. ul f = std::lower_bound(datas + 1, datas + tot + 1, s.f) - datas;
  165. ul b = std::lower_bound(datas + 1, datas + tot + 1, s.b) - datas;
  166. if (s.insert) {
  167. change(f, 1);
  168. } else {
  169. ans += query(f, b);
  170. }
  171. }
  172. }
  173. tot2 = 0;
  174. for (ul it = 1; it <= tot1; ++it) {
  175. ul x = stack1[it] >> 32;
  176. ul y = stack1[it];
  177. ++tot2;
  178. stack2[tot2] = x + y + y;
  179. ++tot2;
  180. stack2[tot2] = x + y + y + 1;
  181. }
  182. std::sort(stack2 + 1, stack2 + tot2 + 1);
  183. tot2 = std::unique(stack2 + 1, stack2 + tot2 + 1) - stack2 - 1;
  184. for (ul i = 1; i <= tot2; ++i) {
  185. blobs[i].resize(0);
  186. }
  187. for (ul it = 1; it <= tot1; ++it) {
  188. ul x = stack1[it] >> 32;
  189. ul y = stack1[it];
  190. at(x + y + y).push_back(seg(y, y + std::min(map[it].yp, map[it].xm >> 1) - 1, true));
  191. at(x + y + y + 1).push_back(seg(y - std::min(map[it].ym, map[it].xp >> 1) + 1, y, false));
  192. }
  193. for (ul it = 1; it <= tot2; ++it) {
  194. std::sort(blobs[it].begin(), blobs[it].end(), [](const seg& a, const seg& b){return a.b != b.b ? a.b > b.b : a.insert > b.insert;});
  195. tot = 0;
  196. for (const auto& s : blobs[it]) {
  197. ++tot;
  198. datas[tot] = s.f;
  199. datas[tot] = s.b;
  200. }
  201. std::sort(datas + 1, datas + tot + 1);
  202. tot = std::unique(datas + 1, datas + tot + 1) - datas - 1;
  203. sz = 1;
  204. while (sz < tot + 2) {
  205. sz <<= 1;
  206. }
  207. std::memset(tree, 0, sizeof(ul) * (sz << 1));
  208. for (const auto& s : blobs[it]) {
  209. ul f = std::lower_bound(datas + 1, datas + tot + 1, s.f) - datas;
  210. ul b = std::lower_bound(datas + 1, datas + tot + 1, s.b) - datas;
  211. if (s.insert) {
  212. change(f, 1);
  213. } else {
  214. ans += query(f, b);
  215. }
  216. }
  217. }
  218. std::printf("Case #%u: %u\n", Case, ans);
  219. }
  220. return 0;
  221. }

B、Prefix Code

简单题

  1. #include <bits/stdc++.h>
  2. using ul = std::uint32_t;
  3. using li = std::int32_t;
  4. using ull = std::uint64_t;
  5. using ll = std::int64_t;
  6. ul T;
  7. ul n;
  8. const ul maxn = 1e4;
  9. std::unordered_set<ull> set;
  10. ull data[maxn + 1];
  11. char str[12];
  12. int main()
  13. {
  14. std::scanf("%u", &T);
  15. for (ul Case = 1; Case <= T; ++Case) {
  16. std::scanf("%u", &n);
  17. for (ul i = 1; i <= n; ++i) {
  18. std::scanf("%s", str + 1);
  19. data[i] = 1;
  20. for (ul j = 1; str[j]; ++j) {
  21. data[i] *= 10;
  22. data[i] += str[j] - '0';
  23. }
  24. }
  25. bool flag = true;
  26. set.clear();
  27. for (ul i = 1; i <= n; ++i) {
  28. if (set.find(data[i]) != set.end()) {
  29. flag = false;
  30. break;
  31. }
  32. ull tmp = data[i];
  33. while (tmp) {
  34. set.insert(tmp);
  35. tmp /= 10;
  36. }
  37. }
  38. if (flag) {
  39. set.clear();
  40. for (ul i = n; i >= 1; --i) {
  41. if (set.find(data[i]) != set.end()) {
  42. flag = false;
  43. break;
  44. }
  45. ull tmp = data[i];
  46. while (tmp) {
  47. set.insert(tmp);
  48. tmp /= 10;
  49. }
  50. }
  51. }
  52. std::printf("Case #%u: %s\n", Case, flag ? "Yes" : "No");
  53. }
  54. return 0;
  55. }

C、Maze

先解决一个子问题:从出发,到,满足在过程中的路径数量。考虑容斥,将两条直线叫做,那么所有违法路径一定有接触两条直线的顺序。现在考虑其接触过,这意味着,其最后一次接触之后的路径全都依对称,正好和从出发到的路线一一对应,而这样的路线一定以或者的顺序收尾。同理,以或者的顺序收尾的路线和从出发到的路线一一对应。直接减掉这两部分之后,还需要将以或以收尾的路线加回来,因为重复减掉了。而继续迭代,以或以收尾的路线,先将最后一次接触之后的路线依对称,再将最后一次接触之后的路线依对称,就和从出发到的路线一一对应了。于是一直这样迭代并乘上容斥系数就能刚好只减去以结尾的路线。
关于必须经过以及必不经过的点再容斥就是了。

  1. #include <bits/stdc++.h>
  2. using ul = std::uint32_t;
  3. using li = std::int32_t;
  4. using ull = std::uint64_t;
  5. using ll = std::int64_t;
  6. const ul mod = 1e9 + 7;
  7. ul plus(ul a, ul b)
  8. {
  9. return a + b < mod ? a + b : a + b - mod;
  10. }
  11. ul minus(ul a, ul b)
  12. {
  13. return a < b ? a + mod - b : a - b;
  14. }
  15. ul mul(ul a, ul b)
  16. {
  17. return ull(a) * ull(b) % mod;
  18. }
  19. void exgcd(li a, li b, li& x, li& y)
  20. {
  21. if (b) {
  22. exgcd(b, a % b, y, x);
  23. y -= a / b * x;
  24. } else {
  25. x = 1;
  26. y = 0;
  27. }
  28. }
  29. ul inverse(ul a)
  30. {
  31. li x, y;
  32. exgcd(a, mod, x, y);
  33. return x < 0 ? x + li(mod) : x;
  34. }
  35. ul T;
  36. ul n, m, s, k;
  37. const ul maxn = 1e5;
  38. const ul maxm = 1e5;
  39. const ul maxs = 10;
  40. const ul maxk = 20;
  41. std::pair<ul, ul> c[maxs + maxk + 2 + 1];
  42. ul tot;
  43. ul fac[maxn + maxm + 1];
  44. ul fiv[maxn + maxm + 1];
  45. ul calc(ul a, ul b)
  46. {
  47. return mul(fac[a + b], mul(fiv[a], fiv[b]));
  48. }
  49. ul f(ul n, ul m, ul t1, ul t2)
  50. {
  51. ul ret = calc(n, m);
  52. for (ul a = n, b = m, p = 1; ; p = !p) {
  53. std::swap(a, b);
  54. if (p) {
  55. if (a < t1) {
  56. break;
  57. }
  58. a -= t1;
  59. b += t1;
  60. ret = minus(ret, calc(a, b));
  61. } else {
  62. if (b < t2) {
  63. break;
  64. }
  65. a += t2;
  66. b -= t2;
  67. ret = plus(ret, calc(a, b));
  68. }
  69. }
  70. for (ul a = n, b = m, p = 1; ; p = !p) {
  71. std::swap(a, b);
  72. if (p) {
  73. if (b < t2) {
  74. break;
  75. }
  76. a += t2;
  77. b -= t2;
  78. ret = minus(ret, calc(a, b));
  79. } else {
  80. if (a < t1) {
  81. break;
  82. }
  83. a -= t1;
  84. b += t1;
  85. ret = plus(ret, calc(a, b));
  86. }
  87. }
  88. return ret;
  89. }
  90. ul sub[maxs + maxk + 2 + 1][maxs + maxk + 2 + 1];
  91. ul d[maxs + maxk + 2 + 1];
  92. ul e[maxs + maxk + 2 + 1];
  93. int main()
  94. {
  95. fac[0] = 1;
  96. for (ul i = 1; i <= maxn + maxm; ++i) {
  97. fac[i] = mul(fac[i - 1], i);
  98. }
  99. fiv[maxn + maxm] = inverse(fac[maxn + maxm]);
  100. for (ul i = maxn + maxm; i; --i) {
  101. fiv[i - 1] = mul(fiv[i], i);
  102. }
  103. std::scanf("%u", &T);
  104. for (ul Case = 1; Case <= T; ++Case) {
  105. std::scanf("%u%u%u%u", &n, &m, &s, &k);
  106. for (ul i = k + 1; i <= k + s; ++i) {
  107. std::scanf("%u%u", &c[i].first, &c[i].second);
  108. e[i] = i;
  109. }
  110. for (ul i = 1; i <= k; ++i) {
  111. std::scanf("%u%u", &c[i].first, &c[i].second);
  112. e[i] = i;
  113. }
  114. c[k + s + 1] = std::pair<ul, ul>(1, 1);
  115. e[k + s + 1] = k + s + 1;
  116. c[k + s + 2] = std::pair<ul, ul>(n, m);
  117. e[k + s + 2] = k + s + 2;
  118. std::sort(e + 1, e + k + s + 2 + 1, [&](ul a, ul b){return c[a] < c[b];});
  119. for (ul i = 1; i <= k + s + 2; ++i) {
  120. for (ul j = 1; j <= k + s + 2; ++j) {
  121. if (c[i].first > c[j].first || c[i].second > c[j].second) {
  122. sub[i][j] = 0;
  123. } else {
  124. const auto& to = c[j];
  125. const auto& from = c[i];
  126. sub[i][j] = f(to.first - from.first, to.second - from.second, from.first - from.second + 1 + m - n, from.second - from.first + 1);
  127. }
  128. }
  129. }
  130. ul ans = 0;
  131. for (ul mask = (1 << k) - 1; ~mask; --mask) {
  132. tot = 0;
  133. for (ul i = 1; i <= k + s + 2; ++i) {
  134. if (e[i] >= k + 1 || (mask >> e[i] - 1 & 1)) {
  135. ++tot;
  136. d[tot] = e[i];
  137. }
  138. }
  139. ul tans = 1;
  140. for (ul i = 1, j = 2; j <= tot; ++i, ++j) {
  141. if (sub[d[i]][d[j]] == 0) {
  142. tans = 0;
  143. break;
  144. }
  145. tans = mul(tans, sub[d[i]][d[j]]);
  146. }
  147. if (tot - s - 2 & 1) {
  148. ans = minus(ans, tans);
  149. } else {
  150. ans = plus(ans, tans);
  151. }
  152. }
  153. std::printf("Case #%u: %u\n", Case, ans);
  154. }
  155. return 0;
  156. }

D、Spanning Tree Removal

参考https://www.zybuluo.com/qq290637843/note/1776933的情况一

  1. #include <bits/stdc++.h>
  2. using ul = std::uint32_t;
  3. using li = std::int32_t;
  4. using ull = std::uint64_t;
  5. using ll = std::int64_t;
  6. ul T;
  7. ul n;
  8. ul f(ul x, ul y, ul n)
  9. {
  10. return x + y <= n - 1 ? x + y : x + y - n + 1;
  11. }
  12. ul g(ul x, ul n)
  13. {
  14. return x + x <= n - 1 ? n - x : n + 1 - x;
  15. }
  16. int main()
  17. {
  18. std::scanf("%u", &T);
  19. for (ul Case = 1; Case <= T; ++Case) {
  20. std::scanf("%u", &n);
  21. std::printf("Case #%u: %u\n", Case, n >> 1);
  22. if (n & 1) {
  23. for (ul i = 1; i <= (n >> 1); ++i) {
  24. std::printf("%u %u\n", n, f(1, i - 1, n));
  25. for (ul j = 1, gjm1 = 1; j <= n - 2; ++j, gjm1 = g(gjm1, n)) {
  26. std::printf("%u %u\n", f(gjm1, i - 1, n), f(g(gjm1, n), i - 1, n));
  27. }
  28. }
  29. } else {
  30. ++n;
  31. for (ul i = 1; i <= (n >> 1); ++i) {
  32. for (ul j = 1, gjm1 = 1; j <= n - 2; ++j, gjm1 = g(gjm1, n)) {
  33. std::printf("%u %u\n", f(gjm1, i - 1, n), f(g(gjm1, n), i - 1, n));
  34. }
  35. }
  36. }
  37. }
  38. return 0;
  39. }

E、Cave Escape

显然,能获得的边构成一棵树

  1. #include <bits/stdc++.h>
  2. using ul = std::uint32_t;
  3. using li = std::int32_t;
  4. using ull = std::uint64_t;
  5. using ll = std::int64_t;
  6. ul T;
  7. ul n, m, sr, sc, tr, tc;
  8. ul a, b, c, p;
  9. const ul maxn = 1e3;
  10. const ul maxm = 1e3;
  11. ul x[maxn * maxm + 1];
  12. ul fa[maxn * maxm + 1];
  13. ul rk[maxn * maxm + 1];
  14. std::vector<std::pair<ul, ul>> edges[10001];
  15. ul getfather(ul x)
  16. {
  17. return x == fa[x] ? x : fa[x] = getfather(fa[x]);
  18. }
  19. bool connect(ul x, ul y)
  20. {
  21. x = getfather(x);
  22. y = getfather(y);
  23. if (x == y) {
  24. return false;
  25. }
  26. if (rk[x] > rk[y]) {
  27. fa[y] = x;
  28. } else if (rk[y] > rk[x]) {
  29. fa[x] = y;
  30. } else {
  31. fa[y] = x;
  32. ++rk[x];
  33. }
  34. return true;
  35. }
  36. int main()
  37. {
  38. std::scanf("%u", &T);
  39. for (ul Case = 1; Case <= T; ++Case) {
  40. std::scanf("%u%u%u%u%u%u", &n, &m, &sr, &sc, &tr, &tc);
  41. std::scanf("%u%u%u%u%u%u", &x[1], &x[2], &a, &b, &c, &p);
  42. for (ul i = 0; i <= p * p; ++i) {
  43. edges[i].resize(0);
  44. }
  45. for (ul i = 3; i <= n * m; ++i) {
  46. x[i] = (a * x[i - 1] + b * x[i - 2] + c) % p;
  47. }
  48. for (ul i = 1; i <= n * m; ++i) {
  49. fa[i] = i;
  50. rk[i] = 0;
  51. }
  52. for (ul i = 1; i <= n; ++i) {
  53. for (ul j = 1; j <= m - 1; ++j) {
  54. ul s = (i - 1) * m + j;
  55. ul t = (i - 1) * m + j + 1;
  56. edges[x[s] * x[t]].push_back(std::pair<ul, ul>(s, t));
  57. }
  58. }
  59. for (ul i = 1; i <= n - 1; ++i) {
  60. for (ul j = 1; j <= m; ++j) {
  61. ul s = (i - 1) * m + j;
  62. ul t = i * m + j;
  63. edges[x[s] * x[t]].push_back(std::pair<ul, ul>(s, t));
  64. }
  65. }
  66. ull ans = 0;
  67. for (ul i = p * p; ~i; --i) {
  68. for (const auto& e : edges[i]) {
  69. ul s = e.first;
  70. ul t = e.second;
  71. if (connect(s, t)) {
  72. ans += i;
  73. }
  74. }
  75. }
  76. std::printf("Case #%u: %llu\n", Case, ans);
  77. }
  78. return 0;
  79. }

F、A Simple Problem On A Tree

重链剖分线段树

  1. #include <bits/stdc++.h>
  2. using ul = std::uint32_t;
  3. using li = std::int32_t;
  4. using ull = std::uint64_t;
  5. using ll = std::int64_t;
  6. const ul mod = 1e9 + 7;
  7. ul plus(ul a, ul b)
  8. {
  9. return a + b < mod ? a + b : a + b - mod;
  10. }
  11. ul mul(ul a, ul b)
  12. {
  13. return ull(a) * ull(b) % mod;
  14. }
  15. ul T;
  16. ul n;
  17. const ul maxn = 1e5;
  18. std::vector<ul> edges[maxn + 1];
  19. ul dfn[maxn + 1];
  20. ul fa[maxn + 1];
  21. ul hvhd[maxn + 1];
  22. ul bigson[maxn + 1];
  23. ul depth[maxn + 1];
  24. void search1(ul curr, ul prev, ul& sz)
  25. {
  26. sz = 1;
  27. ul bigsz = 0;
  28. for (ul next : edges[curr]) {
  29. if (next == prev) {
  30. continue;
  31. }
  32. depth[next] = depth[curr] + 1;
  33. fa[next] = curr;
  34. ul tsz;
  35. search1(next, curr, tsz);
  36. sz += tsz;
  37. if (tsz > bigsz) {
  38. bigson[curr] = next;
  39. bigsz = tsz;
  40. }
  41. }
  42. }
  43. ul tim;
  44. void search2(ul curr)
  45. {
  46. ++tim;
  47. dfn[curr] = tim;
  48. if (bigson[curr]) {
  49. hvhd[bigson[curr]] = hvhd[curr];
  50. search2(bigson[curr]);
  51. }
  52. for (ul next : edges[curr]) {
  53. if (next == fa[curr] || next == bigson[curr]) {
  54. continue;
  55. }
  56. hvhd[next] = next;
  57. search2(next);
  58. }
  59. }
  60. class node {
  61. public:
  62. ul sum[4];
  63. ul a = ~ul(0);
  64. ul b = ~ul(0);
  65. ul c = ~ul(0);
  66. };
  67. ul sz;
  68. const ul maxsz = 1 << 17;
  69. node tree[maxsz << 1];
  70. void combine(ul x, ul y)
  71. {
  72. if (!~tree[x].a && !~tree[x].c) {
  73. return;
  74. }
  75. if (~tree[x].c) {
  76. tree[y].a = ~ul(0);
  77. tree[y].b = ~ul(0);
  78. tree[y].c = tree[x].c;
  79. } else if (~tree[y].a) {
  80. tree[y].b = plus(mul(tree[x].a, tree[y].b), tree[x].b);
  81. tree[y].a = mul(tree[x].a, tree[y].a);
  82. tree[y].c = ~ul(0);
  83. } else if (~tree[y].c) {
  84. tree[y].a = ~ul(0);
  85. tree[y].b = ~ul(0);
  86. tree[y].c = plus(mul(tree[x].a, tree[y].c), tree[x].b);
  87. } else {
  88. tree[y].a = tree[x].a;
  89. tree[y].b = tree[x].b;
  90. tree[y].c = tree[x].c;
  91. }
  92. }
  93. void push(ul x, bool down)
  94. {
  95. if (~tree[x].a) {
  96. ul a = tree[x].a;
  97. ul a2 = mul(a, a);
  98. ul a3 = mul(a2, a);
  99. ul b = tree[x].b;
  100. ul b2 = mul(b, b);
  101. ul b3 = mul(b2, b);
  102. ul a2b = mul(a2, b);
  103. ul ab2 = mul(a, b2);
  104. ul ab = mul(a, b);
  105. tree[x].sum[3] = plus(plus(mul(a3, tree[x].sum[3]), mul(mul(3, a2b), tree[x].sum[2])), plus(mul(mul(3, ab2), tree[x].sum[1]), mul(b3, tree[x].sum[0])));
  106. tree[x].sum[2] = plus(plus(mul(a2, tree[x].sum[2]), mul(mul(2, ab), tree[x].sum[1])), mul(b2, tree[x].sum[0]));
  107. tree[x].sum[1] = plus(mul(a, tree[x].sum[1]), mul(b, tree[x].sum[0]));
  108. } else if (~tree[x].c) {
  109. ul c = tree[x].c;
  110. ul c2 = mul(c, c);
  111. ul c3 = mul(c2, c);
  112. tree[x].sum[3] = mul(c3, tree[x].sum[0]);
  113. tree[x].sum[2] = mul(c2, tree[x].sum[0]);
  114. tree[x].sum[1] = mul(c, tree[x].sum[0]);
  115. }
  116. if (down) {
  117. combine(x, x << 1);
  118. combine(x, x << 1 | 1);
  119. }
  120. tree[x].a = ~ul(0);
  121. tree[x].b = ~ul(0);
  122. tree[x].c = ~ul(0);
  123. }
  124. void change(ul l, ul r, ul nl, ul nr, ul nid, ul a, ul b, ul c)
  125. {
  126. tree[nid].sum[0] = nr - nl + 1;
  127. push(nid, nl != nr);
  128. if (l <= nl && r >= nr) {
  129. tree[nid].a = a;
  130. tree[nid].b = b;
  131. tree[nid].c = c;
  132. push(nid, nl != nr);
  133. return;
  134. }
  135. ul midl = nl + nr >> 1;
  136. ul midr = midl + 1;
  137. if (l <= midl) {
  138. change(l, r, nl, midl, nid << 1, a, b, c);
  139. } else {
  140. tree[nid << 1].sum[0] = midl - nl + 1;
  141. push(nid << 1, nl != midl);
  142. }
  143. if (r >= midr) {
  144. change(l, r, midr, nr, nid << 1 | 1, a, b, c);
  145. } else {
  146. tree[nid << 1 | 1].sum[0] = nr - midr + 1;
  147. push(nid << 1 | 1, midr != nr);
  148. }
  149. for (ul i = 0; i <= 3; ++i) {
  150. tree[nid].sum[i] = plus(tree[nid << 1].sum[i], tree[nid << 1 | 1].sum[i]);
  151. }
  152. }
  153. ul query(ul l, ul r, ul nl, ul nr, ul nid)
  154. {
  155. tree[nid].sum[0] = nr - nl + 1;
  156. push(nid, nl != nr);
  157. if (l <= nl && r >= nr) {
  158. return tree[nid].sum[3];
  159. }
  160. ul midl = nl + nr >> 1;
  161. ul midr = midl + 1;
  162. ul ret = 0;
  163. if (l <= midl) {
  164. ret = plus(ret, query(l, r, nl, midl, nid << 1));
  165. }
  166. if (r >= midr) {
  167. ret = plus(ret, query(l, r, midr, nr, nid << 1 | 1));
  168. }
  169. return ret;
  170. }
  171. ul q;
  172. int main()
  173. {
  174. std::scanf("%u", &T);
  175. for (ul Case = 1; Case <= T; ++Case) {
  176. std::scanf("%u", &n);
  177. for (ul i = 1; i <= n; ++i) {
  178. bigson[i] = 0;
  179. edges[i].resize(0);
  180. }
  181. for (ul i = 1; i <= n - 1; ++i) {
  182. ul a, b;
  183. std::scanf("%u%u", &a, &b);
  184. edges[a].push_back(b);
  185. edges[b].push_back(a);
  186. }
  187. search1(1, 0, n);
  188. hvhd[1] = 1;
  189. tim = 0;
  190. search2(1);
  191. for (ul i = 1; i <= n; ++i) {
  192. ul w;
  193. std::scanf("%u", &w);
  194. change(dfn[i], dfn[i], 1, n, 1, ~ul(0), ~ul(0), w);
  195. }
  196. std::printf("Case #%u:\n", Case);
  197. std::scanf("%u", &q);
  198. for (ul i = 1; i <= q; ++i) {
  199. ul type;
  200. std::scanf("%u", &type);
  201. if (type != 4) {
  202. ul u, v, w;
  203. std::scanf("%u%u%u", &u, &v, &w);
  204. while (hvhd[u] != hvhd[v]) {
  205. if (depth[hvhd[u]] > depth[hvhd[v]]) {
  206. std::swap(u, v);
  207. }
  208. if (type == 1) {
  209. change(dfn[hvhd[v]], dfn[v], 1, n, 1, ~ul(0), ~ul(0), w);
  210. } else if (type == 2) {
  211. change(dfn[hvhd[v]], dfn[v], 1, n, 1, 1, w, ~ul(0));
  212. } else if (type == 3) {
  213. change(dfn[hvhd[v]], dfn[v], 1, n, 1, w, 0, ~ul(0));
  214. }
  215. v = fa[hvhd[v]];
  216. }
  217. if (depth[u] > depth[v]) {
  218. std::swap(u, v);
  219. }
  220. if (type == 1) {
  221. change(dfn[u], dfn[v], 1, n, 1, ~ul(0), ~ul(0), w);
  222. } else if (type == 2) {
  223. change(dfn[u], dfn[v], 1, n, 1, 1, w, ~ul(0));
  224. } else if (type == 3) {
  225. change(dfn[u], dfn[v], 1, n, 1, w, 0, ~ul(0));
  226. }
  227. } else {
  228. ul u, v;
  229. std::scanf("%u%u", &u, &v);
  230. ul ret = 0;
  231. while (hvhd[u] != hvhd[v]) {
  232. if (depth[hvhd[u]] > depth[hvhd[v]]) {
  233. std::swap(u, v);
  234. }
  235. ret = plus(ret, query(dfn[hvhd[v]], dfn[v], 1, n, 1));
  236. v = fa[hvhd[v]];
  237. }
  238. if (depth[u] > depth[v]) {
  239. std::swap(u, v);
  240. }
  241. ret = plus(ret, query(dfn[u], dfn[v], 1, n, 1));
  242. std::printf("%u\n", ret);
  243. }
  244. }
  245. }
  246. return 0;
  247. }

G、Play the game SET

将所有合法方案作为点,如果两个点之间有重复牌就不连边,其余全部连边,于是变为最大团问题。
最大团算法见此https://chaoli.club/index.php/5052/

  1. #include <bits/stdc++.h>
  2. using ul = std::uint32_t;
  3. using li = std::int32_t;
  4. using ull = std::uint64_t;
  5. using ll = std::int64_t;
  6. ul T;
  7. ul n;
  8. std::map<std::string, std::pair<ul, ul>> strtov;
  9. const std::string name[4][3] = {{"one", "two", "three"}, {"diamond", "squiggle", "oval"}, {"solid", "striped", "open"}, {"red", "green", "purple"}};
  10. const ul maxn = 38;
  11. ul v[maxn + 1][4];
  12. char str[300];
  13. std::string tmp;
  14. ul tot;
  15. ul q[300][3];
  16. std::vector<ul> had[maxn + 1];
  17. using data = std::bitset<256>;
  18. data g[256];
  19. data ansr;
  20. data getfirst(const data& x)
  21. {
  22. ul tmp = x._Find_next(0);
  23. data ret;
  24. ret[tmp] = 1;
  25. return ret;
  26. }
  27. ul first(const data& x)
  28. {
  29. return x._Find_next(0);
  30. }
  31. bool flag = false;
  32. void bk(const data& r, data p, data x)
  33. {
  34. if (!p.any() && !x.any()) {
  35. if (r.count() > ansr.count()) {
  36. ansr = r;
  37. if (r.count() == n / 3) {
  38. flag = true;
  39. }
  40. }
  41. return;
  42. }
  43. data px = p | x;
  44. data u = getfirst(px);
  45. for (data tu = getfirst(px); px.any(); px &= ~tu, tu = getfirst(px)) {
  46. if ((p & g[first(tu)]).count() > (p & g[first(u)]).count()) {
  47. u = tu;
  48. }
  49. }
  50. data ext = p & ~g[first(u)];
  51. for (data v = getfirst(ext); ext.any(); p &= ~v, x |= v, ext &= ~v, v = getfirst(ext)) {
  52. bk(r | v, p & g[first(v)], x & g[first(v)]);
  53. if (flag) {
  54. return;
  55. }
  56. }
  57. }
  58. int main()
  59. {
  60. for (ul i = 0; i != 4; ++i) {
  61. for (ul j = 0; j != 3; ++j) {
  62. strtov[name[i][j]] = std::pair<ul, ul>(i, j);
  63. }
  64. }
  65. std::scanf("%u", &T);
  66. for (ul Case = 1; Case <= T; ++Case) {
  67. std::scanf("%u", &n);
  68. for (ul i = 1; i <= n; ++i) {
  69. had[i].resize(0);
  70. std::scanf("%s", str + 1);
  71. for (ul j = 1; str[j]; ++j) {
  72. if (str[j] == ']') {
  73. auto p = strtov[tmp];
  74. v[i][p.first] = p.second;
  75. tmp.resize(0);
  76. } else if (str[j] != '[') {
  77. tmp.push_back(str[j]);
  78. }
  79. }
  80. }
  81. tot = 0;
  82. for (ul a = 1; a + 2 <= n; ++a) {
  83. for (ul b = a + 1; b + 1 <= n; ++b) {
  84. for (ul c = b + 1; c <= n; ++c) {
  85. bool flag = true;
  86. for (ul i = 0; i != 4; ++i) {
  87. if ((v[a][i] + v[b][i] + v[c][i]) % 3) {
  88. flag = false;
  89. break;
  90. }
  91. }
  92. if (flag) {
  93. ++tot;
  94. q[tot][0] = a;
  95. q[tot][1] = b;
  96. q[tot][2] = c;
  97. had[a].push_back(tot);
  98. had[b].push_back(tot);
  99. had[c].push_back(tot);
  100. }
  101. }
  102. }
  103. }
  104. for (ul i = 1; i <= tot; ++i) {
  105. g[i] = 0;
  106. for (ul j = 1; j <= tot; ++j) {
  107. if (i != j) {
  108. g[i][j] = 1;
  109. }
  110. }
  111. }
  112. for (ul a = 1; a <= n; ++a) {
  113. for (ul s = 0; s + 1 < had[a].size(); ++s) {
  114. for (ul t = s + 1; t < had[a].size(); ++t) {
  115. g[had[a][s]][had[a][t]] = 0;
  116. g[had[a][t]][had[a][s]] = 0;
  117. }
  118. }
  119. }
  120. ansr = 0;
  121. data all;
  122. for (ul i = 1; i <= tot; ++i) {
  123. all[i] = 1;
  124. }
  125. flag = false;
  126. bk(0, all, all);
  127. std::printf("Case #%u: %u\n", Case, ul(ansr.count()));
  128. for (ul i = 1; i <= tot; ++i) {
  129. if (ansr[i]) {
  130. std::printf("%u %u %u\n", q[i][0], q[i][1], q[i][2]);
  131. }
  132. }
  133. }
  134. return 0;
  135. }

H、Tree Partition

二分贪心

  1. #include <bits/stdc++.h>
  2. using ul = std::uint32_t;
  3. using li = std::int32_t;
  4. using ull = std::uint64_t;
  5. using ll = std::int64_t;
  6. ul T;
  7. ul n;
  8. ul k;
  9. const ul maxn = 1e5;
  10. ul w[maxn + 1];
  11. std::vector<ul> edges[maxn + 1];
  12. std::vector<ull> stack[maxn + 1];
  13. void search(ul curr, ul prev, ull bound, ul& cnt, ull& sum)
  14. {
  15. stack[curr].resize(0);
  16. cnt = 0;
  17. for (ul next : edges[curr]) {
  18. if (next == prev) {
  19. continue;
  20. }
  21. stack[curr].push_back(0);
  22. ul tcnt;
  23. search(next, curr, bound, tcnt, stack[curr].back());
  24. cnt += tcnt;
  25. }
  26. std::sort(stack[curr].begin(), stack[curr].end());
  27. sum = w[curr];
  28. for (ul i = 0; i != stack[curr].size(); ++i) {
  29. if (sum + stack[curr][i] > bound) {
  30. cnt += stack[curr].size() - i;
  31. break;
  32. }
  33. sum += stack[curr][i];
  34. }
  35. }
  36. int main()
  37. {
  38. std::scanf("%u", &T);
  39. for (ul Case = 1; Case <= T; ++Case) {
  40. std::scanf("%u%u", &n, &k);
  41. for (ul i = 1; i <= n; ++i) {
  42. edges[i].resize(0);
  43. }
  44. ull mx = 0;
  45. for (ul i = 1; i <= n - 1; ++i) {
  46. ul u, v;
  47. std::scanf("%u%u", &u, &v);
  48. edges[u].push_back(v);
  49. edges[v].push_back(u);
  50. }
  51. for (ul i = 1; i <= n; ++i) {
  52. std::scanf("%u", &w[i]);
  53. mx = std::max(mx, ull(w[i]));
  54. }
  55. ull l = mx - 1, r = 1e14;
  56. while (l + 1 != r) {
  57. ull mid = l + r >> 1;
  58. ul cnt;
  59. ull s;
  60. search(1, 0, mid, cnt, s);
  61. if (cnt >= k) {
  62. l = mid;
  63. } else {
  64. r = mid;
  65. }
  66. }
  67. std::printf("Case #%u: %llu\n", Case, r);
  68. }
  69. return 0;
  70. }

I、Portal

首先将原问题重新叙述如下:
有一个长方形,有两个点,对于中的两点,定义两点的距离为

找到最大的两点。
首先引入一个很符合直觉的猜想:对于中的紧致凸集,且是用维边界、维边界、……、维边界所描述的“平直边界凸集”,而有个紧致凸集,且包含了的所有维边界,那么就包含了(我不知道怎么证明,但是至少在零一二三维空间上可以很直观感受这一点)
现在考虑将分为四个紧凸集的并:首先沿着两个传送门的中垂线将分为两个紧凸集,那么被分为,注意无论在哪个部分中,函数定义中所用到的三个凸函数都至少有一个会失效(在第一部分,后两个函数失效;在第二部分,后两个函数失效;在第三部分,第三个函数失效;在第四部分,第二个函数失效),于是根据之前的猜想可知:对于任何一个部分,函数的最大值点一定取在一维边界上,换言之,一个点在角上,一个点在边或角上。但注意这里的“角”包括了中垂线和长方形的交点,“边”包括了中垂线。
现在考虑任取点,将其固定,于是作为关于的函数,三个函数中会自动失效一个,于是再次调用猜想可知,最大值点一定在一维边界上,也就是边或角上。
综合以上两点可知,一定有一个点在长方形的角上,或者在中垂线和长方形边的交点上,另一个点在边或角上。而注意距离中垂线和长方形边的交点最远的点一定在角上可知:一定有一个点在角上,另一个点在边或角上。证毕。

猜想的证明如下:
首先证明:对任何中的紧凸集,如果紧凸集)的并能覆盖的边界,那就能覆盖
考虑有一点没有被覆盖,将此点记为,考虑从分别最近的点,连线段,分别过作线段的垂直超平面。而显然,中是不可能用少于或等于个超平面围出一个有界区域的,于是可知这些超平面围不出一个有界区域,从而有一个方向能不经过到达的边界,故的边界没有被覆盖,矛盾。

于是考虑有个紧凸集覆盖了某平直边界紧凸集的所有维边界,根据上方命题可知,维部分全被覆盖。

  1. #include <bits/stdc++.h>
  2. using ul = std::uint32_t;
  3. using li = std::int32_t;
  4. using ull = std::uint64_t;
  5. using ll = std::int64_t;
  6. using llf = long double;
  7. class vec {
  8. public:
  9. llf x = 0;
  10. llf y = 0;
  11. vec()=default;
  12. vec(llf a, llf b): x(a), y(b) {}
  13. };
  14. vec operator+(const vec& a, const vec& b)
  15. {
  16. return vec(a.x + b.x, a.y + b.y);
  17. }
  18. vec operator-(const vec& a, const vec& b)
  19. {
  20. return vec(a.x - b.x, a.y - b.y);
  21. }
  22. llf operator*(const vec& a, const vec& b)
  23. {
  24. return a.x * b.x + a.y * b.y;
  25. }
  26. vec operator*(llf a, const vec& b)
  27. {
  28. return vec(a * b.x, a * b.y);
  29. }
  30. vec operator*(const vec& a, llf b)
  31. {
  32. return vec(a.x * b, a.y * b);
  33. }
  34. vec operator/(const vec& a, llf b)
  35. {
  36. return vec(a.x / b, a.y / b);
  37. }
  38. llf len2(const vec& a, const vec& b)
  39. {
  40. return (a - b) * (a - b);
  41. }
  42. llf len(const vec& a, const vec& b)
  43. {
  44. return std::sqrt((a - b) * (a - b));
  45. }
  46. vec p1, p2;
  47. llf dis(const vec& a, const vec& b)
  48. {
  49. return std::min(len(a, b), std::min(len(a, p1) + len(p2, b), len(a, p2) + len(p1, b)));
  50. }
  51. vec cs[5];
  52. vec rotate(const vec& a)
  53. {
  54. return vec(-a.y, a.x);
  55. }
  56. bool calc(llf a, llf b, llf c, llf& t1, llf& t2)
  57. {
  58. if (a < 1e-5 && a > -1e-5) {
  59. t1 = -c / b;
  60. t2 = -c / b;
  61. return true;
  62. }
  63. llf delta = b * b - llf(4) * a * c;
  64. if (delta < 0) {
  65. return false;
  66. }
  67. t1 = (-b - std::sqrt(delta)) / a * llf(0.5);
  68. t2 = (-b + std::sqrt(delta)) / a * llf(0.5);
  69. return true;
  70. }
  71. llf calc(const vec& start, vec& ans)
  72. {
  73. llf ret = 0;
  74. vec o, xdir, ydir;
  75. llf a, b;
  76. if (len2(p1, start) < len2(p2, start)) {
  77. a = len(start, p1) * llf(0.5);
  78. b = std::sqrt(len2(start, p2) - len2(start, p1)) * llf(0.5);
  79. o = (start + p2) * llf(0.5);
  80. xdir = (p2 - start) / len(p2, start);
  81. ydir = rotate(xdir);
  82. } else if (len2(p2, start) < len2(p1, start)) {
  83. a = len(start, p2) * llf(0.5);
  84. b = std::sqrt(len2(start, p1) - len2(start, p2)) * llf(0.5);
  85. o = (start + p1) * llf(0.5);
  86. xdir = (p1 - start) / len(p1, start);
  87. ydir = rotate(xdir);
  88. } else {
  89. for (ul i = 1; i <= 4; ++i) {
  90. llf tmp = dis(start, cs[i]);
  91. if (ret < tmp) {
  92. ans = cs[i];
  93. ret = tmp;
  94. }
  95. }
  96. return ret;
  97. }
  98. for (ul i = 1; i <= 4; ++i) {
  99. vec alpha = vec((cs[i - 1] - o) * xdir, (cs[i - 1] - o) * ydir);
  100. vec beta = vec((cs[i] - o) * xdir, (cs[i] - o) * ydir);
  101. llf tmp = dis(start, cs[i]);
  102. if (ret < tmp) {
  103. ans = cs[i];
  104. ret = tmp;
  105. }
  106. llf t1, t2;
  107. bool flag = calc(b * b * (alpha.x - beta.x) * (alpha.x - beta.x) - a * a * (alpha.y - beta.y) * (alpha.y - beta.y), 2 * (alpha.x * b * b * (beta.x - alpha.x) + a * a * alpha.y * (alpha.y - beta.y)), alpha.x * alpha.x * b * b - a * a * alpha.y * alpha.y - a * a * b * b, t1, t2);
  108. if (flag) {
  109. if (t1 >= 0 && t1 <= 1) {
  110. vec k = cs[i - 1] + t1 * (cs[i] - cs[i - 1]);
  111. llf tmp = dis(start, k);
  112. if (ret < tmp) {
  113. ans = k;
  114. ret = tmp;
  115. }
  116. }
  117. if (t2 >= 0 && t2 <= 1) {
  118. vec k = cs[i - 1] + t2 * (cs[i] - cs[i - 1]);
  119. llf tmp = dis(start, k);
  120. if (ret < tmp) {
  121. ans = k;
  122. ret = tmp;
  123. }
  124. }
  125. }
  126. }
  127. return ret;
  128. }
  129. ul T;
  130. int main()
  131. {
  132. std::scanf("%u", &T);
  133. for (ul Case = 1; Case <= T; ++Case) {
  134. ul a, b, x1, x2, y1, y2;
  135. std::scanf("%u%u%u%u%u%u", &a, &b, &x1, &y1, &x2, &y2);
  136. p1 = vec(x1, y1);
  137. p2 = vec(x2, y2);
  138. cs[1] = vec(0, 0);
  139. cs[2] = vec(a, 0);
  140. cs[3] = vec(a, b);
  141. cs[4] = vec(0, b);
  142. cs[0] = cs[4];
  143. llf ans = 0;
  144. vec out1, out2;
  145. for (ul i = 1; i <= 4; ++i) {
  146. llf tans;
  147. vec tout2;
  148. tans = calc(cs[i], tout2);
  149. if (tans > ans) {
  150. ans = tans;
  151. out1 = cs[i];
  152. out2 = tout2;
  153. }
  154. }
  155. std::printf("Case #%u:\n", Case);
  156. std::printf("%.20Lf %.20Lf\n%.20Lf %.20Lf\n", out1.x, out1.y, out2.x, out2.y);
  157. }
  158. return 0;
  159. }

J、Bob's Poor Math

直接看代码

  1. #include <bits/stdc++.h>
  2. using ul = std::uint32_t;
  3. using li = std::int32_t;
  4. using ull = std::uint64_t;
  5. using ll = std::int64_t;
  6. ul T;
  7. ul n, m;
  8. const ul maxn = 1e4;
  9. const ul maxm = 1e4;
  10. class node {
  11. public:
  12. ul son[10];
  13. ull sum = 0;
  14. node() {
  15. std::memset(son, 0, sizeof(son));
  16. }
  17. };
  18. ul tot;
  19. node tree[maxn * 10 + maxm * 10 + 2];
  20. ul stack[maxn * 10 + maxm * 10 + 2];
  21. ul remain;
  22. ul newnode()
  23. {
  24. ul tmp;
  25. if (remain) {
  26. tmp = stack[remain];
  27. --remain;
  28. } else {
  29. ++tot;
  30. tmp = tot;
  31. }
  32. tree[tmp] = node();
  33. return tmp;
  34. }
  35. void kill(ul& x)
  36. {
  37. ++remain;
  38. stack[remain] = x;
  39. x = 0;
  40. }
  41. ull plus(ull a, ull b)
  42. {
  43. ull c = 0;
  44. ull i = 1;
  45. while (a || b) {
  46. ull k = (a % 10 + b % 10) % 10;
  47. c += k * i;
  48. a /= 10;
  49. b /= 10;
  50. i *= 10;
  51. }
  52. return c;
  53. }
  54. void add(ull x, ul root)
  55. {
  56. static ul ins[10];
  57. ull xx = x;
  58. for (ul i = 0; i <= 9; ++i) {
  59. ins[i] = x % 10;
  60. x /= 10;
  61. }
  62. x = xx;
  63. ul curr = root;
  64. for (ul i = 9; ~i; --i) {
  65. if (!tree[curr].son[ins[i]]) {
  66. tree[curr].son[ins[i]] = newnode();
  67. }
  68. curr = tree[curr].son[ins[i]];
  69. tree[curr].sum = plus(tree[curr].sum, x);
  70. }
  71. }
  72. void shift(ul& root)
  73. {
  74. for (ul i = 0; i <= 9; ++i) {
  75. if (tree[root].son[i]) {
  76. tree[root].sum = plus(tree[root].sum, tree[tree[root].son[i]].sum);
  77. }
  78. }
  79. ul s = root;
  80. root = newnode();
  81. tree[root].son[0] = s;
  82. using pulul = std::pair<ul, ul>;
  83. static pulul stack[maxn * 10 + maxm * 10 + 2];
  84. ul tot = 0;
  85. ++tot;
  86. stack[tot] = pulul(s, 9);
  87. while (tot) {
  88. auto curr = stack[tot].first;
  89. auto index = stack[tot].second;
  90. --tot;
  91. tree[curr].sum /= 10;
  92. for (ul i = 0; i != 10; ++i) {
  93. if (tree[curr].son[i]) {
  94. if (index == 0) {
  95. kill(tree[curr].son[i]);
  96. } else {
  97. ++tot;
  98. stack[tot].first = tree[curr].son[i];
  99. stack[tot].second = index - 1;
  100. }
  101. }
  102. }
  103. }
  104. }
  105. ull query(ull x, ul root)
  106. {
  107. static ul ins[10];
  108. for (ul i = 0; i <= 9; ++i) {
  109. ins[i] = x % 10;
  110. x /= 10;
  111. }
  112. ul curr = root;
  113. ull ret2 = 0;
  114. for (ul i = 9; ~i; --i) {
  115. for (ul j = 9; ~j; --j) {
  116. ul t = j < ins[i] ? j + 10 - ins[i] : j - ins[i];
  117. if (tree[curr].son[t]) {
  118. ret2 *= 10;
  119. ret2 += j;
  120. curr = tree[curr].son[t];
  121. break;
  122. }
  123. }
  124. }
  125. return ret2;
  126. }
  127. ull sum(ull l, ull r, ul nid, ull nl, ull nr)
  128. {
  129. if (l <= nl && r >= nr) {
  130. return tree[nid].sum;
  131. }
  132. ull ret = 0;
  133. ull part = (nr - nl + 1) / 10;
  134. for (ull i = 0, ml = nl, mr = nl + part - 1; i <= 9; ++i, ml += part, mr += part) {
  135. if (!tree[nid].son[i]) {
  136. continue;
  137. }
  138. if (l <= mr && r >= ml) {
  139. ret = plus(ret, sum(l, r, tree[nid].son[i], ml, mr));
  140. }
  141. }
  142. return ret;
  143. }
  144. char str[100];
  145. int main()
  146. {
  147. std::scanf("%u", &T);
  148. for (ul Case = 1; Case <= T; ++Case) {
  149. std::printf("Case #%u:\n", Case);
  150. std::scanf("%u%u", &n, &m);
  151. tot = 0;
  152. remain = 0;
  153. ul root = newnode();
  154. for (ul i = 1; i <= n; ++i) {
  155. ull a;
  156. std::scanf("%llu", &a);
  157. add(a, root);
  158. }
  159. for (ul i = 1; i <= m; ++i) {
  160. std::scanf("%s", str + 1);
  161. if (std::strcmp(str + 1, "Add") == 0) {
  162. ull a;
  163. std::scanf("%llu", &a);
  164. add(a, root);
  165. } else if (std::strcmp(str + 1, "Query") == 0) {
  166. ull a;
  167. std::scanf("%llu", &a);
  168. std::printf("%llu\n", query(a, root));
  169. } else if (std::strcmp(str + 1, "Shift") == 0) {
  170. shift(root);
  171. } else if (std::strcmp(str + 1, "Sum") == 0) {
  172. ull l, r;
  173. std::scanf("%llu%llu", &l, &r);
  174. std::printf("%llu\n", sum(l, r, root, 0, 9999999999ull));
  175. }
  176. }
  177. }
  178. return 0;
  179. }

K、Color Graph

简单题

  1. #include <bits/stdc++.h>
  2. using ul = std::uint32_t;
  3. using li = std::int32_t;
  4. using ull = std::uint64_t;
  5. using ll = std::int64_t;
  6. ul T;
  7. ul n, m;
  8. const ul maxn = 16;
  9. ul g(ul x)
  10. {
  11. return x ^ x >> 1;
  12. }
  13. ul edges[maxn + 1];
  14. int main()
  15. {
  16. std::scanf("%u", &T);
  17. for (ul Case = 1; Case <= T; ++Case) {
  18. std::scanf("%u%u", &n, &m);
  19. for (ul i = 1; i <= n; ++i) {
  20. edges[i] = 0;
  21. }
  22. for (ul i = 1; i <= m; ++i) {
  23. ul u, v;
  24. std::scanf("%u%u", &u, &v);
  25. edges[u] |= 1 << v - 1;
  26. edges[v] |= 1 << u - 1;
  27. }
  28. ul ans = 0;
  29. ul tmp = 0;
  30. for (ul i = 1; i != (1 << n); ++i) {
  31. ul curr = g(i);
  32. ul prev = g(i - 1);
  33. ul id = __builtin_ctz(curr ^ prev) + 1;
  34. tmp -= __builtin_popcount(edges[id] & ((prev >> id - 1 & 1) ? ~prev : prev));
  35. tmp += __builtin_popcount(edges[id] & ((curr >> id - 1 & 1) ? ~curr : curr));
  36. ans = std::max(tmp, ans);
  37. }
  38. std::printf("Case #%u: %u\n", Case, ans);
  39. }
  40. return 0;
  41. }

L、

M、Blood Pressure Game

狄克斯特拉费用流,注意由于是稠密图,不要用堆优化。

  1. #include <bits/stdc++.h>
  2. using ul = std::uint32_t;
  3. using li = std::int32_t;
  4. using ull = std::uint64_t;
  5. using ll = std::int64_t;
  6. const ul maxn = 600;
  7. const ul maxm = maxn + 1;
  8. const li liinf = (li(1) << 31) - 1;
  9. const ll llinf = (ll(1) << 63) - 1;
  10. class mcmf {
  11. public:
  12. class edge_t {
  13. public:
  14. ul to = 0;
  15. li cap = 0;
  16. li cost = 0;
  17. edge_t()=default;
  18. edge_t(ul to, li cap, li cost): to(to), cap(cap), cost(cost) {}
  19. };
  20. class node_t {
  21. public:
  22. ll pi;
  23. ll sigma;
  24. ul p;
  25. li a;
  26. ul vis;
  27. std::vector<ul> edge;
  28. };
  29. edge_t edge[maxm + maxm + maxm * maxm << 1];
  30. node_t node[maxm + maxm + 2];
  31. std::vector<ul> stack;
  32. bool instack[maxm + maxm + maxm * maxm << 1];
  33. std::queue<ul> queue;
  34. ul tim = 0;
  35. ul n, m;
  36. void init(ul n) {
  37. this->n = n;
  38. for (ul i = 0; i != n; ++i) {
  39. node[i].edge.resize(0);
  40. node[i].pi = 0;
  41. }
  42. std::memset(instack, false, sizeof(bool) * n);
  43. stack.resize(0);
  44. m = 0;
  45. }
  46. void addedge(ul from, ul to, li cap, li cost) {
  47. edge[m] = edge_t(to, cap, cost);
  48. ++m;
  49. edge[m] = edge_t(from, 0, -cost);
  50. ++m;
  51. node[from].edge.push_back(m - 2);
  52. node[to].edge.push_back(m - 1);
  53. }
  54. bool dikstra(ul s, ul t, li& flow, ll& cost) {
  55. for (ul i = 0; i != n; ++i) {
  56. node[i].sigma = llinf;
  57. }
  58. node[s].sigma = 0;
  59. stack.push_back(s);
  60. instack[s] = true;
  61. while (stack.size()) {
  62. ul small = 0;
  63. for (ul i = 0; i != stack.size(); ++i) {
  64. if (node[stack[i]].sigma < node[stack[small]].sigma) {
  65. small = i;
  66. }
  67. }
  68. std::swap(stack[small], stack.back());
  69. ul curr = stack.back();
  70. stack.pop_back();
  71. instack[curr] = false;
  72. for (ul i : node[curr].edge) {
  73. edge_t& e = edge[i];
  74. if (e.cap > 0 && node[e.to].sigma > node[curr].sigma + e.cost + node[curr].pi - node[e.to].pi) {
  75. node[e.to].sigma = node[curr].sigma + e.cost + node[curr].pi - node[e.to].pi;
  76. if (!instack[e.to]) {
  77. stack.push_back(e.to);
  78. instack[e.to] = true;
  79. }
  80. }
  81. }
  82. }
  83. if (node[t].sigma == llinf) {
  84. return false;
  85. }
  86. while (queue.size()) {
  87. queue.pop();
  88. }
  89. ++tim;
  90. node[s].p = -1;
  91. node[s].a = liinf;
  92. queue.push(s);
  93. node[s].vis = tim;
  94. while (queue.size()) {
  95. ul curr = queue.front();
  96. queue.pop();
  97. for (ul i : node[curr].edge) {
  98. edge_t& e = edge[i];
  99. ul nex = e.to;
  100. if (e.cap > 0 && node[nex].vis != tim && node[nex].sigma == node[curr].sigma + e.cost + node[curr].pi - node[nex].pi) {
  101. node[nex].p = i;
  102. node[nex].a = std::min(node[curr].a, e.cap);
  103. node[nex].vis = tim;
  104. queue.push(nex);
  105. }
  106. }
  107. }
  108. flow += node[t].a;
  109. cost += ll(node[t].sigma + node[t].pi - node[s].pi) * node[t].a;
  110. ul u = t;
  111. while (u != s) {
  112. edge[node[u].p].cap -= node[t].a;
  113. edge[node[u].p ^ 1].cap += node[t].a;
  114. u = edge[node[u].p ^ 1].to;
  115. }
  116. for (ul i = 0; i != n; ++i) {
  117. node[i].pi = node[i].sigma == llinf ? llinf : node[i].pi + node[i].sigma;
  118. }
  119. return true;
  120. }
  121. ll mincost(ul s, ul t) {
  122. li flow = 0;
  123. ll cost = 0;
  124. while (dikstra(s, t, flow, cost));
  125. return cost;
  126. }
  127. };
  128. mcmf graph;
  129. ul T;
  130. ul n, m;
  131. ll a[maxn + 1];
  132. ll b[maxm + 1];
  133. int main()
  134. {
  135. std::scanf("%u", &T);
  136. for (ul Case = 1; Case <= T; ++Case) {
  137. std::scanf("%u%u", &n, &m);
  138. for (ul i = 1; i <= n; ++i) {
  139. std::scanf("%lld", &a[i]);
  140. }
  141. for (ul i = 1; i <= m; ++i) {
  142. std::scanf("%lld", &b[i]);
  143. }
  144. ll ans = 0;
  145. for (ul i = 2; i <= n; ++i) {
  146. ans += std::max(a[i], a[i - 1]) - std::min(a[i], a[i - 1]);
  147. }
  148. graph.init(2 + n + 1 + m);
  149. for (ul i = 1; i <= n + 1; ++i) {
  150. graph.addedge(0, i, 1, 0);
  151. }
  152. for (ul j = n + 1 + 1; j <= n + 1 + m; ++j) {
  153. graph.addedge(j, n + 1 + m + 1, 1, 0);
  154. }
  155. for (ul i = 1; i <= n + 1; ++i) {
  156. for (ul j = 1; j <= m; ++j) {
  157. ll alpha = 0;
  158. ll beta = 0;
  159. if (i != 1) {
  160. alpha += std::max(b[j], a[i - 1]) - std::min(b[j], a[i - 1]);
  161. }
  162. if (i != n + 1) {
  163. alpha += std::max(b[j], a[i]) - std::min(b[j], a[i]);
  164. }
  165. if (i != 1 && i != n + 1) {
  166. beta = std::max(a[i], a[i - 1]) - std::min(a[i], a[i - 1]);
  167. }
  168. graph.addedge(i, n + 1 + j, 1, beta - alpha);
  169. }
  170. }
  171. std::printf("Case #%u:\n", Case);
  172. li flow = 0;
  173. ll cost = 0;
  174. for (ul i = 1; i <= m; ++i) {
  175. if (i != 1) {
  176. std::putchar(' ');
  177. }
  178. graph.dikstra(0, n + 1 + m + 1, flow, cost);
  179. std::printf("%lld", ans - cost);
  180. }
  181. std::putchar('\n');
  182. bool flag = false;
  183. for (ul i = 1; i <= n + 1; ++i) {
  184. for (ul eid : graph.node[i].edge) {
  185. const auto& e = graph.edge[eid];
  186. if (!e.cap && e.to >= n + 1 + 1) {
  187. ul j = e.to - n - 1;
  188. if (flag) {
  189. std::putchar(' ');
  190. }
  191. std::printf("%lld", b[j]);
  192. flag = true;
  193. break;
  194. }
  195. }
  196. if (i != n + 1) {
  197. if (flag) {
  198. std::putchar(' ');
  199. }
  200. std::printf("%lld", a[i]);
  201. flag = true;
  202. }
  203. }
  204. std::putchar('\n');
  205. }
  206. return 0;
  207. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注