A B C D E F G H I J K L M
O O O $\varnothing$ $\varnothing$   $\varnothing$ $\varnothing$ $\varnothing$ $\varnothing$      $\varnothing$

[A. Thickest Burger]

签到。

[B. Relative atomic mass]

签到

[C. Recursive sequence]

$$f[i] = f[i - 1] + 2 * f[i - 2] + i ^ 4$$

$$
\left[
\begin{matrix}
1 & 2 & 1 & 0 & 0 & 0 & 0 \\
1 & 0 & 0 & 0 & 0 & 0 & 0\\
0 &0 & 1 & 4 & 6 &4 & 1 \\
0 & 0 & 0 & 1 & 3 & 3 & 1 \\
0 & 0 & 0 & 0 & 1 & 2 & 1 \\
0 & 0 & 0 & 0 & 0 & 1 & 1 \\
0 & 0 & 0 & 0 & 0 & 0 & 1
\end{matrix}
\right]
\times
\left[
\begin{matrix}
f_{i-1} & 0 & 0 & 0 & 0 & 0 & 0 \\
f_{i-2} & 0 & 0 & 0 & 0 & 0 & 0\\
i^4 &0 & 0 & 0& 0 &0 & 0 \\
i^3 & 0 & 0 & 0 & 0 & 0 & 0 \\
i^2 & 0 & 0 & 0 & 0 & 0 & 0\\
i & 0 & 0 & 0 & 0 & 0 & 0 \\
1 & 0 & 0 & 0 & 0 & 0 & 0
\end{matrix}
\right]=
\left[
\begin{matrix}
f_{i} & 0 & 0 & 0 & 0 & 0 & 0 \\
f_{i} & 0 & 0 & 0 & 0 & 0 & 0\\
(i+1)^4 &0 & 0 & 0& 0 &0 & 0 \\
(i+1)^3 & 0 & 0 & 0 & 0 & 0 & 0 \\
(i+1)^2 & 0 & 0 & 0 & 0 & 0 & 0\\
i+1 & 0 & 0 & 0 & 0 & 0 & 0 \\
1 & 0 & 0 & 0 & 0 & 0 & 0
\end{matrix}
\right]
$$

  1. #include <bits/stdc++.h>
  2. #define ll long long
  3.  
  4. const ll MOD = ;
  5. const int N = ;
  6.  
  7. struct Mat {
  8. ll a[][];
  9. Mat() {
  10. memset(a, , sizeof(a));
  11. }
  12. Mat(int x) {
  13. memset(a, , sizeof(a));
  14. for (int i = ; i <= N; i++)
  15. a[i][i] = ;
  16. }
  17. Mat operator * (const Mat &rhs) const {
  18. Mat c;
  19. for (int i = ; i <= N; i++)
  20. for (int j = ; j <= N; j++)
  21. for (int k = ; k <= N; k++)
  22. c.a[i][j] = (c.a[i][j] + a[i][k] * rhs.a[k][j] % MOD) % MOD;
  23. return c;
  24. }
  25. };
  26.  
  27. Mat qp(Mat a, int b) {
  28. Mat c();
  29. while (b) {
  30. if (b & ) c = a * c;
  31. a = a * a;
  32. b >>= ;
  33. }
  34. return c;
  35. }
  36.  
  37. int main() {
  38. int T;
  39. scanf("%d", &T);
  40. Mat base;
  41. base.a[][] = ; base.a[][] = ; base.a[][] = ;
  42. base.a[][] = ;
  43. base.a[][] = ; base.a[][] = ; base.a[][] = ; base.a[][] = ; base.a[][] = ;
  44. base.a[][] = ; base.a[][] = ; base.a[][] = ; base.a[][] = ;
  45. base.a[][] = ; base.a[][] = ; base.a[][] = ;
  46. base.a[][] = ; base.a[][] = ;
  47. base.a[][] = ;
  48. while (T--) {
  49. int n, a, b;
  50. scanf("%d%d%d", &n, &a, &b);
  51. if (n == ) {
  52. printf("%d\n", a);
  53. continue;
  54. }
  55. if (n == ) {
  56. printf("%d\n", b);
  57. continue;
  58. }
  59. n--;
  60. n--;
  61. Mat ans;
  62. ans.a[][] = b; ans.a[][] = a; ans.a[][] = ; ans.a[][] = ; ans.a[][] = ; ans.a[][] = ; ans.a[][] = ;
  63. ans = qp(base, n) * ans;
  64. printf("%lld\n", ans.a[][] % MOD);
  65. }
  66. return ;
  67. }

[D. Winning an Auction]

博弈。

