[关闭]
@qq290637843 2020-10-27T12:33:40.000000Z 字数 40555 阅读 431

2020杭电第九场

A、Tree 6867

简单题。

  1. #include <bits/stdc++.h>
  2. using ul = std::uint32_t;
  3. using ull = std::uint64_t;
  4. using li = std::int32_t;
  5. using ll = std::int64_t;
  6. ul T;
  7. const ul maxn = 5e5;
  8. ul n;
  9. ul p[maxn + 1];
  10. ul sz[maxn + 1];
  11. ull ans[maxn + 1];
  12. ull mx;
  13. ull out;
  14. int main()
  15. {
  16. std::scanf("%u", &T);
  17. for (ul Case = 1; Case <= T; ++Case) {
  18. std::scanf("%u", &n);
  19. sz[1] = 1;
  20. for (ul i = 2; i <= n; ++i) {
  21. std::scanf("%u", &p[i]);
  22. sz[i] = 1;
  23. }
  24. ans[1] = 0;
  25. out = 0;
  26. for (ul i = n; i >= 2; --i) {
  27. sz[p[i]] += sz[i];
  28. ans[i] = n - sz[i];
  29. out += sz[i];
  30. }
  31. out += sz[1];
  32. mx = 0;
  33. for (ul i = 2; i <= n; ++i) {
  34. ans[i] += ans[p[i]];
  35. mx = std::max(mx, ans[i]);
  36. }
  37. std::printf("%llu\n", out + mx);
  38. }
  39. return 0;
  40. }

B、Absolute Math 6868

题意:,求


,于是

关于此递推式的时间复杂度,首先,肯定是关于不降的(注意,这句话成立的前提是不针对使用记忆化,因为这样可能导致不同的时候也相同,但在更小的,却又不相同了,所以用于计算时间复杂度的程序必须要把记忆化改为针对的。然而实际上,如果只是对记忆化,那就根本没必要记忆化,因为实际上根本不可能重复对的调用),所以直接取,然后将全部枚举,可知实际计算步数(指对的调用次数)小于等于,也就是时的值,故总时间

不使用记忆化的版本:

  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. const ul maxm = 1e7;
  20. const ul maxn = 1e7;
  21. ul f[maxm + 1];
  22. ul sf[maxm + 1];
  23. std::vector<ul> prime;
  24. bool notprime[maxn + 1];
  25. ul low[maxn + 1];
  26. ul n, m;
  27. ul sz[256];
  28. ul r[256];
  29. ul p[8];
  30. ul Case;
  31. ul pow2[9];
  32. ul pow2inv[9];
  33. ul getans(ul s, ull t)
  34. {
  35. if (m < t) {
  36. return 0;
  37. }
  38. if (s == 0) {
  39. return sf[m / t];
  40. }
  41. ul ans = 0;
  42. for (ul k = s; ; k = k - 1 & s) {
  43. if (sz[k] & 1) {
  44. ans = minus(ans, mul(getans(k, t * r[k]), pow2inv[sz[k]]));
  45. } else {
  46. ans = plus(ans, mul(getans(k, t * r[k]), pow2inv[sz[k]]));
  47. }
  48. if (k == 0) {
  49. break;
  50. }
  51. }
  52. ans = mul(ans, pow2[sz[s]]);
  53. return ans;
  54. }
  55. ul T;
  56. int main()
  57. {
  58. for (ul i = 1; i != 256; ++i) {
  59. sz[i] = sz[i >> 1] + (i & 1);
  60. }
  61. pow2[0] = pow2inv[0] = 1;
  62. for (ul i = 1; i <= 8; ++i) {
  63. pow2[i] = pow2[i - 1] * 2;
  64. pow2inv[i] = (pow2inv[i - 1] & 1) ? (pow2inv[i - 1] + mod >> 1) : (pow2inv[i - 1] >> 1);
  65. }
  66. f[1] = 1;
  67. sf[1] = 1;
  68. for (ul i = 2; i <= maxn; ++i) {
  69. if (!notprime[i]) {
  70. prime.push_back(i);
  71. f[i] = 2;
  72. low[i] = i;
  73. }
  74. for (ul p : prime) {
  75. if (i * p > maxn) {
  76. break;
  77. }
  78. notprime[i * p] = true;
  79. low[i * p] = p;
  80. if (i % p == 0) {
  81. f[i * p] = f[i];
  82. break;
  83. } else {
  84. f[i * p] = 2 * f[i];
  85. }
  86. }
  87. sf[i] = plus(sf[i - 1], f[i]);
  88. }
  89. std::scanf("%u", &T);
  90. for (Case = 1; Case <= T; ++Case) {
  91. std::scanf("%u%u", &n, &m);
  92. ul tn = 1;
  93. ul sn = 0;
  94. while (n != 1) {
  95. p[sn] = low[n];
  96. tn *= p[sn];
  97. while (low[n] == p[sn]) {
  98. n /= p[sn];
  99. }
  100. ++sn;
  101. }
  102. n = tn;
  103. r[0] = 1;
  104. for (ul i = 1; i != (1 << sn); ++i) {
  105. r[i] = r[i & ~(1 << 31 - __builtin_clz(i))] * p[31 - __builtin_clz(i)];
  106. }
  107. std::printf("%u\n", getans((1 << sn) - 1, 1));
  108. }
  109. return 0;
  110. }

使用记忆化的版本:

  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. const ul maxm = 1e7;
  20. const ul maxn = 1e7;
  21. ul f[maxm + 1];
  22. ul sf[maxm + 1];
  23. std::vector<ul> prime;
  24. bool notprime[maxn + 1];
  25. ul low[maxn + 1];
  26. ul n, m, sq;
  27. ul sz[256];
  28. ul r[256];
  29. ul p[8];
  30. ul Case;
  31. ul ans[7000][256];
  32. ul already[7000][256];
  33. ul pow2[9];
  34. ul pow2inv[9];
  35. ul getans(ul mm, ul s)
  36. {
  37. ul id;
  38. if (mm <= sq) {
  39. id = mm;
  40. } else {
  41. id = m / mm + sq + 1;
  42. }
  43. if (already[id][s] == Case) {
  44. return ans[id][s];
  45. }
  46. already[id][s] = Case;
  47. if (mm == 0) {
  48. return ans[id][s] = 0;
  49. }
  50. if (s == 0) {
  51. return ans[id][s] = sf[mm];
  52. }
  53. ans[id][s] = 0;
  54. for (ul k = s; ; k = k - 1 & s) {
  55. if (sz[k] & 1) {
  56. ans[id][s] = minus(ans[id][s], mul(getans(mm / r[k], k), pow2inv[sz[k]]));
  57. } else {
  58. ans[id][s] = plus(ans[id][s], mul(getans(mm / r[k], k), pow2inv[sz[k]]));
  59. }
  60. if (k == 0) {
  61. break;
  62. }
  63. }
  64. ans[id][s] = mul(ans[id][s], pow2[sz[s]]);
  65. return ans[id][s];
  66. }
  67. ul T;
  68. int main()
  69. {
  70. for (ul i = 1; i != 256; ++i) {
  71. sz[i] = sz[i >> 1] + (i & 1);
  72. }
  73. pow2[0] = pow2inv[0] = 1;
  74. for (ul i = 1; i <= 8; ++i) {
  75. pow2[i] = pow2[i - 1] * 2;
  76. pow2inv[i] = (pow2inv[i - 1] & 1) ? (pow2inv[i - 1] + mod >> 1) : (pow2inv[i - 1] >> 1);
  77. }
  78. f[1] = 1;
  79. sf[1] = 1;
  80. for (ul i = 2; i <= maxn; ++i) {
  81. if (!notprime[i]) {
  82. prime.push_back(i);
  83. f[i] = 2;
  84. low[i] = i;
  85. }
  86. for (ul p : prime) {
  87. if (i * p > maxn) {
  88. break;
  89. }
  90. notprime[i * p] = true;
  91. low[i * p] = p;
  92. if (i % p == 0) {
  93. f[i * p] = f[i];
  94. break;
  95. } else {
  96. f[i * p] = 2 * f[i];
  97. }
  98. }
  99. sf[i] = plus(sf[i - 1], f[i]);
  100. }
  101. std::scanf("%u", &T);
  102. for (Case = 1; Case <= T; ++Case) {
  103. std::scanf("%u%u", &n, &m);
  104. ul tn = 1;
  105. ul sn = 0;
  106. while (n != 1) {
  107. p[sn] = low[n];
  108. tn *= p[sn];
  109. while (low[n] == p[sn]) {
  110. n /= p[sn];
  111. }
  112. ++sn;
  113. }
  114. n = tn;
  115. r[0] = 1;
  116. for (ul i = 1; i != (1 << sn); ++i) {
  117. r[i] = r[i & ~(1 << 31 - __builtin_clz(i))] * p[31 - __builtin_clz(i)];
  118. }
  119. sq = std::sqrt(m);
  120. std::printf("%u\n", getans(m, (1 << sn) - 1));
  121. }
  122. return 0;
  123. }

C、Slime and Stones 6869

先给出结论,然后证明:一个状态是必败态,当且仅当

今后将记为记为

先说明的一些性质:

,亦可知,亦可知,