$dp[n][a][b]$ 表示当前剩下 $n$ 个物品,第一个人有 $a$ 元钱,第二个人有 $b$ 元钱,第一个人能获得的物品数。

$dp[1][a][b] = [a\leq b]$

消除奇偶性可以通过从 $dp[i - 1][b][a]$ 转移过来。这样就不用考虑奇偶了。

然后枚举两个人分别要出多少钱,当第一个人出 $x$ 块钱,第二个人出 $x+1$ 块钱会使第一个人的收益变小,那么第二个人会继续加价。同理第一个人会继续加价。当无法得到更好的收益的时候就停下来。

  1. #include <cstdio>
  2. #include <algorithm>
  3. #include <cstring>
  4.  
  5. const int N = ;
  6. short dp[N][N][N];
  7.  
  8. int n, T, a, b;
  9.  
  10. inline int geta(int n, int a) {
  11. return n / * a + (n - n / ) * (a + );
  12. }
  13.  
  14. int main() {
  15. for (int a = ; a < N; a++)
  16. for (int b = ; b < N; b++)
  17. if (a >= b) dp[][a][b] = ;
  18. for (int i = ; i < N; i++) {
  19. for (int a = ; a < N; a++) {
  20. int limit = std::min(N, geta(i, a));
  21. for (int b = ; b < limit; b++) {
  22. if (a == b) {
  23. dp[i][a][b] = (i + ) / ;
  24. continue;
  25. }
  26. int vala = i - dp[i - ][b][a];
  27. int valb = ;
  28. for (int u = ; ; u++) {
  29. if (b < u || (valb = (i - - dp[i - ][b - u][a])) >= vala) {
  30. dp[i][a][b] = vala;
  31. break;
  32. }
  33. if (a < u || (vala = (i - dp[i - ][b][a - u])) <= valb) {
  34. dp[i][a][b] = valb;
  35. break;
  36. }
  37. }
  38. }
  39. }
  40. }
  41. scanf("%d", &T);
  42. while (T--) {
  43. scanf("%d%d%d", &n, &a, &b);
  44. int ans1 = dp[n][a][b], ans2 = n - ans1;
  45. printf("Alice %d Bob %d\n", ans1, ans2);
  46. }
  47. return ;
  48. }

[E. Counting Cliques]

经过暑假牛客多校的洗礼,看到团就想到暴搜...

首先用了bfs+bitset。T了。

改成vector判,又T了。

看了一份题解是dfs,存团的是数组。

我把那份代码的数组改成vector,还是T。

这么卡STL的吗...

  1. #include <bits/stdc++.h>
  2.  
  3. const int N = ;
  4. std::vector<int> G[N];
  5. bool mp[N][N];
  6.  
  7. int ans, n, m, s;
  8.  
  9. void solve(int *a, int u) {
  10. if (a[] == s) {
  11. ans++;
  12. return;
  13. }
  14. for (int v: G[u]) {
  15. if (v <= u) continue;
  16. bool flag = ;
  17. for (int j = ; j <= a[]; j++) {
  18. if (!mp[a[j]][v]) {
  19. flag = ;
  20. break;
  21. }
  22. }
  23. if (!flag) continue;
  24. a[++a[]] = v;
  25. solve(a, v);
  26. --a[];
  27. }
  28. }
  29.  
  30. int a[N];
  31.  
  32. int main() {
  33. int T;
  34. scanf("%d", &T);
  35. while (T--) {
  36. scanf("%d%d%d", &n, &m, &s);
  37. for (int i = ; i <= n; i++) {
  38. G[i].clear();
  39. for (int j = ; j <= n; j++)
  40. mp[i][j] = ;
  41. a[i] = ;
  42. }
  43. for (int i = ; i < m; i++) {
  44. int u, v;
  45. scanf("%d%d", &u, &v);
  46. if (u > v) std::swap(u, v);
  47. G[u].push_back(v);
  48. mp[u][v] = mp[v][u] = ;
  49. }
  50. ans = ;
  51. for (int i = ; i <= n; i++) {
  52. a[] = ;
  53. a[] = i;
  54. solve(a, i);
  55. }
  56. printf("%d\n", ans);
  57. }
  58. return ;
  59. }

[G. Do not pour out]

积分题。

看的这篇 https://www.cnblogs.com/chen9510/p/7635679.html

  1. #include <bits/stdc++.h>
  2.  
  3. const double pi = acos(-1.0);
  4. const double eps = 1e-;
  5.  
  6. inline int dcmp(double x) {
  7. if (fabs(x) < eps) return ;
  8. return x < ? - : ;
  9. }
  10.  
  11. double cal(double x) {
  12. return sin(x) - x * cos(x) - / 3.0 * sin(x) * sin(x) * sin(x);
  13. }
  14.  
  15. double calV(double mid) {
  16. double V = cal(acos(1.0)) - cal(acos(1.0 - mid));
  17. V *= -2.0 / mid;
  18. return V;
  19. }
  20.  
  21. double cal2(double x) {
  22. return x + sin( * x) / ;
  23. }
  24.  
  25. double area(double a, double x) {
  26. return (cal2(pi / 2.0) - cal2(asin(x / a))) * a;
  27. }
  28.  
  29. int main() {
  30. int T;
  31. scanf("%d", &T);
  32. while (T--) {
  33. double d;
  34. scanf("%lf", &d);
  35. if (dcmp(d - ) >= ) {
  36. double h = - * d;
  37. double a = sqrt( * + h * h) / ;
  38. printf("%.5f\n", pi * a);
  39. continue;
  40. }
  41. if (dcmp(d) == ) {
  42. puts("0.00000");
  43. continue;
  44. }
  45. double l = , r = 2.0;
  46. for (int i = ; i < ; i++) {
  47. double mid = (l + r) / 2.0;
  48. double V = calV(mid);
  49. if (dcmp(V - pi * d) == ) break;
  50. if (dcmp(V - pi * d) < ) l = mid;
  51. else r = mid;
  52. }
  53. double mid = l;
  54.  
  55. int flag = ;
  56. if (mid < ) flag = -;
  57. double len = sqrt(mid * mid + );
  58. double h = sqrt( - ( - mid) * ( - mid));
  59. double a = len / ( + flag * sqrt( - h * h));
  60. double x = a - len;
  61. printf("%.5f\n", area(a, x));
  62. }
  63. }

[H. Guessing the Dice Roll]

先把AC自动机建出来。在AC自动机上DP。

$dp[i] = \sum \frac{1}{6} \times dp[from]$

$from$ 为能转到 $i$ 且不为某个串的结尾的结点

因为会存在环,所以高斯消元就行了。

  1. #include <bits/stdc++.h>
  2.  
  3. const int N = + ;
  4.  
  5. double mat[N][N];
  6. const double eps = 1e-;
  7.  
  8. inline void gauss(int n) {
  9. for(int i = ; i <= n; i++) {
  10. int r = i;
  11. for(int j = i + ; j <= n; j++)
  12. if(std::fabs(mat[r][i]) < std::fabs(mat[j][i]))
  13. r = j;
  14. if(r != i) std::swap(mat[i], mat[r]);
  15. for(int j = ; j <= n; j++) {
  16. if(j == i) continue;
  17. double t = mat[j][i] / mat[i][i];
  18. for(int k = i; k <= n + ; k++)
  19. mat[j][k] -= mat[i][k] * t;
  20. }
  21. }
  22. for(int i = ; i <= n; i++) {
  23. mat[i][n + ] /= mat[i][i];
  24. }
  25. }
  26.  
  27. struct Aho {
  28. static const int sz = ;
  29. int ch[N][sz], last[N], fail[N], tol;
  30. bool end[N];
  31. void init() {
  32. tol = ;
  33. newnode();
  34. }
  35. inline int newnode() {
  36. memset(ch[tol], , sizeof(ch[tol]));
  37. last[tol] = fail[tol] = end[tol] = ;
  38. return tol++;
  39. }
  40. void insert(int *a, int n) {
  41. int u = ;
  42. for (int i = ; i < n; i++) {
  43. int id = a[i] - ;
  44. if (!ch[u][id]) ch[u][id] = newnode();
  45. u = ch[u][id];
  46. }
  47. end[u] = ;
  48. }
  49. void build() {
  50. std::queue<int> que;
  51. for (int i = ; i < sz; i++)
  52. if (ch[][i]) que.push(ch[][i]), fail[ch[][i]] = last[ch[][i]] = ;
  53. while (!que.empty()) {
  54. int u = que.front(); que.pop();
  55. end[u] |= end[last[u]];
  56. for (int i = ; i < sz; i++) {
  57. int &v = ch[u][i];
  58. if (v) {
  59. fail[v] = ch[fail[u]][i];
  60. que.push(v);
  61. last[v] = end[fail[v]] ? fail[v] : last[fail[v]];
  62. } else {
  63. v = ch[fail[u]][i];
  64. }
  65. }
  66. }
  67. }
  68. void solve() {
  69. memset(mat, , sizeof(mat));
  70. mat[][tol] = -1.0;
  71. for (int i = ; i < tol; i++) {
  72. mat[i][i] = -1.0;
  73. if (end[i]) continue;
  74. for (int j = ; j < sz; j++)
  75. mat[ch[i][j]][i] += 1.0 / ;
  76. }
  77. gauss(tol - );
  78. bool flag = ;
  79. for (int i = ; i < tol; i++)
  80. if (end[i]) {
  81. if (flag) putchar(' ');
  82. printf("%.6f", mat[i][tol]);
  83. flag = ;
  84. }
  85. puts("");
  86. }
  87. } ac;
  88.  
  89. int a[];
  90.  
  91. int main() {
  92. int T;
  93. scanf("%d", &T);
  94. for (; T--; ) {
  95. int n, l;
  96. scanf("%d%d", &n, &l);
  97. ac.init();
  98. for (int i = ; i <= n; i++) {
  99. for (int j = ; j < l; j++)
  100. scanf("%d", a + j);
  101. ac.insert(a, l);
  102. }
  103. ac.build();
  104. ac.solve();
  105. }
  106. return ;
  107. }