③因为均为正无理数,且,故互不相交,且并是。(这一点的证明,见https://www.zybuluo.com/qq290637843/note/1746147

现在任务就是要证明两点:①必败态不能到达必败态;②必胜态能到达必败态。

1、必败不能到达必败
  1.1、同属于一类:
  不妨设属于第一类,并设,现在要证明

关于第一个命题,由可知
关于第二个命题,由可知

  1.2、不属于同一类:
  不妨设属于第一类,属于第二类,于是不同时为,现在要证明
第一和第二个命题实际都是要证明
的性质③能直接得出这一点。而第三个命题只需要注意到

  
2、必胜能达到必败
  考虑必胜态,则存在为必败态(来自性质③):
  2.1、均为一类点时:于是
于是恰好有一个为真。
  2.2、均为二类点时:于是
于是恰好有一个为真。
  2.3、为二类点且为一类点时:于是
于是至少有一个为真。
  2.4、为一类点且为二类点时:于是
,只需要考虑的情况。由于性质②,可知,既存在必败态满足,又存在(可能是不同的)必败态满足。如果,则第一种就是可达到的,如果,则第二种就是可达到的。
  
  顺带的连分数形式为,可以简化代码,这一点请自己证明。
  

  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 lll = __int128;
  7. ul a, b, k;
  8. lll x, y;
  9. ul T;
  10. ull ma, mb;
  11. ull mas, mbt;
  12. lll upper(lll x, lll y)
  13. {
  14. return (x + y - 1) / y;
  15. }
  16. int main()
  17. {
  18. std::scanf("%u", &T);
  19. for (ul Case = 1; Case <= T; ++Case) {
  20. std::scanf("%u%u%u", &a, &b, &k);
  21. if (a > b) {
  22. std::swap(a, b);
  23. }
  24. ma = a, mb = upper(b, k + 2);
  25. mas = a, mbt = mb * lll(k + 2);
  26. x = 1, y = k + 1;
  27. while (true) {
  28. ull tma = upper(lll(a) * y, x + y);
  29. ull tmb = upper(lll(b) * y, x + y * lll(k + 2));
  30. ull tmas = lll(tma) * (x + y) / y;
  31. ull tmbt = lll(tmb) * (x + y * lll(k + 2)) / y;
  32. if (tma == ma && tmb == mb && tmas == mas && tmbt == mbt) {
  33. break;
  34. }
  35. ma = tma;
  36. mb = tmb;
  37. mas = tmas;
  38. mbt = tmbt;
  39. x += y * lll(k + 1);
  40. std::swap(x, y);
  41. }
  42. std::printf(ma == mb && mas == a && mbt == b ? "0\n" : "1\n");
  43. }
  44. return 0;
  45. }

D、Product 6870

不知道为什么下面的代码就能过,过于肏你妈的调参题。代码中是指将小于等于的非负整数被拆为大于等于的质数的和有多少种方案,两个方案等价是指每一个质数出现的次数相同,只取质数,然后借助于用gett()函数实现等概率从所有拆解方案中选一个。

  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. ull p, a;
  8. std::mt19937_64 rnd;
  9. std::vector<ul> ans;
  10. bool notprime[2501];
  11. std::vector<ul> prime;
  12. void exgcd(ll a, ll b, ll& x, ll& y)
  13. {
  14. if (b) {
  15. exgcd(b, a % b, y, x);
  16. y -= a / b * x;
  17. } else {
  18. x = 1;
  19. y = 0;
  20. }
  21. }
  22. ull inverse(ull a)
  23. {
  24. ll x, y;
  25. exgcd(a, p, x, y);
  26. return x < 0 ? x + ll(p) : x;
  27. }
  28. using llf = long double;
  29. ll mul(ll a, ll b, ll p)
  30. {
  31. ll t = a * b - ll(llf(a) * llf(b) / llf(p)) * p;
  32. return t < 0 ? t + p : (t < p ? t : t - p);
  33. }
  34. const ul b = 256;
  35. ull f[b + 1][b + b + 1];
  36. ull inv[b + 1][b + 1];
  37. ul vsz = 0;
  38. ul tv[ul(1e8)];
  39. ul sz = 0;
  40. ull ts[ul(1e6)];
  41. ul start[ul(1e6)];
  42. ul next[2501];
  43. void gett()
  44. {
  45. ts[sz] = 1;
  46. start[sz] = vsz;
  47. auto& t = ts[sz];
  48. ++sz;
  49. ul x = b, y = 2;
  50. ull r = rnd() % f[x][y];
  51. ul prev = 2;
  52. ul cnt = 0;
  53. while (x >= y && r) {
  54. if (r < f[x][next[y]]) {
  55. y = next[y];
  56. } else {
  57. r -= f[x][next[y]];
  58. x -= y;
  59. tv[vsz] = y;
  60. ++vsz;
  61. if (y != prev) {
  62. t = mul(t, inv[prev][cnt], p);
  63. prev = y;
  64. cnt = 0;
  65. }
  66. ++cnt;
  67. }
  68. }
  69. t = mul(t, inv[prev][cnt], p);
  70. }
  71. int main()
  72. {
  73. rnd.seed(std::time(0));
  74. std::scanf("%llu", &p);
  75. ul prev = 1;
  76. for (ul i = 2; i <= 2500; ++i) {
  77. if (!notprime[i]) {
  78. prime.push_back(i);
  79. next[prev] = i;
  80. prev = i;
  81. if (i <= b) {
  82. for (ull t = 0, q = 1; i * t <= b; ++t, q = mul(i, q, p)) {
  83. inv[i][t] = inverse(q);
  84. }
  85. }
  86. }
  87. for (ul p : prime) {
  88. if (i * p > 2500) {
  89. break;
  90. }
  91. notprime[i * p] = true;
  92. if (i % p == 0) {
  93. break;
  94. }
  95. }
  96. }
  97. for (ul y = b + b; y >= 2; --y) {
  98. if (notprime[y]) {
  99. continue;
  100. }
  101. for (ul x = 0; x <= b; ++x) {
  102. if (x < y) {
  103. f[x][y] = 1;
  104. continue;
  105. }
  106. if (x >= y) {
  107. f[x][y] += f[x - y][y];
  108. }
  109. if (next[y] <= b + b) {
  110. f[x][y] += f[x][next[y]];
  111. }
  112. }
  113. }
  114. std::scanf("%u", &T);
  115. for (ul Case = 1; Case <= T; ++Case) {
  116. std::scanf("%llu", &a);
  117. ul i;
  118. for (i = 0; ; ++i) {
  119. if (i == sz) {
  120. gett();
  121. }
  122. ull t = ts[i];
  123. ul sum = 0;
  124. ull v = mul(t, a, p);
  125. ans.resize(0);
  126. for (ul p : prime) {
  127. if (p > 40 && v > 1e15 || p > 120 && v > 1e13) {
  128. break;
  129. }
  130. if (sum + p > 2500 - b) {
  131. break;
  132. }
  133. while (v % p == 0) {
  134. v /= p;
  135. ans.push_back(p);
  136. sum += p;
  137. }
  138. if (sum > 2500 - b || v == 1) {
  139. break;
  140. }
  141. }
  142. if (v == 1 && sum + b <= 2500) {
  143. break;
  144. }
  145. }
  146. for (ul k = start[i]; k != start[i + 1] && k != vsz; ++k) {
  147. ans.push_back(tv[k]);
  148. }
  149. std::printf("%u", ul(ans.size()));
  150. for (auto t : ans) {
  151. std::printf(" %u", t);
  152. }
  153. std::putchar('\n');
  154. }
  155. return 0;
  156. }

E、Resistance 6871

圈上边的贡献如下,这是一个大小为的圈。


注意,这个代码在本地跑可能会爆栈。

  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. const ul maxn = 2e5;
  8. const ul maxm = 4e5;
  9. ul n, m;
  10. class edge_t {
  11. public:
  12. ul u = 0;
  13. ul v = 0;
  14. ul unext = 0;
  15. ul vnext = 0;
  16. ul& next(ul x) {
  17. return x == u ? unext : vnext;
  18. }
  19. ul to(ul x) const {
  20. return x ^ u ^ v;
  21. }
  22. ul next(ul x) const {
  23. return x == u ? unext : vnext;
  24. }
  25. };
  26. edge_t edge[maxm + 1];
  27. ul head[maxn + 1];
  28. ul sz[maxn + 1];
  29. ul al[maxn + 1];
  30. ul ale[maxm + 1];
  31. ul back[maxn + 1];
  32. ul p[maxn + 1];
  33. bool incircle[maxn + 1];
  34. void search(ul x)
  35. {
  36. al[x] = true;
  37. sz[x] = 1;
  38. for (ul eid = head[x]; eid; eid = edge[eid].next(x)) {
  39. if (ale[eid]) {
  40. continue;
  41. }
  42. ale[eid] = true;
  43. ul y = edge[eid].to(x);
  44. if (al[y]) {
  45. back[x] = y;
  46. for (ul i = x; i != y; i = p[i]) {
  47. incircle[i] = true;
  48. }
  49. continue;
  50. }
  51. p[y] = x;
  52. search(y);
  53. sz[x] += sz[y];
  54. }
  55. }
  56. const ul mod = 1e9 + 7;
  57. ul plus(ul a, ul b)
  58. {
  59. return a + b < mod ? a + b : a + b - mod;
  60. }
  61. ul minus(ul a, ul b)
  62. {
  63. return a < b ? a + mod - b : a - b;
  64. }
  65. ul mul(ul a, ul b)
  66. {
  67. return ull(a) * ull(b) % mod;
  68. }
  69. void exgcd(li a, li b, li& x, li& y)
  70. {
  71. if (b) {
  72. exgcd(b, a % b, y, x);
  73. y -= a / b * x;
  74. } else {
  75. x = 1;
  76. y = 0;
  77. }
  78. }
  79. ul inverse(ul a)
  80. {
  81. li x, y;
  82. exgcd(a, mod, x, y);
  83. return x < 0 ? x + li(mod) : x;
  84. }
  85. ul c[maxn + 1];
  86. ul sumc[maxn + 1];
  87. ul sumjc[maxn + 1];
  88. ul sumjjc[maxn + 1];
  89. int main()
  90. {
  91. std::scanf("%u", &T);
  92. for (ul Case = 1; Case <= T; ++Case) {
  93. std::scanf("%u%u", &n, &m);
  94. for (ul i = 1; i <= n; ++i) {
  95. head[i] = 0;
  96. al[i] = false;
  97. incircle[i] = false;
  98. back[i] = 0;
  99. }
  100. for (ul i = 1; i <= m; ++i) {
  101. ale[i] = false;
  102. std::scanf("%u%u", &edge[i].u, &edge[i].v);
  103. for (ul x : {edge[i].u, edge[i].v}) {
  104. edge[i].next(x) = head[x];
  105. head[x] = i;
  106. }
  107. }
  108. search(1);
  109. ul ans = 0;
  110. for (ul i = 2; i <= n; ++i) {
  111. if (!incircle[i]) {
  112. ans = plus(ans, mul(sz[i], n - sz[i]));
  113. }
  114. }
  115. for (ul t = 2; t <= n; ++t) {
  116. if (back[t]) {
  117. ul k = 0;
  118. for (ul i = 1, s = t; ; ++i, s = p[s]) {
  119. c[i] = sz[s];
  120. if (s == back[t]) {
  121. k = i;
  122. break;
  123. }
  124. }
  125. for (ul i = k; i >= 2; --i) {
  126. c[i] -= c[i - 1];
  127. }
  128. c[k] += n - sz[back[t]];
  129. sumc[k] = c[k];
  130. sumjc[k] = mul(k, c[k]);
  131. sumjjc[k] = mul(mul(k, k), c[k]);
  132. for (ul j = k - 1; j >= 1; --j) {
  133. sumc[j] = plus(c[j], sumc[j + 1]);
  134. sumjc[j] = plus(mul(j, c[j]), sumjc[j + 1]);
  135. sumjjc[j] = plus(mul(mul(j, j), c[j]), sumjjc[j + 1]);
  136. }
  137. ul invk = inverse(k);
  138. for (ul i = 1; i <= k; ++i) {
  139. ans = plus(ans, mul(c[i], sumjc[i]));
  140. ans = minus(ans, mul(mul(i, c[i]), sumc[i]));
  141. ans = minus(ans, mul(invk, mul(c[i], sumjjc[i])));
  142. ans = minus(ans, mul(invk, mul(mul(mul(i, i), c[i]), sumc[i])));
  143. ans = plus(ans, mul(mul(2, invk), mul(mul(i, c[i]), sumjc[i])));
  144. }
  145. }
  146. }
  147. std::printf("%u\n", ans);
  148. }
  149. return 0;
  150. }

F、Skyscrapers 6872

先重复清洗每个格子可能填的数,直到没有变化为止,接着,舞蹈链搜索。

  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 = 8;
  7. const ul facmaxn = 40320;
  8. ul n;
  9. ul hash[maxn + 1];
  10. std::vector<ul> able[maxn + 1][maxn + 1][maxn + 1];
  11. bool ablev1[maxn + 1][maxn + 1][maxn + 1];
  12. bool ablev2[maxn + 1][maxn + 1][maxn + 1];
  13. std::vector<ul> ablev3[maxn + 1];
  14. std::vector<ul> ablev4[maxn + 1];
  15. std::vector<ul> tmp;
  16. ul idtoper[maxn + 1][facmaxn + 1][maxn + 1];
  17. ul per[maxn + 1];
  18. ul T;
  19. ul t[maxn + 1], b[maxn + 1], l[maxn + 1], r[maxn + 1];
  20. class dlxnode {
  21. public:
  22. ul left = 0;
  23. ul right = 0;
  24. ul up = 0;
  25. ul down = 0;
  26. ul col = 0;
  27. ul row = 0;
  28. dlxnode()=default;
  29. };
  30. ul dlxsz = 0;
  31. dlxnode dlx[ul(1e6)];
  32. const ul head = 1;
  33. std::vector<ul> ans;
  34. std::vector<ul> currcol;
  35. std::vector<ul> delv;
  36. void init() {
  37. dlx[head].left = head;
  38. dlx[head].right = head;
  39. dlxsz = 1;
  40. delv.resize(0);
  41. currcol.resize(0);
  42. ans.resize(0);
  43. }
  44. ul c[maxn + maxn + maxn * maxn * 5 + maxn * maxn + maxn * maxn + maxn * maxn + maxn * maxn * 5 + maxn * maxn * 5 + maxn * maxn + maxn * maxn + maxn * maxn * maxn * 2 + 1];
  45. const ul sz = 1 << 12;
  46. ul cnt[sz << 1];
  47. ul mnid[sz << 1];
  48. void change(ul pos, ul v)
  49. {
  50. for (cnt[pos |= sz] += v, pos >>= 1; pos; pos >>= 1) {
  51. cnt[pos] = std::min(cnt[pos << 1], cnt[pos << 1 | 1]);
  52. mnid[pos] = cnt[pos << 1] < cnt[pos << 1 | 1] ? mnid[pos << 1] : mnid[pos << 1 | 1];
  53. }
  54. }
  55. void pushc(ul col)
  56. {
  57. ++dlxsz;
  58. dlx[dlxsz].left = dlx[head].left;
  59. dlx[dlxsz].right = head;
  60. dlx[head].left = dlxsz;
  61. dlx[dlx[dlxsz].left].right = dlxsz;
  62. dlx[dlxsz].up = dlxsz;
  63. dlx[dlxsz].down = dlxsz;
  64. dlx[dlxsz].col = col;
  65. dlx[dlxsz].row = 0;
  66. c[col] = dlxsz;
  67. }
  68. ul front;
  69. void push(ul row, ul col)
  70. {
  71. change(col, 1);
  72. ++dlxsz;
  73. if (!front) {
  74. dlx[dlxsz].left = dlxsz;
  75. dlx[dlxsz].right = dlxsz;
  76. front = dlxsz;
  77. } else {
  78. dlx[dlxsz].left = dlx[front].left;
  79. dlx[dlxsz].right = front;
  80. dlx[front].left = dlxsz;
  81. dlx[dlx[dlxsz].left].right = dlxsz;
  82. }
  83. dlx[dlxsz].up = dlx[c[col]].up;
  84. dlx[dlxsz].down = c[col];
  85. dlx[c[col]].up = dlxsz;
  86. dlx[dlx[dlxsz].up].down = dlxsz;
  87. dlx[dlxsz].row = row;
  88. dlx[dlxsz].col = col;
  89. }
  90. void del(ul x)
  91. {
  92. change(dlx[x].col, ~ul(0));
  93. dlx[dlx[x].right].left = dlx[x].left;
  94. dlx[dlx[x].left].right = dlx[x].right;
  95. dlx[dlx[x].up].down = dlx[x].down;
  96. dlx[dlx[x].down].up = dlx[x].up;
  97. }
  98. void re(ul x)
  99. {
  100. change(dlx[x].col, 1);
  101. dlx[dlx[x].right].left = x;
  102. dlx[dlx[x].left].right = x;
  103. dlx[dlx[x].up].down = x;
  104. dlx[dlx[x].down].up = x;
  105. }
  106. bool search()
  107. {
  108. if (dlx[head].right == head) {
  109. return true;
  110. }
  111. ul co = c[mnid[1]];
  112. if (dlx[co].down == co) {
  113. return false;
  114. }
  115. currcol.push_back(0);
  116. for (ul i = dlx[co].up; i != co; i = dlx[i].up) {
  117. currcol.push_back(i);
  118. }
  119. delv.push_back(0);
  120. for (ul i = dlx[co].down; ; i = dlx[i].down) {
  121. delv.push_back(i);
  122. del(i);
  123. if (i == co) {
  124. break;
  125. }
  126. }
  127. while (currcol.back()) {
  128. delv.push_back(0);
  129. ul choice = currcol.back();
  130. ans.push_back(dlx[choice].row);
  131. currcol.pop_back();
  132. ul tmp = dlx[choice].right;
  133. if (tmp != choice) {
  134. for (ul i = dlx[tmp].right; ; i = dlx[i].right) {
  135. for (ul j = dlx[i].down; ; j = dlx[j].down) {
  136. if (j == c[dlx[i].col]) {
  137. delv.push_back(j);
  138. del(j);
  139. continue;
  140. }
  141. if (j == i) {
  142. delv.push_back(j);
  143. del(j);
  144. break;
  145. }
  146. for (ul k = dlx[j].right; ; k = dlx[k].right) {
  147. delv.push_back(k);
  148. del(k);
  149. if (k == j) {
  150. break;
  151. }
  152. }
  153. }
  154. if (i == tmp) {
  155. break;
  156. }
  157. }
  158. }
  159. if (search()) {
  160. return true;
  161. }
  162. while (delv.back()) {
  163. re(delv.back());
  164. delv.pop_back();
  165. }
  166. delv.pop_back();
  167. ans.pop_back();
  168. }
  169. currcol.pop_back();
  170. while (delv.back()) {
  171. re(delv.back());
  172. delv.pop_back();
  173. }
  174. delv.pop_back();
  175. return false;
  176. }
  177. int main()
  178. {
  179. for (ul i = 1, j = 0; i <= 8; ++j) {
  180. if (__builtin_popcount(j) == 2) {
  181. hash[i] = j;
  182. ++i;
  183. }
  184. }
  185. for (ul n = 4; n <= 8; ++n) {
  186. for (ul i = 1; i <= n; ++i) {
  187. per[i] = i;
  188. }
  189. for (ul id = 1; ; ++id) {
  190. std::memcpy(idtoper[n][id] + 1, per + 1, n * sizeof(ul));
  191. ul cntl = 0, cntr = 0;
  192. ul mx = 0;
  193. for (ul i = 1; i <= n; ++i) {
  194. if (per[i] > mx) {
  195. mx = per[i];
  196. ++cntl;
  197. }
  198. }
  199. mx = 0;
  200. for (ul i = n; i >= 1; --i) {
  201. if (per[i] > mx) {
  202. mx = per[i];
  203. ++cntr;
  204. }
  205. }
  206. able[n][cntl][cntr].push_back(id);
  207. able[n][0][cntr].push_back(id);
  208. able[n][cntl][0].push_back(id);
  209. able[n][0][0].push_back(id);
  210. if (!std::next_permutation(per + 1, per + n + 1)) {
  211. break;
  212. }
  213. }
  214. }
  215. std::scanf("%u", &T);
  216. for (ul Case = 1; Case <= T; ++Case) {
  217. std::scanf("%u", &n);
  218. ul facn = 1;
  219. for (ul i = 1; i <= n; ++i) {
  220. facn *= i;
  221. }
  222. for (ul i = 1; i <= n; ++i) {
  223. std::scanf("%u", &t[i]);
  224. }
  225. for (ul i = 1; i <= n; ++i) {
  226. std::scanf("%u", &b[i]);
  227. }
  228. for (ul i = 1; i <= n; ++i) {
  229. std::scanf("%u", &l[i]);
  230. }
  231. for (ul i = 1; i <= n; ++i) {
  232. std::scanf("%u", &r[i]);
  233. }
  234. for (ul i = 1; i <= n; ++i) {
  235. ablev3[i] = able[n][l[i]][r[i]];
  236. ablev4[i] = able[n][t[i]][b[i]];
  237. }
  238. while (true) {
  239. ul prevcnt = 0;
  240. for (ul i = 1; i <= n; ++i) {
  241. for (ul j = 1; j <= n; ++j) {
  242. for (ul v = 1; v <= n; ++v) {
  243. ablev1[i][j][v] = ablev2[i][j][v] = false;
  244. }
  245. }
  246. }
  247. for (ul i = 1; i <= n; ++i) {
  248. for (ul j : ablev3[i]) {
  249. for (ul k = 1; k <= n; ++k) {
  250. ablev1[i][k][idtoper[n][j][k]] = true;
  251. }
  252. ++prevcnt;
  253. }
  254. }
  255. for (ul i = 1; i <= n; ++i) {
  256. for (ul j : ablev4[i]) {
  257. for (ul k = 1; k <= n; ++k) {
  258. ablev2[k][i][idtoper[n][j][k]] = true;
  259. }
  260. ++prevcnt;
  261. }
  262. }
  263. ul currcnt = 0;
  264. for (ul i = 1; i <= n; ++i) {
  265. tmp.resize(0);
  266. for (ul j : ablev3[i]) {
  267. bool flag = true;
  268. for (ul k = 1; k <= n; ++k) {
  269. ul v = idtoper[n][j][k];
  270. if (!ablev1[i][k][v] || !ablev2[i][k][v]) {
  271. flag = false;
  272. break;
  273. }
  274. }
  275. if (flag) {
  276. tmp.push_back(j);
  277. ++currcnt;
  278. }
  279. }
  280. std::swap(tmp, ablev3[i]);
  281. }
  282. for (ul i = 1; i <= n; ++i) {
  283. tmp.resize(0);
  284. for (ul j : ablev4[i]) {
  285. bool flag = true;
  286. for (ul k = 1; k <= n; ++k) {
  287. ul v = idtoper[n][j][k];
  288. if (!ablev1[k][i][v] || !ablev2[k][i][v]) {
  289. flag = false;
  290. break;
  291. }
  292. }
  293. if (flag) {
  294. tmp.push_back(j);
  295. ++currcnt;
  296. }
  297. }
  298. std::swap(tmp, ablev4[i]);
  299. }
  300. if (currcnt == prevcnt) {
  301. break;
  302. }
  303. }
  304. init();
  305. for (ul i = 1; i <= (sz << 1) - 1; ++i) {
  306. mnid[i] = 0;
  307. cnt[i] = ~ul(0);
  308. }
  309. for (ul i = 1; i <= n + n + n * n * 5 + n * n + n * n + n * n + n * n * 5 + n * n * 5 + n * n + n * n + n * n * n * 2; ++i) {
  310. mnid[i | sz] = i;
  311. pushc(i);
  312. cnt[i | sz] = 0;
  313. }
  314. for (ul i = 1; i <= n; ++i) {
  315. for (ul j : ablev3[i]) {
  316. front = 0;
  317. ul row = (i - 1) * facn + j;
  318. ul s = 0;
  319. push(row, s + i);
  320. s = n + n;
  321. for (ul k = 1; k <= n; ++k) {
  322. ul v = idtoper[n][j][k];
  323. for (ul m = 0; m != 5; ++m) {
  324. if (hash[v] >> m & 1) {
  325. push(row, s + ((i - 1) * n + k - 1) * 5 + m + 1);
  326. }
  327. }
  328. }
  329. s = n + n + n * n * 5;
  330. for (ul k = 1; k <= n; ++k) {
  331. ul v = idtoper[n][j][k];
  332. push(row, s + (k - 1) * n + v);
  333. }
  334. s = n + n + n * n * 5 + n * n + n * n + n * n;
  335. for (ul k = 1; k <= n; ++k) {
  336. ul v = idtoper[n][j][k];
  337. for (ul m = 0; m != 5; ++m) {
  338. if (hash[v] >> m & 1) {
  339. push(row, s + ((i - 1) * n + k - 1) * 5 + m + 1);
  340. }
  341. }
  342. }
  343. s = n + n + n * n * 5 + n * n + n * n + n * n + n * n * 5 + n * n * 5 + n * n + n * n;
  344. for (ul k = 1; k <= n; ++k) {
  345. ul v = idtoper[n][j][k];
  346. push(row, s + (i - 1) * n * n + (k - 1) * n + v);
  347. }
  348. }
  349. }
  350. for (ul i = 1; i <= n; ++i) {
  351. for (ul j : ablev4[i]) {
  352. front = 0;
  353. ul row = (n + i - 1) * facn + j;
  354. ul s = n;
  355. push(row, s + i);
  356. s = n + n;
  357. for (ul k = 1; k <= n; ++k) {
  358. ul v = idtoper[n][j][k];
  359. for (ul m = 0; m != 5; ++m) {
  360. if (~hash[v] >> m & 1) {
  361. push(row, s + ((k - 1) * n + i - 1) * 5 + m + 1);
  362. }
  363. }
  364. }
  365. s = n + n + n * n * 5 + n * n;
  366. for (ul k = 1; k <= n; ++k) {
  367. ul v = idtoper[n][j][k];
  368. push(row, s + (k - 1) * n + v);
  369. }
  370. s = n + n + n * n * 5 + n * n + n * n + n * n + n * n * 5;
  371. for (ul k = 1; k <= n; ++k) {
  372. ul v = idtoper[n][j][k];
  373. for (ul m = 0; m != 5; ++m) {
  374. if (hash[v] >> m & 1) {
  375. push(row, s + ((k - 1) * n + i - 1) * 5 + m + 1);
  376. }
  377. }
  378. }
  379. s = n + n + n * n * 5 + n * n + n * n + n * n + n * n * 5 + n * n * 5 + n * n + n * n + n * n * n;
  380. for (ul k = 1; k <= n; ++k) {
  381. ul v = idtoper[n][j][k];
  382. push(row, s + (k - 1) * n * n + (i - 1) * n + v);
  383. }
  384. }
  385. }
  386. for (ul i = 1; i <= n; ++i) {
  387. for (ul j = 1; j <= n; ++j) {
  388. for (ul v = 1; v <= n; ++v) {
  389. if (!ablev1[i][j][v] || !ablev2[i][j][v]) {
  390. continue;
  391. }
  392. front = 0;
  393. ul row = (n + n) * facn + (i - 1) * n * n + (j - 1) * n + v;
  394. ul s = n + n + n * n * 5 + n * n + n * n;
  395. push(row, s + (i - 1) * n + j);
  396. s = n + n + n * n * 5 + n * n + n * n + n * n;
  397. for (ul m = 0; m != 5; ++m) {
  398. if (~hash[v] >> m & 1) {
  399. push(row, s + ((i - 1) * n + j - 1) * 5 + m + 1);
  400. }
  401. }
  402. s = n + n + n * n * 5 + n * n + n * n + n * n + n * n * 5;
  403. for (ul m = 0; m != 5; ++m) {
  404. if (~hash[v] >> m & 1) {
  405. push(row, s + ((i - 1) * n + j - 1) * 5 + m + 1);
  406. }
  407. }
  408. s = n + n + n * n * 5 + n * n + n * n + n * n + n * n * 5 + n * n * 5;
  409. push(row, s + (i - 1) * n + v);
  410. s = n + n + n * n * 5 + n * n + n * n + n * n + n * n * 5 + n * n * 5 + n * n;
  411. push(row, s + (j - 1) * n + v);
  412. s = n + n + n * n * 5 + n * n + n * n + n * n + n * n * 5 + n * n * 5 + n * n + n * n;
  413. for (ul k = 1; k <= n; ++k) {
  414. if (k == i) {
  415. continue;
  416. }
  417. push(row, s + (k - 1) * n * n + (j - 1) * n + v);
  418. }
  419. s = n + n + n * n * 5 + n * n + n * n + n * n + n * n * 5 + n * n * 5 + n * n + n * n + n * n * n;
  420. for (ul k = 1; k <= n; ++k) {
  421. if (k == j) {
  422. continue;
  423. }
  424. push(row, s + (i - 1) * n * n + (k - 1) * n + v);
  425. }
  426. }
  427. }
  428. }
  429. search();
  430. std::sort(ans.begin(), ans.end());
  431. for (ul a : ans) {
  432. if (a > n * facn) {
  433. continue;
  434. }
  435. ul id = (a - 1) % facn + 1;
  436. for (ul i = 1; i <= n; ++i) {
  437. if (i != 1) {
  438. std::putchar(' ');
  439. }
  440. std::printf("%u", idtoper[n][id][i]);
  441. }
  442. std::putchar('\n');
  443. }
  444. }
  445. return 0;
  446. }

G、Game 6873

很裸的平衡树,直接用无旋树堆就能过。

  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, q;
  8. const ul maxn = 2e5;
  9. std::mt19937_64 rnd;
  10. class node {
  11. public:
  12. ul lc = 0;
  13. ul rc = 0;
  14. ul sz = 0;
  15. ul mn = 0;
  16. ul val = 0;
  17. ull sum = 0;
  18. ull rank = 0;
  19. node()=default;
  20. void init() {
  21. *this = node();
  22. mn = ~ul(0);
  23. rank = rnd();
  24. }
  25. };
  26. node tree[maxn + 1];
  27. void update(ul x)
  28. {
  29. tree[x].sz = tree[tree[x].lc].sz + tree[tree[x].rc].sz + 1;
  30. tree[x].mn = std::min(std::min(tree[tree[x].lc].mn, tree[tree[x].rc].mn), tree[x].val);
  31. tree[x].sum = tree[tree[x].lc].sum + tree[tree[x].rc].sum + tree[x].val;
  32. }
  33. void split(ul root, ul& a, ul& b, ul pos)
  34. {
  35. if (!root) {
  36. a = b = 0;
  37. return;
  38. }
  39. if (tree[tree[root].lc].sz + 1 < pos) {
  40. pos -= tree[tree[root].lc].sz + 1;
  41. a = root;
  42. split(tree[root].rc, tree[a].rc, b, pos);
  43. } else {
  44. b = root;
  45. split(tree[root].lc, a, tree[b].lc, pos);
  46. }
  47. update(root);
  48. }
  49. void merge(ul& root, ul a, ul b)
  50. {
  51. if (!a || !b) {
  52. root = a ^ b;
  53. return;
  54. }
  55. if (tree[a].rank > tree[b].rank) {
  56. root = a;
  57. merge(tree[root].rc, tree[a].rc, b);
  58. } else {
  59. root = b;
  60. merge(tree[root].lc, a, tree[b].lc);
  61. }
  62. update(root);
  63. }
  64. ul queryval(ul root, ul pos)
  65. {
  66. for ( ; ; ) {
  67. if (tree[tree[root].lc].sz + 1 < pos) {
  68. pos -= tree[tree[root].lc].sz + 1;
  69. root = tree[root].rc;
  70. } else if (tree[tree[root].lc].sz >= pos) {
  71. root = tree[root].lc;
  72. } else {
  73. return tree[root].val;
  74. }
  75. }
  76. }
  77. ul querypos(ul root, ul val)
  78. {
  79. ul ret = 0;
  80. if (tree[root].mn >= val) {
  81. return 0;
  82. }
  83. for ( ; ; ) {
  84. if (tree[tree[root].rc].mn < val) {
  85. ret += tree[tree[root].lc].sz + 1;
  86. root = tree[root].rc;
  87. } else if (tree[root].val < val) {
  88. ret += tree[tree[root].lc].sz + 1;
  89. return ret;
  90. } else {
  91. root = tree[root].lc;
  92. }
  93. }
  94. }
  95. int main()
  96. {
  97. rnd.seed(std::time(0));
  98. std::scanf("%u", &T);
  99. for (ul Case = 1; Case <= T; ++Case) {
  100. std::scanf("%u%u", &n, &q);
  101. ul root = 0;
  102. tree[root].init();
  103. for (ul i = 1; i <= n; ++i) {
  104. tree[i].init();
  105. std::scanf("%u", &tree[i].val);
  106. update(i);
  107. merge(root, root, i);
  108. }
  109. for (ul i = 1; i <= q; ++i) {
  110. ul t;
  111. std::scanf("%u", &t);
  112. if (t == 1) {
  113. ul x, y;
  114. std::scanf("%u%u", &x, &y);
  115. ul a, e;
  116. split(root, a, e, x + 1);
  117. ul keypos = querypos(a, y);
  118. if (keypos == x || keypos == 0) {
  119. std::printf("0\n");
  120. merge(root, a, e);
  121. continue;
  122. }
  123. ul b, c, d;
  124. split(a, a, c, keypos + 2);
  125. split(a, a, d, keypos + 1);
  126. split(a, a, b, keypos);
  127. ull ans = tree[c].sum + tree[d].sum - ull(tree[c].sz + tree[d].sz) * ull(y - 1);
  128. tree[b].val += tree[d].val - y + 1;
  129. update(b);
  130. tree[d].val = y - 1;
  131. update(d);
  132. merge(root, a, b);
  133. merge(root, root, c);
  134. merge(root, root, d);
  135. merge(root, root, e);
  136. std::printf("%llu\n", ans);
  137. } else if (t == 2) {
  138. ul x;
  139. std::scanf("%u", &x);
  140. std::printf("%u\n", queryval(root, x));
  141. }
  142. }
  143. for (ul i = 1; i <= n; ++i) {
  144. if (i != 1) {
  145. std::putchar(' ');
  146. }
  147. std::printf("%u", queryval(root, i));
  148. }
  149. std::putchar('\n');
  150. }
  151. return 0;
  152. }

H、Distance 6874

  为了连贯性,用表示
  设,首先考虑莫队把排序(按照分段,每一段内按照从小到大排序即可)。直接这么做,时间复杂度是来自重链剖分套线段树的查询和修改),需要继续降低时间。接着,注意(设):


其中第一和第三个求和中所需要计算的项,可以在次修改以及查询中完成,而第二和第四个求和中,根据莫队的特性可知,一共要算个结果,总共需要次查询,修改则需要次。由此可知,总计需要次查询,次修改。
“所以要求修改要完成,查询要完成,这样就能让总时间复杂度为,直接对树根号分块即可。”
引号中的话是官方题解翻译过来的结果,但我实在不知道怎样分块能做到这么好的程度,最终选择重链剖分套根号分块。于是总时间复杂度为,关于为什么第二个在根号里边,请自行证明。直接这样还是会超时的,接着,注意到二次离线莫队将允许像写广搜动态规划那样转移,所以实际询问次数可以压缩到最小生成树的大小,这样常数就很小了。(其实原则上可以更小,因为是允许辅助点的,所以是斯坦纳树)。

  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 = 2e5;
  9. const ul maxm = 2e5;
  10. class edge_t {
  11. public:
  12. ul to = 0;
  13. ul d = 0;
  14. edge_t(ul a, ul b): to(a), d(b) {}
  15. edge_t()=default;
  16. };
  17. std::vector<edge_t> edge[maxn + 1];
  18. ul p[maxn + 1];
  19. ul bigc[maxn + 1];
  20. ul depth[maxn + 1];
  21. ul sz[maxn + 1];
  22. ul dfn[maxn + 1];
  23. ul rdfn[maxn + 1];
  24. ul hvhd[maxn + 1];
  25. ul hvlen[maxn + 1];
  26. ul hvb[maxn + 1];
  27. ul hvbdfn[maxn + 1];
  28. ul rdfnhvhddfn[maxn + 1];
  29. ul rdfnphvhddfn[maxn + 1];
  30. ul depthdfn[maxn + 1];
  31. ul hvlendfn[maxn + 1];
  32. ul lambda[maxn + 1];
  33. ul alpha[maxn + 1];
  34. ul as[maxn + 1];
  35. ul bs[maxn + 1];
  36. ul ap[maxn + 1];
  37. ul bp[maxn + 1];
  38. ul sd;
  39. ul cnt;
  40. void search1(ul curr)
  41. {
  42. sz[curr] = 1;
  43. const ul prev = p[curr];
  44. bigc[curr] = 0;
  45. for (const auto &e : edge[curr]) {
  46. ul next = e.to;
  47. ul d = e.d;
  48. if (next == prev) {
  49. continue;
  50. }
  51. depth[next] = depth[curr] + d;
  52. p[next] = curr;
  53. search1(next);
  54. sz[curr] += sz[next];
  55. if (!bigc[curr] || sz[next] > sz[bigc[curr]]) {
  56. bigc[curr] = next;
  57. }
  58. }
  59. }
  60. ul tim = 0;
  61. void search2(ul curr)
  62. {
  63. ++tim;
  64. rdfn[curr] = tim;
  65. dfn[tim] = curr;
  66. rdfnhvhddfn[tim] = rdfn[hvhd[curr]];
  67. rdfnphvhddfn[tim] = rdfn[p[hvhd[curr]]];
  68. depthdfn[tim] = depth[curr];
  69. lambda[tim] = depth[curr] - depth[dfn[rdfnphvhddfn[tim]]];
  70. if (bigc[curr]) {
  71. hvhd[bigc[curr]] = hvhd[curr];
  72. ++hvlen[hvhd[curr]];
  73. search2(bigc[curr]);
  74. }
  75. ul prev = p[curr];
  76. for (const auto &e : edge[curr]) {
  77. ul next = e.to;
  78. if (next == prev || next == bigc[curr]) {
  79. continue;
  80. }
  81. hvhd[next] = next;
  82. hvlen[next] = 1;
  83. search2(next);
  84. }
  85. hvlendfn[rdfn[curr]] = hvlen[curr];
  86. }
  87. void insert(ul x)
  88. {
  89. sd += depth[x];
  90. ++cnt;
  91. ul rx = rdfn[x];
  92. while (rx) {
  93. ul rh = rdfnhvhddfn[rx];
  94. ul dis = depthdfn[rx] - depthdfn[rdfnphvhddfn[rx]];
  95. ul len = hvlendfn[rh];
  96. ul b = hvbdfn[rh];
  97. ul q = (rx - rh) / b;
  98. ul r = (rx - rh) % b;
  99. for (ul i = 0, j = rh; i != q; ++i, j += b) {
  100. ++as[j];
  101. }
  102. for (ul i = 0, j = rh + q * b; i != r; ++i, ++j) {
  103. ++ap[j];
  104. }
  105. for (ul i = r, j = rh + q * b + r; j != rh + len && i != b; ++i, ++j) {
  106. bp[j] += dis;
  107. }
  108. for (ul i = q + 1, j = rh + (q + 1) * b; j < rh + len; ++i, j += b) {
  109. bs[j] += dis;
  110. }
  111. rx = rdfnphvhddfn[rx];
  112. }
  113. }
  114. ul query(ul x)
  115. {
  116. ul r = rdfn[x];
  117. ul ret = depth[x] * cnt + sd;
  118. while (r) {
  119. ul alphar = alpha[r];
  120. ret -= (as[alphar] + ap[r]) * lambda[r] + bs[alphar] + bp[r] << 1;
  121. r = rdfnphvhddfn[r];
  122. }
  123. return ret;
  124. }
  125. void init(ul n)
  126. {
  127. sd = 0;
  128. cnt = 0;
  129. for (ul i = 1; i <= n; ++i) {
  130. as[i] = ap[i] = bs[i] = bp[i] = 0;
  131. }
  132. }
  133. class query_t {
  134. public:
  135. ul l = 0;
  136. ul r = 0;
  137. ul val = 0;
  138. };
  139. query_t qs[maxm + 1];
  140. std::vector<std::pair<li, std::pair<ul, ul>>> cs[maxn + 2];
  141. ul sum[maxn + 2];
  142. class vec {
  143. public:
  144. li x = 0;
  145. li y = 0;
  146. vec()=default;
  147. vec(li a, li b): x(a), y(b) {}
  148. };
  149. vec operator+(const vec& a, const vec& b)
  150. {
  151. return vec(a.x + b.x, a.y + b.y);
  152. }
  153. vec operator-(const vec& a, const vec& b)
  154. {
  155. return vec(a.x - b.x, a.y - b.y);
  156. }
  157. li norm(const vec& a)
  158. {
  159. return (a.x < 0 ? -a.x : a.x) + (a.y < 0 ? -a.y : a.y);
  160. }
  161. li operator*(const vec& a, const vec& b)
  162. {
  163. return a.x * b.x + a.y * b.y;
  164. }
  165. vec operator*(const vec& a, li b)
  166. {
  167. return vec(a.x * b, a.y * b);
  168. }
  169. vec querypoint[maxm + 1];
  170. std::vector<ul> mintree[maxm + 1];
  171. ul fa[maxm + 1];
  172. ul rk[maxm + 1];
  173. ul getfather(ul x)
  174. {
  175. return fa[x] == x ? x : fa[x] = getfather(fa[x]);
  176. }
  177. bool connect(ul x, ul y)
  178. {
  179. x = getfather(x);
  180. y = getfather(y);
  181. if (x == y) {
  182. return false;
  183. }
  184. if (rk[x] > rk[y]) {
  185. fa[y] = x;
  186. } else if (rk[y] > rk[x]) {
  187. fa[x] = y;
  188. } else {
  189. fa[x] = y;
  190. ++rk[y];
  191. }
  192. return true;
  193. }
  194. const ul segsz = 1 << 19;
  195. ul segtree[segsz << 1];
  196. void change(ul pos, ul id, const li w[])
  197. {
  198. assert(pos >= 1 && pos <= segsz - 1);
  199. pos |= segsz;
  200. if (w[segtree[pos]] <= w[id]) {
  201. return;
  202. }
  203. for (segtree[pos] = id, pos >>= 1; pos; pos >>= 1) {
  204. ul next = w[segtree[pos << 1]] < w[segtree[pos << 1 | 1]] ? segtree[pos << 1] : segtree[pos << 1 | 1];
  205. segtree[pos] == next ? (pos = 1) : (segtree[pos] = next);
  206. }
  207. }
  208. ul query(ul l, ul r, const li w[])
  209. {
  210. ul ret = 0;
  211. for (l = l - 1 | segsz, r = r + 1 | segsz; l ^ r ^ 1; l >>= 1, r >>= 1) {
  212. if (~l & 1) {
  213. ret = w[ret] < w[segtree[l ^ 1]] ? ret : segtree[l ^ 1];
  214. }
  215. if (r & 1) {
  216. ret = w[ret] < w[segtree[r ^ 1]] ? ret : segtree[r ^ 1];
  217. }
  218. }
  219. return ret;
  220. }
  221. li len(ul a, ul b, const vec p[])
  222. {
  223. if (!a || !b) {
  224. return std::max(p[a ^ b].x, p[a ^ b].y) - std::min(p[a ^ b].x, p[a ^ b].y);
  225. } else {
  226. return norm(p[a] - p[b]);
  227. }
  228. }
  229. void mintreel1(const vec p[], std::vector<ul> edge[], ul m)
  230. {
  231. static ul o[maxm + 1];
  232. static std::vector<std::pair<ul, ul>> edges;
  233. static li dir3p[maxm + 1];
  234. static li dir1p[maxm + 1];
  235. edges.resize(0);
  236. for (ul i = 0; i <= m; ++i) {
  237. edge[i].resize(0);
  238. fa[i] = i;
  239. rk[i] = 0;
  240. o[i] = i;
  241. edges.push_back(std::pair<ul, ul>(0, i));
  242. }
  243. static const std::vector<vec> dirs = {vec(1, 0), vec(0, 1)};
  244. for (const auto& dir1 : dirs) {
  245. for (li lambda : {-1, 1}) {
  246. const vec dirt = vec(dir1.y, dir1.x) * lambda;
  247. const vec dir2 = vec(0, 0) - dirt - dir1;
  248. const vec dir3 = dirt - dir1;
  249. for (ul i = 1; i <= m; ++i) {
  250. dir3p[i] = dir3 * p[i];
  251. dir1p[i] = dir1 * p[i];
  252. }
  253. std::sort(o + 1, o + m + 1, [&](ul a, ul b){return dir1p[a] != dir1p[b] ? dir1p[a] < dir1p[b] : (dir3p[a] != dir3p[b] ? dir3p[a] > dir3p[b] : a < b);});
  254. dir3p[0] = dir3 * li(maxn + 1) * dir3;
  255. std::memset(segtree, 0, sizeof(segtree));
  256. li mn = 1e9;
  257. for (const auto& v : {vec(1, 1), vec(maxn, maxn), vec(1, maxn)}) {
  258. mn = std::min(mn, v * dir2);
  259. }
  260. for (ul i = 1; i <= m; ++i) {
  261. auto t = query(1, p[o[i]] * dir2 - mn + 1, dir3p);
  262. if (t) {
  263. edges.push_back(std::pair<ul, ul>(o[i], t));
  264. }
  265. change(p[o[i]] * dir2 - mn + 1, o[i], dir3p);
  266. }
  267. }
  268. }
  269. std::sort(edges.begin(), edges.end(), [&](const std::pair<ul, ul>& a, const std::pair<ul, ul>& b){
  270. return len(a.first, a.second, p) < len(b.first, b.second, p);});
  271. for (const auto& e : edges) {
  272. ul a = e.first;
  273. ul b = e.second;
  274. if (connect(a, b)) {
  275. edge[a].push_back(b);
  276. edge[b].push_back(a);
  277. }
  278. }
  279. }
  280. std::deque<ul> queue;
  281. int main()
  282. {
  283. std::scanf("%u", &T);
  284. for (ul Case = 1; Case <= T; ++Case) {
  285. auto start = std::clock();
  286. std::scanf("%u%u", &n, &m);
  287. for (ul i = 1; i <= n; ++i) {
  288. edge[i].resize(0);
  289. }
  290. for (ul i = 1; i <= n - 1; ++i) {
  291. ul u, v, d;
  292. std::scanf("%u%u%u", &u, &v, &d);
  293. edge[u].push_back(edge_t(v, d));
  294. edge[v].push_back(edge_t(u, d));
  295. }
  296. ul root = 1;
  297. depth[root] = 0;
  298. p[root] = 0;
  299. search1(root);
  300. tim = 0;
  301. hvhd[root] = root;
  302. hvlen[root] = 1;
  303. search2(root);
  304. for (ul i = 1; i <= n; ++i) {
  305. if (hvhd[i] == i) {
  306. hvb[i] = std::round(std::sqrt(hvlen[i]));
  307. hvbdfn[rdfn[i]] = hvb[i];
  308. }
  309. }
  310. for (ul r = 1; r <= n; ++r) {
  311. ul rh = rdfnhvhddfn[r];
  312. ul b = hvbdfn[rh];
  313. ul q = (r - rh) / b;
  314. alpha[r] = rh + q * b;
  315. }
  316. for (ul i = 1; i <= m; ++i) {
  317. std::scanf("%u%u", &qs[i].l, &qs[i].r);
  318. qs[i].val = 0;
  319. }
  320. for (ul i = 1; i <= m; ++i) {
  321. querypoint[i] = vec(qs[i].l, qs[i].r);
  322. }
  323. mintreel1(querypoint, mintree, m);
  324. while (queue.size()) {
  325. queue.pop_front();
  326. }
  327. for (ul i = 0; i <= n; ++i) {
  328. cs[i].resize(0);
  329. }
  330. for (ul start : mintree[0]) {
  331. queue.push_back(start);
  332. fa[start] = 0;
  333. cs[qs[start].l - 1].push_back(std::pair<li, std::pair<ul, ul>>(start, std::pair<ul, ul>(qs[start].l + 1, qs[start].r)));
  334. }
  335. while (queue.size()) {
  336. ul curr = queue.front();
  337. queue.pop_front();
  338. for (ul next : mintree[curr]) {
  339. if (next == fa[curr]) {
  340. continue;
  341. }
  342. queue.push_back(next);
  343. fa[next] = curr;
  344. cs[qs[next].l - 1].push_back(std::pair<li, std::pair<ul, ul>>(next, std::pair<ul, ul>(qs[curr].r + 1, qs[next].r)));
  345. }
  346. }
  347. init(n);
  348. for (ul i = 0; i <= n; ++i) {
  349. if (i >= 1) {
  350. insert(i);
  351. }
  352. sum[i] = i == 0 ? ul(0) : query(i);
  353. if (i >= 1) {
  354. sum[i] += sum[i - 1];
  355. }
  356. for (const auto& p : cs[i]) {
  357. ul to = p.first;
  358. ul a = p.second.first, b = p.second.second;
  359. if (a <= b) {
  360. for (ul i = a; i <= b; ++i) {
  361. qs[to].val -= query(i);
  362. }
  363. } else {
  364. for (ul i = b + 1; i <= a - 1; ++i) {
  365. qs[to].val += query(i);
  366. }
  367. }
  368. }
  369. }
  370. for (li it = 1; it <= m; ++it) {
  371. qs[it].val += fa[it] ? sum[qs[it].r] - sum[qs[fa[it]].r] : sum[qs[it].r] - sum[qs[it].l];
  372. }
  373. while (queue.size()) {
  374. queue.pop_front();
  375. }
  376. for (ul i = 0; i <= n; ++i) {
  377. cs[i].resize(0);
  378. }
  379. for (ul start : mintree[0]) {
  380. queue.push_back(start);
  381. fa[start] = 0;
  382. cs[qs[start].l + 1].push_back(std::pair<li, std::pair<ul, ul>>(start, std::pair<ul, ul>(qs[start].l, qs[start].l - 1)));
  383. }
  384. while (queue.size()) {
  385. ul curr = queue.front();
  386. queue.pop_front();
  387. for (ul next : mintree[curr]) {
  388. if (next == fa[curr]) {
  389. continue;
  390. }
  391. queue.push_back(next);
  392. fa[next] = curr;
  393. cs[qs[curr].r + 1].push_back(std::pair<li, std::pair<ul, ul>>(next, std::pair<ul, ul>(qs[curr].l, qs[next].l - 1)));
  394. }
  395. }
  396. init(n);
  397. for (ul i = n + 1; i >= 1; --i) {
  398. if (i <= n) {
  399. insert(i);
  400. }
  401. sum[i] = i == n + 1 ? ul(0) : query(i);
  402. if (i <= n) {
  403. sum[i] += sum[i + 1];
  404. }
  405. for (const auto& p : cs[i]) {
  406. ul to = p.first;
  407. ul a = p.second.first, b = p.second.second;
  408. if (a <= b) {
  409. for (ul i = a; i <= b; ++i) {
  410. qs[to].val += query(i);
  411. }
  412. } else {
  413. for (ul i = b + 1; i <= a - 1; ++i) {
  414. qs[to].val -= query(i);
  415. }
  416. }
  417. }
  418. }
  419. for (li it = 1; it <= m; ++it) {
  420. qs[it].val -= fa[it] ? sum[qs[fa[it]].l] - sum[qs[it].l] : sum[qs[it].l] - sum[qs[it].l];
  421. }
  422. while (queue.size()) {
  423. queue.pop_front();
  424. }
  425. for (ul start : mintree[0]) {
  426. queue.push_back(start);
  427. fa[start] = 0;
  428. }
  429. while (queue.size()) {
  430. ul curr = queue.front();
  431. queue.pop_front();
  432. qs[curr].val += qs[fa[curr]].val;
  433. for (ul next : mintree[curr]) {
  434. if (fa[curr] == next) {
  435. continue;
  436. }
  437. queue.push_back(next);
  438. fa[next] = curr;
  439. }
  440. }
  441. for (ul i = 1; i <= m; ++i) {
  442. std::printf("%u\n", qs[i].val);
  443. }
  444. }
  445. return 0;
  446. }