[I. The Elder]

$dp[u] = min(dp[anc] + (sum[u] - sum[anc])^2 + p)$

$anc$ 为 $u$ 到根的路径上的结点。

斜率优化DP一下。在进入一个结点时存储一下对当前队列的修改,离开一个结点时改回去,这样就能保证进入一个结点时,队列存储的都是它的祖先。

  1. #include <bits/stdc++.h>
  2. #define pii pair<int, int>
  3. #define ll long long
  4. #define fi first
  5. #define se second
  6.  
  7. const int N = 1e5 + ;
  8. const double eps = 1e-;
  9. ll dp[N];
  10. int n, p, que[N], l, r;
  11. ll sum[N];
  12. std::vector<std::pii> G[N];
  13.  
  14. inline ll sqr(ll x) {
  15. return x * x;
  16. }
  17.  
  18. inline ll up(int i, int j) {
  19. return dp[i] + sqr(sum[i]) - dp[j] - sqr(sum[j]);
  20. }
  21.  
  22. inline ll down(int i, int j) {
  23. return sum[i] - sum[j];
  24. }
  25.  
  26. ll ans;
  27.  
  28. void dfs(int u, int fa = ) {
  29. std::vector<std::pii> vec;
  30. int x = l, y = r;
  31. while (l < r && up(que[l + ], que[l]) <= down(que[l + ], que[l]) * * sum[u]) {
  32. vec.push_back(std::pii(l, que[l]));
  33. l++;
  34. }
  35. if (u != ) {
  36. dp[u] = dp[que[l]] + sqr(sum[u] - sum[que[l]]) + p;
  37. ans = std::max(ans, dp[u]);
  38. }
  39. while (l < r && up(que[r], que[r - ]) * down(u, que[r]) >= up(u, que[r]) * down(que[r], que[r - ])) {
  40. vec.push_back(std::pii(r, que[r]));
  41. r--;
  42. }
  43. que[++r] = u;
  44. for (auto v: G[u]) {
  45. if (v.fi == fa) continue;
  46. sum[v.fi] = sum[u] + v.se;
  47. dfs(v.fi, u);
  48. }
  49. l = x, r = y;
  50. for (auto p: vec)
  51. que[p.fi] = p.se;
  52. }
  53.  
  54. int main() {
  55. int T;
  56. scanf("%d", &T);
  57. while (T--) {
  58. scanf("%d%d", &n, &p);
  59. for (int i = ; i <= n; i++)
  60. dp[i] = sum[i] = , G[i].clear();
  61. for (int i = , u, v, w; i < n; i++) {
  62. scanf("%d%d%d", &u, &v, &w);
  63. G[u].push_back(std::pii(v, w));
  64. G[v].push_back(std::pii(u, w));
  65. }
  66. dp[] = -p;
  67. que[l = r = ] = ;
  68. ans = ;
  69. dfs();
  70. printf("%lld\n", ans);
  71. }
  72. return ;
  73. }

[J. Query on a graph]

基环树先找出环,用一个数组 $a$ 记录位置。然后以环上的每个点为根,去bfs非环上的点得到bfs序.

那么对于非环上的点,与他距离不大于 $k$ 的点bfs序连续,对于环上的点,与他距离不大于 $k$ 的点在 $a$ 数组里连续

这样就可以用线段树维护了。

然后就是恶心的细节了。

  1. #include <bits/stdc++.h>
  2. #define ll long long
  3.  
  4. inline void checkmax(int &a, int b) {
  5. if (a < b) a = b;
  6. }
  7.  
  8. inline void checkmin(int &a, int b) {
  9. if (a > b) a = b;
  10. }
  11.  
  12. const int N = 1e5 + ;
  13. std::vector<int> vec[N];
  14. int fa[N], son[N], n, id[N], BCC[N], a[N];
  15. int tol;
  16. bool vis[N];
  17.  
  18. void getBCC(int u, int v) {
  19. for (int i = u; i != v; i = fa[i])
  20. a[BCC[i] = ++a[]] = i;
  21. a[BCC[v] = ++a[]] = v;
  22. }
  23.  
  24. void dfs(int u, int pre) {
  25. vis[u] = ;
  26. for (int v: vec[u]) {
  27. if (v == pre) continue;
  28. if (!vis[v]) {
  29. fa[v] = u;
  30. dfs(v, u);
  31. } else if (!BCC[u]) {
  32. getBCC(u, v);
  33. }
  34. }
  35. }
  36.  
  37. int que[N];
  38. int ls[N], rs[N], lg[N], rg[N];
  39.  
  40. void bfs(int s) {
  41. int h = , t = ;
  42. que[++t] = s;
  43. id[s] = ++tol;
  44. while (h != t) {
  45. int u = que[++h]; ls[u] = tol + ;
  46. for (int v: vec[u])
  47. if (!id[v] && !BCC[v]) {
  48. fa[v] = u;
  49. que[++t] = v;
  50. id[v] = ++tol;
  51. }
  52. rs[u] = tol;
  53. }
  54. for (int i = ; i <= t; i++) {
  55. int u = que[i];
  56. lg[u] = N; rg[u] = -N;
  57. for (int v: vec[u])
  58. if (id[v] > id[u] && !BCC[v])
  59. checkmin(lg[u], ls[v]), checkmax(rg[u], rs[v]);
  60. }
  61. }
  62.  
  63. struct Seg {
  64. #define lp p << 1
  65. #define rp p << 1 | 1
  66. static const int NN = N * ;
  67. ll sum[NN], lazy[NN];
  68. void build(int p, int l, int r) {
  69. sum[p] = lazy[p] = ;
  70. if (l == r) return;
  71. int mid = l + r >> ;
  72. build(lp, l, mid);
  73. build(rp, mid + , r);
  74. }
  75. inline void pushup(int p) {
  76. sum[p] = sum[lp] + sum[rp];
  77. }
  78. inline void tag(int p, int len, ll w) {
  79. lazy[p] += w;
  80. sum[p] += len * w;
  81. }
  82. inline void pushdown(int p, int llen, int rlen) {
  83. if (lazy[p]) {
  84. tag(lp, llen, lazy[p]);
  85. tag(rp, rlen, lazy[p]);
  86. lazy[p] = ;
  87. }
  88. }
  89. void update(int p, int l, int r, int x, int y, int w) {
  90. if (x > r || l > y) return;
  91. if (x <= l && y >= r) {
  92. tag(p, r - l + , w);
  93. return;
  94. }
  95. int mid = l + r >> ;
  96. pushdown(p, mid - l + , r - mid);
  97. if (x <= mid) update(lp, l, mid, x, y, w);
  98. if (y > mid) update(rp, mid + , r, x, y, w);
  99. pushup(p);
  100. }
  101. ll query(int p, int l, int r, int x, int y) {
  102. if (x > r || l > y) return ;
  103. if (x <= l && y >= r) return sum[p];
  104. int mid = l + r >> ;
  105. pushdown(p, mid - l + , r - mid);
  106. ll ans = ;
  107. if (x <= mid) ans += query(lp, l, mid, x, y);
  108. if (y > mid) ans += query(rp, mid + , r, x, y);
  109. return ans;
  110. }
  111. inline int getl(int x) { return (x > ) ? x - : a[]; }
  112. inline int getr(int x) { return (x < a[]) ? x + : ; }
  113. inline void update(int u, int w) { update(, , tol, u, u, w); }
  114. inline ll query(int u) { return query(, , tol, u, u); }
  115. void update(int u, int k, int w) {
  116. update(id[u], w);
  117. if (k >= ) {
  118. update(, , tol, ls[u], rs[u], w);
  119. if (!BCC[u]) update(id[fa[u]], w);
  120. else {
  121. update(id[a[getl(BCC[u])]], w);
  122. update(id[a[getr(BCC[u])]], w);
  123. }
  124. }
  125. if (k >= ) {
  126. update(, , tol, lg[u], rg[u], w);
  127. if (!BCC[u]) {
  128. update(id[u], -w);
  129. update(, , tol, ls[fa[u]], rs[fa[u]], w);
  130. int p = BCC[fa[u]];
  131. if (!p) update(id[fa[fa[u]]], w);
  132. else update(id[a[getl(p)]], w), update(id[a[getr(p)]], w);
  133. } else {
  134. int bl = getl(BCC[u]), br = getr(BCC[u]);
  135. update(, , tol, ls[a[bl]], rs[a[bl]], w);
  136. update(, , tol, ls[a[br]], rs[a[br]], w);
  137. if (getl(bl) != br) update(id[a[getl(bl)]], w);
  138. if (getr(br) != bl && getr(br) != getl(bl)) update(id[a[getr(br)]], w);
  139. }
  140. }
  141. }
  142. ll query(int u, int k) {
  143. ll ans = query(id[u]);
  144. if (k >= ) {
  145. ans += query(, , tol, ls[u], rs[u]);
  146. if (!BCC[u]) ans += query(id[fa[u]]);
  147. else ans += query(id[a[getl(BCC[u])]]) + query(id[a[getr(BCC[u])]]);
  148. }
  149. if (k >= ) {
  150. ans += query(, , tol, lg[u], rg[u]);
  151. if (!BCC[u]) {
  152. ans += query(, , tol, ls[fa[u]], rs[fa[u]]) - query(id[u]);
  153. int p = BCC[fa[u]];
  154. if (!p) ans += query(id[fa[fa[u]]]);
  155. else ans += query(id[a[getl(p)]]) + query(id[a[getr(p)]]);
  156. } else {
  157. int bl = getl(BCC[u]), br = getr(BCC[u]);
  158. ans += query(, , tol, ls[a[bl]], rs[a[bl]]) + query(, , tol, ls[a[br]], rs[a[br]]);
  159. if (getl(bl) != br) ans += query(id[a[getl(bl)]]);
  160. if (getr(br) != bl && getr(br) != getl(bl)) ans += query(id[a[getr(br)]]);
  161. }
  162. }
  163. return ans;
  164. }
  165. } seg;
  166.  
  167. int main() {
  168. freopen("in.txt", "r", stdin);
  169. int T;
  170. scanf("%d", &T);
  171. while (T--) {
  172. scanf("%d", &n);
  173. tol = a[] = ;
  174. for (int i = ; i <= n; i++) {
  175. fa[i] = son[i] = BCC[i] = id[i] = vis[i] = ;
  176. vec[i].clear();
  177. }
  178. for (int i = , u, v; i <= n; i++) {
  179. scanf("%d%d", &u, &v);
  180. vec[u].push_back(v);
  181. vec[v].push_back(u);
  182. }
  183. dfs(, );
  184. for (int i = ; i <= a[]; i++)
  185. bfs(a[i]);
  186. seg.build(, , tol);
  187. int q;
  188. scanf("%d", &q);
  189. while (q--) {
  190. int u, k;
  191. char s[];
  192. scanf("%s%d%d", s, &u, &k);
  193. if (s[] == 'M') {
  194. int d;
  195. scanf("%d", &d);
  196. seg.update(u, k, d);
  197. } else {
  198. printf("%lld\n", seg.query(u, k));
  199. }
  200. }
  201. }
  202. return ;
  203. }