I、Yajilin 6875

插头动归,为了思考方便,没有选择一格一格更新,而是一行一行更行,这样会慢一些,但勉强能过。

  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 maxcntfrom = 31189;
  7. enum entry {
  8. x,
  9. tr,
  10. tl,
  11. br,
  12. bl,
  13. lr,
  14. tb
  15. };
  16. enum dir {
  17. t,
  18. b,
  19. l,
  20. r
  21. };
  22. bool right(entry y)
  23. {
  24. return y == tr || y == lr || y == br;
  25. }
  26. bool left(entry y)
  27. {
  28. return y == tl || y == lr || y == bl;
  29. }
  30. bool top(entry y)
  31. {
  32. return y == tl || y == tr || y == tb;
  33. }
  34. bool buttom(entry y)
  35. {
  36. return y == bl || y == br || y == tb;
  37. }
  38. const ul maxn = 10;
  39. ul brackstack[maxn + 1];
  40. ul match[maxn + 1];
  41. char from[maxn + 1];
  42. entry edge[maxn + 1];
  43. char to[maxn + 1];
  44. bool alvis[maxn + 1];
  45. ul cnt[2];
  46. ul go1(ul i)
  47. {
  48. dir prev = b;
  49. while (true) {
  50. alvis[i] = true;
  51. if (prev == b) {
  52. if (edge[i] == bl) {
  53. prev = r;
  54. --i;
  55. } else if (edge[i] == br) {
  56. prev = l;
  57. ++i;
  58. } else if (edge[i] == tb) {
  59. prev = t;
  60. i = match[i];
  61. }
  62. } else if (prev == t) {
  63. if (edge[i] == tl) {
  64. prev = r;
  65. --i;
  66. } else if (edge[i] == tr) {
  67. prev = l;
  68. ++i;
  69. } else if (edge[i] == tb) {
  70. break;
  71. }
  72. } else if (prev == l) {
  73. if (edge[i] == lr) {
  74. prev = l;
  75. ++i;
  76. } else if (edge[i] == tl) {
  77. prev = t;
  78. i = match[i];
  79. } else if (edge[i] == bl) {
  80. break;
  81. }
  82. } else if (prev == r) {
  83. if (edge[i] == lr) {
  84. prev = r;
  85. --i;
  86. } else if (edge[i] == tr) {
  87. prev = t;
  88. i = match[i];
  89. } else if (edge[i] == br) {
  90. break;
  91. }
  92. }
  93. }
  94. return i;
  95. }
  96. void go2(ul i)
  97. {
  98. dir prev = r;
  99. while (!alvis[i]) {
  100. alvis[i] = true;
  101. if (prev == t) {
  102. if (edge[i] == tl) {
  103. prev = r;
  104. --i;
  105. } else if (edge[i] == tr) {
  106. prev = l;
  107. ++i;
  108. }
  109. } else if (prev == l) {
  110. if (edge[i] == lr) {
  111. prev = l;
  112. ++i;
  113. } else if (edge[i] == tl) {
  114. prev = t;
  115. i = match[i];
  116. }
  117. } else if (prev == r) {
  118. if (edge[i] == lr) {
  119. prev = r;
  120. --i;
  121. } else if (edge[i] == tr) {
  122. prev = t;
  123. i = match[i];
  124. }
  125. }
  126. }
  127. }
  128. ul fromid[1 << 20];
  129. ul gethash(char str[], ul n)
  130. {
  131. ul ret = 0;
  132. for (ul i = 1; i <= n; ++i) {
  133. ret *= 4;
  134. if (str[i] == '1') {
  135. ret += 1;
  136. }
  137. if (str[i] == '(') {
  138. ret += 2;
  139. }
  140. if (str[i] == ')') {
  141. ret += 3;
  142. }
  143. }
  144. return ret;
  145. }
  146. ul space[ul(1e7)];
  147. ul* currend = space;
  148. class trans_t {
  149. public:
  150. ul* begin;
  151. ul* end;
  152. ul toid;
  153. };
  154. std::vector<trans_t> trans[maxn + 1][maxcntfrom + 1][2];
  155. ul cntfrom[maxn + 1];
  156. std::vector<ul> ablein[maxn + 1];
  157. std::vector<ul> ableout[maxn + 1];
  158. bool possible[maxn + 1][maxn + 1][maxcntfrom + 1][2];
  159. bool possible2[maxn + 1][maxn + 1][maxcntfrom + 1][2];
  160. std::vector<ul> pv[maxn + 1][maxn + 1][2];
  161. trans_t fromastrans[maxn + 1][maxcntfrom + 1];
  162. void search1(ul pos, ul n)
  163. {
  164. if (pos == n + 1) {
  165. ul addcircle = 0;
  166. for (ul i = 1; i <= n; ++i) {
  167. to[i] = edge[i] == x ? '1' : '0';
  168. alvis[i] = false;
  169. }
  170. for (ul i = 1; i <= n; ++i) {
  171. if (buttom(edge[i]) && !alvis[i]) {
  172. to[i] = '(';
  173. to[go1(i)] = ')';
  174. }
  175. }
  176. for (ul i = 1; i <= n; ++i) {
  177. if (edge[i] == tr && !alvis[i]) {
  178. if (addcircle) {
  179. return;
  180. }
  181. go2(i);
  182. ++addcircle;
  183. }
  184. }
  185. trans_t tmp;
  186. tmp.toid = fromid[gethash(to, n)];
  187. tmp.begin = currend;
  188. for (ul i = 1; i <= n; ++i) {
  189. if (edge[i] == x) {
  190. *currend = i;
  191. ++currend;
  192. }
  193. }
  194. tmp.end = currend;
  195. trans[n][cntfrom[n]][addcircle].push_back(tmp);
  196. ++cnt[addcircle];
  197. return;
  198. }
  199. for (entry curr : {x, tr, tl, br, bl, lr, tb}) {
  200. edge[pos] = curr;
  201. if (right(edge[pos - 1]) != left(curr)) {
  202. continue;
  203. }
  204. if (left(curr) && pos == 1) {
  205. continue;
  206. }
  207. if (right(curr) && pos == n) {
  208. continue;
  209. }
  210. if (top(curr) == (from[pos] == '0' || from[pos] == '1')) {
  211. continue;
  212. }
  213. if (curr == x && from[pos] == '1') {
  214. continue;
  215. }
  216. if (pos != 1 && curr == x && edge[pos - 1] == x) {
  217. continue;
  218. }
  219. search1(pos + 1, n);
  220. }
  221. }
  222. void search2(ul pos, ul stacksize, ul n)
  223. {
  224. if (stacksize > n - pos + 1) {
  225. return;
  226. }
  227. if (pos == n + 1) {
  228. ul sz = 0;
  229. bool flag = true;
  230. for (ul i = 1; i <= n; ++i) {
  231. if (from[i] == '0' && sz == 0) {
  232. flag = false;
  233. }
  234. if (from[i] == '1' && sz == 1) {
  235. flag = false;
  236. }
  237. if (from[i] == '(') {
  238. ++sz;
  239. if (sz == 2) {
  240. flag = false;
  241. }
  242. brackstack[sz] = i;
  243. } else if (from[i] == ')') {
  244. match[i] = brackstack[sz];
  245. match[brackstack[sz]] = i;
  246. --sz;
  247. }
  248. }
  249. ++cntfrom[n];
  250. if (flag) {
  251. ablein[n].push_back(cntfrom[n]);
  252. }
  253. fromastrans[n][cntfrom[n]].begin = currend;
  254. for (ul i = 1; i <= n; ++i) {
  255. if (from[i] == '1') {
  256. *currend = i;
  257. ++currend;
  258. }
  259. }
  260. fromastrans[n][cntfrom[n]].end = currend;
  261. search1(1, n);
  262. return;
  263. }
  264. from[pos] = '0';
  265. search2(pos + 1, stacksize, n);
  266. if (from[pos - 1] != '1') {
  267. from[pos] = '1';
  268. search2(pos + 1, stacksize, n);
  269. }
  270. if (stacksize > 0) {
  271. from[pos] = ')';
  272. search2(pos + 1, stacksize - 1, n);
  273. }
  274. from[pos] = '(';
  275. search2(pos + 1, stacksize + 1, n);
  276. }
  277. void search3(ul pos, ul stacksize, ul n)
  278. {
  279. if (stacksize > n - pos + 1) {
  280. return;
  281. }
  282. if (pos == n + 1) {
  283. ++cntfrom[n];
  284. fromid[gethash(from, n)] = cntfrom[n];
  285. bool flag = true;
  286. for (ul i = 1; i <= n; ++i) {
  287. if (from[i] == '(' || from[i] == ')') {
  288. flag = false;
  289. break;
  290. }
  291. }
  292. if (flag) {
  293. ableout[n].push_back(cntfrom[n]);
  294. }
  295. return;
  296. }
  297. from[pos] = '0';
  298. search3(pos + 1, stacksize, n);
  299. if (from[pos - 1] != '1') {
  300. from[pos] = '1';
  301. search3(pos + 1, stacksize, n);
  302. }
  303. if (stacksize > 0) {
  304. from[pos] = ')';
  305. search3(pos + 1, stacksize - 1, n);
  306. }
  307. from[pos] = '(';
  308. search3(pos + 1, stacksize + 1, n);
  309. }
  310. ul ans[maxn + 1][maxcntfrom + 1][2];
  311. ul T;
  312. ul n;
  313. const ul inf = ~ul(0);
  314. ul cost[maxn + 1];
  315. char outstr[100000];
  316. char* outend = outstr;
  317. int main()
  318. {
  319. for (ul n = 2; n <= maxn; ++n) {
  320. search3(1, 0, n);
  321. cntfrom[n] = 0;
  322. cnt[0] = cnt[1] = 0;
  323. search2(1, 0, n);
  324. for (ul to : ableout[n]) {
  325. possible[n][n][to][1] = true;
  326. }
  327. for (ul i = n - 1; i >= 1; --i) {
  328. for (ul from = 1; from <= cntfrom[n]; ++from) {
  329. for (const auto& edge : trans[n][from][0]) {
  330. ul to = edge.toid;
  331. if (possible[n][i + 1][to][0]) {
  332. possible[n][i][from][0] = true;
  333. break;
  334. }
  335. }
  336. if (!possible[n][i][from][0]) {
  337. for (const auto& edge : trans[n][from][1]) {
  338. ul to = edge.toid;
  339. if (possible[n][i + 1][to][1]) {
  340. possible[n][i][from][0] = true;
  341. break;
  342. }
  343. }
  344. }
  345. for (const auto& edge : trans[n][from][0]) {
  346. ul to = edge.toid;
  347. if (possible[n][i + 1][to][1]) {
  348. possible[n][i][from][1] = true;
  349. break;
  350. }
  351. }
  352. }
  353. }
  354. for (ul from : ablein[n]) {
  355. if (possible[n][1][from][0]) {
  356. possible2[n][1][from][0] = true;
  357. }
  358. }
  359. for (ul i = 2; i <= n; ++i) {
  360. for (ul from = 1; from <= cntfrom[n]; ++from) {
  361. if (possible2[n][i - 1][from][0]) {
  362. for (const auto& edge : trans[n][from][0]) {
  363. ul to = edge.toid;
  364. if (possible[n][i][to][0]) {
  365. possible2[n][i][to][0] = true;
  366. }
  367. }
  368. for (const auto& edge : trans[n][from][1]) {
  369. ul to = edge.toid;
  370. if (possible[n][i][to][1]) {
  371. possible2[n][i][to][1] = true;
  372. }
  373. }
  374. }
  375. if (possible2[n][i - 1][from][1]) {
  376. for (const auto& edge : trans[n][from][0]) {
  377. ul to = edge.toid;
  378. if (possible[n][i][to][1]) {
  379. possible2[n][i][to][1] = true;
  380. }
  381. }
  382. }
  383. }
  384. }
  385. for (ul i = 1; i <= n; ++i) {
  386. for (ul id = 1; id <= cntfrom[n]; ++id) {
  387. for (ul plus = 0; plus <= 1; ++plus) {
  388. if (possible2[n][i][id][plus]) {
  389. pv[n][i][plus].push_back(id);
  390. }
  391. }
  392. }
  393. }
  394. }
  395. std::scanf("%u", &T);
  396. for (ul Case = 1; Case <= T; ++Case) {
  397. std::scanf("%u", &n);
  398. for (ul from = 1; from <= cntfrom[n]; ++from) {
  399. ans[1][from][0] = ans[1][from][1] = inf;
  400. }
  401. for (ul j = 1; j <= n; ++j) {
  402. std::scanf("%u", &cost[j]);
  403. }
  404. for (ul from : pv[n][1][0]) {
  405. ans[1][from][0] = 0;
  406. for (ul* j = fromastrans[n][from].begin; j != fromastrans[n][from].end; ++j) {
  407. ans[1][from][0] += cost[*j];
  408. }
  409. }
  410. for (ul i = 2; i <= n; ++i) {
  411. for (ul j = 1; j <= n; ++j) {
  412. std::scanf("%u", &cost[j]);
  413. }
  414. for (ul to = 1; to <= cntfrom[n]; ++to) {
  415. ans[i][to][0] = ans[i][to][1] = inf;
  416. }
  417. for (ul from : pv[n][i - 1][0]) {
  418. if (ans[i - 1][from][0] != inf) {
  419. for (const auto& edge : trans[n][from][0]) {
  420. ul newcost = ans[i - 1][from][0];
  421. ul to = edge.toid;
  422. if (!possible[n][i][to][0]) {
  423. continue;
  424. }
  425. for (ul* j = edge.begin; j != edge.end; ++j) {
  426. newcost += cost[*j];
  427. }
  428. if (ans[i][to][0] == inf || ans[i][to][0] < newcost) {
  429. ans[i][to][0] = newcost;
  430. }
  431. }
  432. for (const auto& edge : trans[n][from][1]) {
  433. ul newcost = ans[i - 1][from][0];
  434. ul to = edge.toid;
  435. if (!possible[n][i][to][1]) {
  436. continue;
  437. }
  438. for (ul* j = edge.begin; j != edge.end; ++j) {
  439. newcost += cost[*j];
  440. }
  441. if (ans[i][to][1] == inf || ans[i][to][1] < newcost) {
  442. ans[i][to][1] = newcost;
  443. }
  444. }
  445. }
  446. }
  447. for (ul from : pv[n][i - 1][1]) {
  448. if (ans[i - 1][from][1] != inf) {
  449. for (const auto& edge : trans[n][from][0]) {
  450. ul newcost = ans[i - 1][from][1];
  451. ul to = edge.toid;
  452. if (!possible[n][i][to][1]) {
  453. continue;
  454. }
  455. for (ul* j = edge.begin; j != edge.end; ++j) {
  456. newcost += cost[*j];
  457. }
  458. if (ans[i][to][1] == inf || ans[i][to][1] < newcost) {
  459. ans[i][to][1] = newcost;
  460. }
  461. }
  462. }
  463. }
  464. }
  465. ul out = 0;
  466. for (ul to : ableout[n]) {
  467. if (ans[n][to][1] != inf) {
  468. out = std::max(out, ans[n][to][1]);
  469. }
  470. }
  471. std::sprintf(outend, "%u\n", out);
  472. outend += std::strlen(outend);
  473. }
  474. std::printf(outstr);
  475. return 0;
  476. }