[M. Subsequence]

终于把这道题给补了...比赛前我居然还在搞这些不考的东西

裸 K 短路,并且是有向无环图,求 $T$ 到其他点的最短路拓扑排序就能解决。

求出 $T$ 到其他所有点的最短路树,记 $d[i]$ 为 $i$ 到 $T$ 的最短路。给每一个点分配一个前趋,如果多个相同则选其中一个。(注意有重边时要记录边而不是记录前趋的点!!!)

走 $S$ 到 $T$ 上的树边即为最短路,走一条非树边 $(u, v, c)$ 则会使费用增大 $d[v] + c - d[u]$。记该花费为非树边的费用,显然树边的费用为 $0$。

将一条从 $S$ 到 $T$ 的路径记为其经过的非树边序列 $p$,那么这条路径的权值和即为 $d[s] + \sum_{(u,v,c) \in p} (d[v] + c - d[u])$

求 $k$ 短路即求第 $k$ 小的合法非树边序列费用之和。

合法的非树边序列为相邻两条非树边 $e$,$f$,$e$ 在 $f$ 之前,$head(f)$ 需为 $tail(e)$ 在 $T$ 上的祖先或相同。

用一个堆来存储搜索的状态,当前的非树边权值和为优先级,再存储最后一条非树边的起点。

往后可以有两个决策,一为直接加上最后一条非树边的终点之后的非树边中,权值最小的那个。

二为将最后一条非树边替换为 $u$ 之后的非树边下一条比这条非树边大的。

发现需要用另一个堆维护每个点往后所有的非树边。发现 $u$ 和 $pre[u]$ 大部分非树边相同,只是多了一些以自身为起点的非树边,那么可以可持久化地添加非树边。

可以用可持久化左偏树,虽然论文里说的是它不可完全可持久化。

论文

还是挺好写的,就是在合并的过程中用新的节点来合并。像线段树合并。

  1. #include <bits/stdc++.h>
  2.  
  3. #define pii pair<int, int>
  4. #define fi first
  5. #define se second
  6.  
  7. const int N = 4e5 + ;
  8. const int INF = 0x3f3f3f3f;
  9. template<class T>inline bool chkmin(T &a, const T &b) { return a > b ? a = b, true : false; }
  10. template<class T>inline bool chkmax(T &a, const T &b) { return a < b ? a = b, true : false; }
  11.  
  12. namespace Heap {
  13. struct Node {
  14. int lp, rp, v, dis, val;
  15. } tree[N * ];
  16. int tol, root[N];
  17. int newnode(int x = , int y = ) {
  18. int p = ++tol;
  19. tree[p].val = x, tree[p].v = y;
  20. tree[p].lp = tree[p].rp = ; tree[p].dis = ;
  21. return p;
  22. }
  23. int merge(int p, int q) {
  24. if (!p || !q) return p + q;
  25. if (tree[p].val < tree[q].val) std::swap(p, q);
  26. int x = newnode();
  27. tree[x] = tree[p];
  28. tree[x].rp = merge(tree[x].rp, q);
  29. if (tree[tree[x].lp].dis < tree[tree[x].rp].dis) std::swap(tree[x].lp, tree[x].rp);
  30. tree[x].dis = tree[tree[x].rp].dis + ;
  31. return x;
  32. }
  33. inline void init() {
  34. tol = ;
  35. tree[].dis = -;
  36. }
  37. } using namespace Heap;
  38.  
  39. int n, k, cnt, id[N][], s, t, deg[N];
  40. int head1[N], head2[N], e, d[N];
  41. struct Ed {
  42. int v, ne, c;
  43. } E[N];
  44.  
  45. void add(int u, int v, int c) {
  46. E[cnt].v = v; E[cnt].ne = head1[u]; E[cnt].c = c; head1[u] = cnt++;
  47. E[cnt].v = u; E[cnt].ne = head2[v]; E[cnt].c = c; head2[v] = cnt++;
  48. deg[u]++;
  49. }
  50.  
  51. int Q[N], pre[N];
  52.  
  53. int topo(int S, int *head) {
  54. int l = , r = ;
  55. Q[r++] = S;
  56. d[S] = ;
  57. while (l <= r) {
  58. int u = Q[l++];
  59. for (int i = head[u]; ~i; i = E[i].ne) {
  60. int v = E[i].v;
  61. if (chkmax(d[v], d[u] + E[i].c)) pre[v] = i;
  62. if (!--deg[v]) Q[r++] = v;
  63. }
  64. }
  65. return r;
  66. }
  67.  
  68. int solve() {
  69. scanf("%d%d", &n, &k);
  70. cnt = e = ;
  71. init();
  72. for (int i = ; i <= n; i++)
  73. id[i][] = ++e, id[i][] = ++e;
  74. s = ++e, t = ++e;
  75. for (int i = ; i <= e; i++) {
  76. root[i] = ;
  77. d[i] = -INF;
  78. pre[i] = -;
  79. deg[i] = ;
  80. head1[i] = head2[i] = -;
  81. }
  82. for (int i = ; i < n; i++) {
  83. int a, b, c;
  84. scanf("%d%d%d", &a, &b, &c);
  85. add(id[i][], id[i + ][c], a);
  86. add(id[i][], id[i + ][c], b);
  87. add(id[i][], id[i + ][], );
  88. add(id[i][], id[i + ][], );
  89. }
  90. add(s, id[][], );
  91. add(id[n][], t, );
  92. add(id[n][], t, );
  93. int m = topo(t, head2);
  94. if (k == ) return d[s];
  95. for (int j = ; j < m; j++) {
  96. int u = Q[j];
  97. for (int i = head1[u]; ~i; i = E[i].ne) {
  98. int v = E[i].v;
  99. if (d[v] == INF || (i ^ ) == pre[u]) continue;
  100. root[u] = merge(root[u], newnode(d[v] + E[i].c - d[u], v));
  101. }
  102. if (~pre[u]) root[u] = merge(root[u], root[E[pre[u] ^ ].v]);
  103. }
  104. std::priority_queue<std::pii> que;
  105. que.push(std::pii(d[s] + tree[root[s]].val, root[s]));
  106. for (k -= ; k; k--) {
  107. auto p = que.top(); que.pop();
  108. int i = p.se, j = root[tree[i].v];
  109. if (j) que.push(std::pii(p.fi + tree[j].val, j));
  110. if (tree[i].lp) que.push(std::pii(p.fi - tree[i].val + tree[tree[i].lp].val, tree[i].lp));
  111. if (tree[i].rp) que.push(std::pii(p.fi - tree[i].val + tree[tree[i].rp].val, tree[i].rp));
  112. }
  113. return que.top().fi;
  114. }
  115.  
  116. int main() {
  117. freopen("in.txt", "r", stdin);
  118. int T;
  119. scanf("%d", &T);
  120. while (T--) printf("%d\n", solve());
  121. return ;
  122. }