J、Jump 6876

官方题解写得很清楚,如下:
QQ图片20201027202956.png-101.9kB
其中“区间加减、区间求最大最小值”可以依靠差分实现非递归。(根存的是全局最大值,其他节点存的是“此区间的最大值减去母区间的最大值得到的差”)

  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 lf = double;
  7. const ul maxn = 2e5;
  8. const ul maxm = 2e5;
  9. ul T;
  10. ul n, m, rt;
  11. class edge_t {
  12. public:
  13. ul to = 0;
  14. ull len = 0;
  15. edge_t()=default;
  16. edge_t(ul a, ull b): to(a), len(b) {}
  17. };
  18. std::vector<edge_t> edge[maxn + 1];
  19. ul fa[maxn + 1];
  20. ull dep[maxn + 1];
  21. ul len[maxn + 1];
  22. ul lencnt[maxn + 1];
  23. void search(ul curr)
  24. {
  25. len[curr] = 0;
  26. for (const edge_t& e : edge[curr]) {
  27. ul next = e.to;
  28. if (next == fa[curr]) {
  29. continue;
  30. }
  31. fa[next] = curr;
  32. dep[next] = dep[curr] + e.len;
  33. search(next);
  34. len[curr] = std::max(len[curr], len[next] + ul(1));
  35. }
  36. ++lencnt[len[curr]];
  37. }
  38. ul B1, B2;
  39. ul type[maxn + 1];
  40. ul a[maxn + 1];
  41. std::list<std::pair<ul, ul>> list[maxn + 1];
  42. ull mindep[maxn + 1];
  43. ull lentodep[512][maxn + 1];
  44. const ul sz = 1 << 18;
  45. li tree[512][sz << 1];
  46. void change(ul l, ul r, li val, li tree[])
  47. {
  48. li tmp;
  49. for (l = l - 1 | sz, r = r + 1 | sz; l ^ r ^ 1; l >>= 1, r >>= 1) {
  50. if (~l & 1) {
  51. tree[l ^ 1] += val;
  52. }
  53. if (r & 1) {
  54. tree[r ^ 1] += val;
  55. }
  56. tmp = std::max(tree[l], tree[l ^ 1]);
  57. tree[l] -= tmp;
  58. tree[l ^ 1] -= tmp;
  59. tree[l >> 1] += tmp;
  60. tmp = std::max(tree[r], tree[r ^ 1]);
  61. tree[r] -= tmp;
  62. tree[r ^ 1] -= tmp;
  63. tree[r >> 1] += tmp;
  64. }
  65. for (ul i = l; i >> 1; i >>= 1) {
  66. tmp = std::max(tree[i], tree[i ^ 1]);
  67. tree[i] -= tmp;
  68. tree[i ^ 1] -= tmp;
  69. tree[i >> 1] += tmp;
  70. }
  71. }
  72. li query(ul l, ul r, const li tree[])
  73. {
  74. li lans = -1e7;
  75. li rans = -1e7;
  76. for (l = l - 1 | sz, r = r + 1 | sz; l ^ r ^ 1; l >>= 1, r >>= 1) {
  77. if (~l & 1) {
  78. lans = std::max(lans, tree[l ^ 1]);
  79. }
  80. if (r & 1) {
  81. rans = std::max(rans, tree[r ^ 1]);
  82. }
  83. lans += tree[l >> 1];
  84. rans += tree[r >> 1];
  85. }
  86. li ans = std::max(lans, rans);
  87. for (ul i = l; i >> 1; i >>= 1) {
  88. ans += tree[i >> 1];
  89. }
  90. return ans;
  91. }
  92. int main()
  93. {
  94. std::scanf("%u", &T);
  95. for (ul Case = 1; Case <= T; ++Case) {
  96. std::scanf("%u%u%u", &n, &m, &rt);
  97. for (ul i = 1; i <= n; ++i) {
  98. type[i] = 0;
  99. edge[i].resize(0);
  100. lencnt[i] = 0;
  101. }
  102. lencnt[0] = 0;
  103. for (ul i = 1; i <= n - 1; ++i) {
  104. ul u, v, d;
  105. std::scanf("%u%u%u", &u, &v, &d);
  106. edge[u].push_back(edge_t(v, d));
  107. edge[v].push_back(edge_t(u, d));
  108. }
  109. fa[rt] = rt;
  110. dep[rt] = 0;
  111. search(rt);
  112. B1 = 0;
  113. for (ul i = 1; i <= n; ++i) {
  114. if ((lf(n) + lf(m * std::log(n) / std::log(2))) * lencnt[i] + lf(n) * i < (lf(n) + lf(m * std::log(n) / std::log(2))) * lencnt[B1] + lf(n) * B1) {
  115. B1 = i;
  116. }
  117. }
  118. B2 = std::round(std::sqrt(n));
  119. ul cnt = 0;
  120. for (ul i = 1; i <= n; ++i) {
  121. mindep[i / B2] = 1e18;
  122. list[i / B2].clear();
  123. if (len[i] == B1) {
  124. ++cnt;
  125. std::memset(tree[cnt], 0, sizeof(li) * (sz << 1));
  126. tree[cnt][1] = -li(m);
  127. for (ul j = i; ; j = fa[j]) {
  128. type[j] = cnt;
  129. if (type[fa[j]] || len[fa[j]] != len[j] + 1) {
  130. break;
  131. }
  132. }
  133. for (ul t = B1 - 1; t != B1; ++t) {
  134. lentodep[cnt][t] = 1e18;
  135. }
  136. for (ul j = i, t = B1; t <= n; j = fa[j], ++t) {
  137. lentodep[cnt][t] = dep[j];
  138. }
  139. }
  140. }
  141. for (ul i = 1; i <= n; ++i) {
  142. std::scanf("%u", &a[i]);
  143. if (len[a[i]] < B1) {
  144. list[i / B2].push_back(std::pair<ul, ul>(i, a[i]));
  145. mindep[i / B2] = std::min(mindep[i / B2], dep[a[i]]);
  146. } else {
  147. change(i, i, len[a[i]] + li(m), tree[type[a[i]]]);
  148. }
  149. }
  150. for (ul i = 1; i <= m; ++i) {
  151. ul qt, l, r;
  152. std::scanf("%u%u%u", &qt, &l, &r);
  153. if (qt == 1) {
  154. for (ul i = 1; i <= cnt; ++i) {
  155. change(l, r, 1, tree[i]);
  156. }
  157. ul s = l / B2;
  158. ul t = r / B2;
  159. for (ul i = s; i <= t; ++i) {
  160. for (auto it = list[i].begin(); it != list[i].end(); ) {
  161. if (it->first < l || it->first > r) {
  162. ++it;
  163. continue;
  164. }
  165. it->second = fa[it->second];
  166. if (len[it->second] >= B1) {
  167. change(it->first, it->first, li(len[it->second]) - query(it->first, it->first, tree[type[it->second]]), tree[type[it->second]]);
  168. it = list[i].erase(it);
  169. } else {
  170. mindep[i] = std::min(mindep[i], dep[it->second]);
  171. ++it;
  172. }
  173. }
  174. }
  175. } else {
  176. ull ans = 1e18;
  177. for (ul i = 1; i <= cnt; ++i) {
  178. ans = std::min(ans, lentodep[i][std::max(std::min(query(l, r, tree[i]), li(n)), li(B1 - 1))]);
  179. }
  180. ul s = l / B2;
  181. ul t = r / B2;
  182. for (const auto& p : list[s]) {
  183. if (p.first < l || p.first > r) {
  184. continue;
  185. }
  186. ans = std::min(ans, dep[p.second]);
  187. }
  188. for (const auto& p : list[t]) {
  189. if (p.first < l || p.first > r) {
  190. continue;
  191. }
  192. ans = std::min(ans, dep[p.second]);
  193. }
  194. for (ul i = s + 1; i < t; ++i) {
  195. ans = std::min(ans, mindep[i]);
  196. }
  197. std::printf("%llu\n", ans);
  198. }
  199. }
  200. }
  201. return 0;
  202. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注