2016 ACM/ICPC亚洲区沈阳站的更多相关文章

  1. 2016 ACM/ICPC亚洲区青岛站现场赛(部分题解)

    摘要 本文主要列举并求解了2016 ACM/ICPC亚洲区青岛站现场赛的部分真题,着重介绍了各个题目的解题思路,结合详细的AC代码,意在熟悉青岛赛区的出题策略,以备战2018青岛站现场赛. HDU 5 ...

  2. 2016 ACM/ICPC亚洲区大连站-重现赛 解题报告

    任意门:http://acm.hdu.edu.cn/showproblem.php?pid=5979 按AC顺序: I - Convex Time limit    1000 ms Memory li ...

  3. 2016 ACM/ICPC亚洲区大连站 F - Detachment 【维护前缀积、前缀和、二分搜索优化】

    F - Detachment In a highly developed alien society, the habitats are almost infinite dimensional spa ...

  4. 2016 ACM/ICPC亚洲区青岛站

    A B C D E F G H I J K L M O O O O     $\varnothing$     $\varnothing$  $\varnothing$  $\varnothing$  ...

  5. HDU 5950 Recursive sequence 【递推+矩阵快速幂】 (2016ACM/ICPC亚洲区沈阳站)

    Recursive sequence Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Other ...

  6. HDU 5952 Counting Cliques 【DFS+剪枝】 (2016ACM/ICPC亚洲区沈阳站)

    Counting Cliques Time Limit: 8000/4000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) ...

  7. HDU 5948 Thickest Burger 【模拟】 (2016ACM/ICPC亚洲区沈阳站)

    Thickest Burger Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)T ...

  8. HDU 5949 Relative atomic mass 【模拟】 (2016ACM/ICPC亚洲区沈阳站)

    Relative atomic mass Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Oth ...

  9. 2015ACM/ICPC亚洲区沈阳站 Pagodas

    Pagodas Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Sub ...

随机推荐

  1. http与tcp,udp的区别

    1.网络协议的概念 (1)在学习网络课程的时候,老师会讲iso七层模型,有应用层 表示层 会话层 传输层 网络层 数据链路层 物理层,其中http就属于应用层,tcp与udp是属于传输层,如图1.1( ...

  2. .NET Core:过滤器

    过滤器的作用是在 Action 方法执行前或执行后做一些加工处理.使用过滤器可以避免Action方法的重复代码.功能上更贴合业务的使用过滤器. 在Startup中的ConfigureServices方 ...

  3. 深入理解C语言 - 指针使用的常见错误

    在C语言中,指针的重要性不言而喻,但在很多时候指针又被认为是一把双刃剑.一方面,指针是构建数据结构和操作内存的精确而高效的工具.另一方面,它们又很容易误用,从而产生不可预知的软件bug.下面总结一下指 ...

  4. python数据分析开发中的常用整理

    Pandas操作 python使用pandas读取csv import pandas as pd #数据筛选 usetTable = pd.read_csv(filename,header = 0) ...

  5. Unity Shader 屏幕后效果——高斯模糊

    高斯模糊是图像模糊处理中非常经典和常见的一种算法,也是Bloom屏幕效果的基础. 实现高斯模糊同样用到了卷积的概念,关于卷积的概念和原理详见我的另一篇博客: https://www.cnblogs.c ...

  6. AbstractExecutorService源码

    public class RunnableFutureTask { static FinalizableDelegatedExecutorService executorService = (Fina ...

  7. 关于wordpress4.8中的Twenty Seventeen主题的主题选项增加章节的实现

    我这里的wordpress版本是4.8  默认的主题是 Twenty Seventeen 我想实现的事 主题选项的首页  多增加2个章节 默认是只有4个章节  我想在增加2个 到6个 看下实现后的效果 ...

  8. loadrunner:Action.c(4): Error -27796: Failed to connect to server "10.8.251.101:10086": [10060] Connection timed out

    Action.c(4): Error -27796: Failed to connect to server "10.8.251.101:10086": [10060] Conne ...

  9. Form之action提交不刷新不跳转

    <div class="file-box"> <form action="/File/fileUpLoad" id="form1&q ...

  10. centos7 配置nginx vim语法高亮

    看了Nginx核心知识100讲,按照他的做法,没有配置成功,可以使用下面的方法: 下载nginx源码,http://nginx.org/en/download.html 这里下载的是:nginx-1. ...