[关闭]
@ljt12138 2017-04-22T09:33:54.000000Z 字数 26558 阅读 899

[Template]省选复习计划


字符串相关

KMP算法(luogu3375)

740′′

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. const int MAXN = 1000005, MAXM = 1005;
  4. char s1[MAXN], s2[MAXM];
  5. int pi[MAXM];
  6. void kmp_init(int len)
  7. {
  8. pi[0] = pi[1] = 0;
  9. int j = 0;
  10. for (int i = 2; i <= len; i++) {
  11. while (j && s2[j+1] != s2[i]) j = pi[j];
  12. if (s2[j+1] == s2[i]) j++;
  13. pi[i] = j;
  14. }
  15. }
  16. void kmp_match(int len)
  17. {
  18. int j = 0, p = strlen(s2+1);
  19. for (int i = 1; i <= len; i++) {
  20. while (j && s1[i] != s2[j+1]) j = pi[j];
  21. if (s1[i] == s2[j+1]) ++j;
  22. if (j == p) printf("%d\n", i-p+1), j = pi[j];
  23. }
  24. }
  25. int main()
  26. {
  27. scanf("%s", s1+1), scanf("%s", s2+1);
  28. kmp_init(strlen(s2+1));
  29. kmp_match(strlen(s1+1));
  30. for (int i = 1, l = strlen(s2+1); i <= l; i++)
  31. printf("%d ", pi[i]);
  32. return 0;
  33. }

AC自动机(hdu2222)

3242′′

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. const int MAXN = 1000005;
  4. int chl[MAXN][26], fail[MAXN], fin[MAXN], top = 0, root = 0, mak[MAXN];
  5. void push(int &nd, char *str)
  6. {
  7. if (!nd) nd = ++top;
  8. if (*str == '\0') fin[nd]++;
  9. else push(chl[nd][*str-'a'], str+1);
  10. }
  11. struct node {
  12. int to, next;
  13. } edge[MAXN];
  14. int head[MAXN], tp = 0;
  15. void push(int i, int j)
  16. { ++tp, edge[tp] = (node) {j, head[i]}, head[i] = tp; }
  17. queue<int> que;
  18. void init()
  19. {
  20. fail[root] = 0, que.push(root);
  21. while (!que.empty()) {
  22. int tp = que.front(); que.pop();
  23. for (int i = 0; i < 26; i++) {
  24. if (!chl[tp][i]) continue;
  25. int p = fail[tp];
  26. while (p && !chl[p][i]) p = fail[p];
  27. if (p) fail[chl[tp][i]] = chl[p][i];
  28. else fail[chl[tp][i]] = root;
  29. push(fail[chl[tp][i]], chl[tp][i]);
  30. que.push(chl[tp][i]);
  31. }
  32. }
  33. }
  34. void match(int nd, char *str)
  35. {
  36. if (fin[nd]) mak[nd] = 1;
  37. if (*str == '\0') return;
  38. while (nd && !chl[nd][*str-'a']) nd = fail[nd];
  39. if (nd) match(chl[nd][*str-'a'], str+1);
  40. else match(root, str+1);
  41. }
  42. int dp[MAXN], siz[MAXN]; // 两次collect
  43. int dfs1(int nd)
  44. {
  45. if (!nd) return 0;
  46. if (siz[nd] != -1) return siz[nd];
  47. for (int i = 0; i < 26; i++)
  48. mak[nd] |= dfs1(chl[nd][i]);
  49. return siz[nd] = mak[nd];
  50. }
  51. int dfs2(int nd)
  52. {
  53. if (dp[nd] != -1) return dp[nd];
  54. dp[nd] = siz[nd];
  55. for (int i = head[nd]; i; i = edge[i].next) {
  56. int to = edge[i].to;
  57. dp[nd] |= dfs2(to);
  58. }
  59. return dp[nd];
  60. }
  61. char str[MAXN];
  62. int T, n;
  63. void clear()
  64. {
  65. top = root = tp = 0, memset(chl, 0, sizeof chl), memset(fail, 0, sizeof fail);
  66. memset(fin, 0, sizeof fin), memset(mak, 0, sizeof mak);
  67. memset(siz, -1, sizeof siz), memset(dp, -1, sizeof dp);
  68. memset(head, 0, sizeof head);
  69. }
  70. int main()
  71. {
  72. scanf("%d", &T);
  73. while (T--) {
  74. clear();
  75. scanf("%d", &n);
  76. for (int i = 1; i <= n; i++) {
  77. scanf("%s", str);
  78. push(root, str);
  79. }
  80. init();
  81. scanf("%s", str);
  82. match(root, str);
  83. dfs1(root), dfs2(root);
  84. int ans = 0;
  85. for (int i = 1; i <= top; i++)
  86. ans += dfs2(i)*fin[i];
  87. printf("%d\n", ans);
  88. }
  89. return 0;
  90. }

SA

24′′04,然而参考了模板...

第二次1415′′

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. const int MAXN = 1e5+5, N = 1e5;
  4. struct ele {
  5. int k[2], id;
  6. ele(){}
  7. ele(int a, int b, int c) { k[0] = a, k[1] = b, id = c; }
  8. } RE[MAXN], RT[MAXN];
  9. int sa[MAXN], rk[MAXN], height[MAXN], sum[MAXN], n;
  10. char str[MAXN];
  11. void radix_sort()
  12. {
  13. for (int y = 1; y >= 0; y--) {
  14. memset(sum, 0, sizeof sum);
  15. for (int i = 1; i <= n; i++) sum[RE[i].k[y]]++;
  16. for (int i = 1; i <= N; i++) sum[i] += sum[i-1];
  17. for (int i = n; i >= 1; i--) RT[sum[RE[i].k[y]]--] = RE[i];
  18. for (int i = 1; i <= n; i++) RE[i] = RT[i];
  19. }
  20. for (int i = 1; i <= n; i++) {
  21. rk[RE[i].id] = rk[RE[i-1].id];
  22. if (RE[i].k[0] != RE[i-1].k[0] || RE[i].k[1] != RE[i-1].k[1])
  23. rk[RE[i].id]++;
  24. }
  25. }
  26. void calc_sa()
  27. {
  28. for (int i = 1; i <= n; i++) RE[i] = ele(str[i]-'a'+1, 0, i);
  29. radix_sort();
  30. for (int k = 1; k < n; k <<= 1) {
  31. for (int i = 1; i <= n; i++) RE[i] = ele(rk[i], i+k<=n?rk[i+k]:0, i);
  32. radix_sort();
  33. }
  34. for (int i = 1; i <= n; i++) sa[rk[i]] = i;
  35. }
  36. void calc_height()
  37. {
  38. int h = 0;
  39. for (int i = 1; i <= n; i++) {
  40. if (rk[i] == 1) h = 0;
  41. else {
  42. int k = sa[rk[i]-1];
  43. if (--h < 0) h = 0;
  44. while (str[i+h] == str[k+h]) h++;
  45. }
  46. height[rk[i]] = h;
  47. }
  48. }
  49. int main()
  50. {
  51. scanf("%s", str+1);
  52. n = strlen(str+1);
  53. calc_sa(), calc_height();
  54. for (int i = 1; i <= n; i++) printf("%d ", sa[i]); puts("");
  55. for (int i = 2; i <= n; i++) printf("%d ", height[i]);
  56. return 0;
  57. }

SAM

luogu2852
859′′

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. const int MAXN = 40005;
  4. map<int, int> chl[MAXN];
  5. int fa[MAXN], maxl[MAXN], right_siz[MAXN];
  6. int top = 1, root = 1, last = 1;
  7. void push(int x)
  8. {
  9. int p = last, np = ++top; maxl[np] = maxl[p]+1, right_siz[np] = 1;
  10. while (p && !chl[p][x]) chl[p][x] = np, p = fa[p];
  11. if (!p) fa[np] = root;
  12. else {
  13. int q = chl[p][x];
  14. if (maxl[q] == maxl[p] + 1) fa[np] = q;
  15. else {
  16. int nq = ++top; maxl[nq] = maxl[p]+1, chl[nq] = chl[q];
  17. fa[nq] = fa[q], fa[q] = fa[np] = nq;
  18. while (p && chl[p][x] == q) chl[p][x] = nq, p = fa[p];
  19. }
  20. }
  21. last = np;
  22. }
  23. struct node {
  24. int to, next;
  25. } edge[MAXN];
  26. int head[MAXN], tp = 0;
  27. void push(int i, int j)
  28. { ++tp, edge[tp] = (node){j, head[i]}, head[i] = tp; }
  29. int n, k, ans = 0;
  30. void dfs(int nd)
  31. {
  32. for (int i = head[nd]; i; i = edge[i].next) {
  33. dfs(edge[i].to);
  34. right_siz[nd] += right_siz[edge[i].to];
  35. }
  36. if (right_siz[nd] >= k) ans = max(ans, maxl[nd]);
  37. }
  38. int main()
  39. {
  40. scanf("%d%d", &n, &k);
  41. for (int i = 1; i <= n; i++) {
  42. int u; scanf("%d", &u);
  43. push(u);
  44. }
  45. for (int i = 2; i <= top; i++) push(fa[i], i);
  46. dfs(root);
  47. cout << ans << endl;
  48. return 0;
  49. }

bzoj3238: [Ahoi2013]差异

30。因为longlong WA了一次。
后缀自动机parent树=逆序后缀树,后缀长度=maxl[nd]

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. const int MAXN = 500005*2;
  4. int chl[MAXN][26], fa[MAXN], maxl[MAXN];
  5. long long right_siz[MAXN];
  6. int top = 1, root = 1, last = 1;
  7. void push(int x)
  8. {
  9. int p = last, np = ++top; maxl[np] = maxl[p]+1, right_siz[np] = 1;
  10. while (p && !chl[p][x]) chl[p][x] = np, p = fa[p];
  11. if (!p) fa[np] = root;
  12. else {
  13. int q = chl[p][x];
  14. if (maxl[q] == maxl[p] + 1) fa[np] = q;
  15. else {
  16. int nq = ++top; maxl[nq] = maxl[p]+1;
  17. memcpy(chl[nq], chl[q], sizeof chl[q]);
  18. fa[nq] = fa[q], fa[q] = fa[np] = nq;
  19. while (p && chl[p][x] == q) chl[p][x] = nq, p = fa[p];
  20. }
  21. }
  22. last = np;
  23. }
  24. struct node {
  25. int to, next;
  26. } edge[MAXN];
  27. int head[MAXN], tp = 0;
  28. void push(int i, int j)
  29. { edge[++tp] = (node) {j, head[i]}, head[i] = tp; }
  30. char str[MAXN];
  31. long long dfs(int nd)
  32. {
  33. long long ans = 0, beg = right_siz[nd];
  34. for (int i = head[nd]; i; i = edge[i].next)
  35. ans += dfs(edge[i].to), right_siz[nd] += right_siz[edge[i].to];
  36. for (int i = head[nd]; i; i = edge[i].next) {
  37. int to = edge[i].to;
  38. ans += right_siz[to]*(right_siz[nd]-right_siz[to])*maxl[nd];
  39. }
  40. ans += beg*(right_siz[nd]-beg)*maxl[nd];
  41. return ans;
  42. }
  43. void init()
  44. {
  45. scanf("%s", str+1);
  46. int n = strlen(str+1);
  47. for (int i = n; i >= 1; i--)
  48. push(str[i]-'a');
  49. for (int i = 2; i <= top; i++) push(fa[i], i);
  50. long long ans = 0;
  51. for (int i = 1; i <= n; i++) ans += (long long)(n-i)*(n-i+1ll)+(long long)(1ll+n-i)*(n-i)/2;
  52. cout << ans-dfs(root) << endl;
  53. }
  54. int main()
  55. {
  56. init();
  57. return 0;
  58. }

树相关

树上倍增

NOIP2013 货车运输

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. const int MAXN = 10005, MAXM = 100005;
  4. struct p {
  5. int x, y, d;
  6. friend bool operator < (const p &a, const p &b)
  7. { return a.d > b.d; }
  8. } edge_arr[MAXN];
  9. struct node {
  10. int to, next, dis;
  11. } edge[MAXN];
  12. int head[MAXN], top = 0;
  13. void push(int i, int j, int k)
  14. { edge[++top] = (node){j, head[i], k}, head[i] = top; }
  15. int fa[MAXN];
  16. int findf(int nd)
  17. { return fa[nd] ? fa[nd] = findf(fa[nd]) : nd; }
  18. int n, m;
  19. int depth[MAXN], jmp[MAXN][20], min_val[MAXN][20], vis[MAXN];
  20. void dfs(int nd, int f)
  21. {
  22. jmp[nd][0] = f, depth[nd] = depth[f] + 1;
  23. for (int j = head[nd]; j; j = edge[j].next) {
  24. int to = edge[j].to, d = edge[j].dis;
  25. if (to == f) continue;
  26. min_val[to][0] = d;
  27. dfs(to, nd);
  28. }
  29. }
  30. void init()
  31. {
  32. for (int j = 1; j < 20; j++)
  33. for (int i = 1; i <= n; i++) {
  34. jmp[i][j] = jmp[jmp[i][j-1]][j-1];
  35. min_val[i][j] = min(min_val[i][j-1], min_val[jmp[i][j-1]][j-1]);
  36. }
  37. }
  38. int lca(int a, int b)
  39. {
  40. if (depth[a] < depth[b]) swap(a, b);
  41. for (int i = 0, d = depth[a]-depth[b]; i < 20; i++)
  42. if ((1<<i)&d)
  43. a = jmp[a][i];
  44. if (a == b) return a;
  45. for (int i = 19; i >= 0; i--)
  46. if (jmp[a][i] != jmp[b][i])
  47. a = jmp[a][i], b = jmp[b][i];
  48. return jmp[a][0];
  49. }
  50. int query(int a, int b)
  51. {
  52. int c = lca(a, b);
  53. if (findf(a) != findf(b)) return -1;
  54. int ans = INT_MAX;
  55. for (int i = 0, d = depth[a]-depth[c]; i < 20; i++)
  56. if ((1<<i)&d)
  57. ans = min(ans, min_val[a][i]), a = jmp[a][i];
  58. for (int i = 0, d = depth[b]-depth[c]; i < 20; i++)
  59. if ((1<<i)&d)
  60. ans = min(ans, min_val[b][i]), b = jmp[b][i];
  61. return ans;
  62. }
  63. int main()
  64. {
  65. memset(min_val, 127/3, sizeof min_val);
  66. scanf("%d%d", &n, &m);
  67. for (int i = 1; i <= m; i++)
  68. scanf("%d%d%d", &edge_arr[i].x, &edge_arr[i].y, &edge_arr[i].d);
  69. sort(edge_arr+1, edge_arr+m+1);
  70. for (int i = 1; i <= m; i++) {
  71. int u = edge_arr[i].x, v = edge_arr[i].y, d = edge_arr[i].d;
  72. if (findf(u) != findf(v)) {
  73. fa[findf(u)] = findf(v);
  74. push(u, v, d), push(v, u, d);
  75. }
  76. }
  77. depth[0] = 0;
  78. for (int i = 1; i <= n; i++)
  79. if (fa[i] == 0)
  80. dfs(i, 0);
  81. init();
  82. int q; scanf("%d", &q);
  83. for (int i = 1; i <= q; i++) {
  84. int u, v; scanf("%d%d", &u, &v);
  85. printf("%d\n", query(u, v));
  86. }
  87. return 0;
  88. }

树链剖分

luogu模板题
50

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. const int MAXN = 100005;
  4. int lc[MAXN], rc[MAXN], l[MAXN], r[MAXN], root = 0;
  5. long long sum[MAXN], lazy[MAXN], P;
  6. int tp = 0;
  7. void build_tree(int &nd, int opl, int opr)
  8. {
  9. nd = ++tp, l[nd] = opl, r[nd] = opr;
  10. sum[nd] = lazy[nd] = 0;
  11. if (opl < opr)
  12. build_tree(lc[nd], opl, (opl+opr)/2), build_tree(rc[nd], (opl+opr)/2+1, opr);
  13. }
  14. void pdw(int nd)
  15. {
  16. if (!lazy[nd]) return;
  17. if (lc[nd]) lazy[lc[nd]] += lazy[nd];
  18. if (rc[nd]) lazy[rc[nd]] += lazy[nd];
  19. (sum[nd] += lazy[nd]*(r[nd]-l[nd]+1)) %= P;
  20. lazy[nd] = 0;
  21. }
  22. void modify(int nd, int opl, int opr, long long dt)
  23. {
  24. if (opl == l[nd] && opr == r[nd]) (lazy[nd] += dt) %= P;
  25. else {
  26. int mid = (l[nd]+r[nd])/2;
  27. (sum[nd] += (opr-opl+1)*dt) %= P;
  28. if (opr <= mid) modify(lc[nd], opl, opr, dt);
  29. else if (opl >= mid+1) modify(rc[nd], opl, opr, dt);
  30. else modify(lc[nd], opl, mid, dt), modify(rc[nd], mid+1, opr, dt);
  31. }
  32. }
  33. long long query(int nd, int opl, int opr)
  34. {
  35. if (nd) pdw(nd);
  36. if (opl == l[nd] && opr == r[nd]) return sum[nd]%P;
  37. else {
  38. int mid = (l[nd]+r[nd])/2;
  39. if (opr <= mid) return query(lc[nd], opl, opr);
  40. else if (opl >= mid+1) return query(rc[nd], opl, opr);
  41. else return (query(lc[nd], opl, mid)+query(rc[nd], mid+1, opr))%P;
  42. }
  43. }
  44. struct node {
  45. int to, next;
  46. } edge[MAXN*2];
  47. int head[MAXN], top = 0;
  48. void push(int i, int j)
  49. { edge[++top] = (node) {j, head[i]}, head[i] = top; }
  50. int n, m, rt;
  51. int siz[MAXN], id[MAXN], out[MAXN], ind[MAXN], rk[MAXN], depth[MAXN];
  52. int id_in_ds = 0;
  53. int fa[MAXN][21];
  54. void dfs(int nd, int f)
  55. {
  56. fa[nd][0] = f, siz[nd] = 1, depth[nd] = depth[f] + 1;
  57. for (int i = head[nd]; i; i = edge[i].next) {
  58. int to = edge[i].to;
  59. if (to == f) continue;
  60. dfs(to, nd), siz[nd] += siz[to];
  61. }
  62. }
  63. void dfs2(int nd, int from)
  64. {
  65. id[nd] = ++id_in_ds, ind[nd] = from;
  66. modify(root, id[nd], id[nd], rk[nd]);
  67. int hev = 0;
  68. for (int i = head[nd]; i; i = edge[i].next) {
  69. int to = edge[i].to;
  70. if (depth[to] < depth[nd]) continue;
  71. if (siz[to] > siz[hev]) hev = to;
  72. }
  73. if (!hev) { out[nd] = id_in_ds; return; }
  74. dfs2(hev, from);
  75. for (int i = head[nd]; i; i = edge[i].next) {
  76. int to = edge[i].to;
  77. if (depth[to] < depth[nd]) continue;
  78. if (to != hev) dfs2(to, to);
  79. }
  80. out[nd] = id_in_ds;
  81. }
  82. void init()
  83. {
  84. for (int j = 1; j <= 20; j++)
  85. for (int i = 1; i <= n; i++)
  86. fa[i][j] = fa[fa[i][j-1]][j-1];
  87. }
  88. int lca(int a, int b)
  89. {
  90. if (depth[a] < depth[b]) swap(a, b);
  91. for (int d = depth[a]-depth[b], i = 0; i <= 20; i++)
  92. if (d&(1<<i))
  93. a = fa[a][i];
  94. if (a == b) return a;
  95. for (int i = 20; i >= 0; i--)
  96. if (fa[a][i] != fa[b][i])
  97. a = fa[a][i], b = fa[b][i];
  98. return fa[a][0];
  99. }
  100. void add_path(int a, long long dt) // a到根
  101. {
  102. while (a) {
  103. modify(root, id[ind[a]], id[a], dt);
  104. a = fa[ind[a]][0];
  105. }
  106. }
  107. void add_son(int a, int dt)
  108. { modify(root, id[a], out[a], dt); }
  109. long long query_path(int a) //
  110. {
  111. long long ans = 0;
  112. while (a) {
  113. (ans += query(root, id[ind[a]], id[a])) %= P;
  114. a = fa[ind[a]][0];
  115. }
  116. return ans;
  117. }
  118. long long query_son(int a)
  119. { return query(root, id[a], out[a]); }
  120. int main()
  121. {
  122. scanf("%d%d%d%lld", &n, &m, &rt, &P);
  123. for (int i = 1; i <= n; i++) scanf("%d", &rk[i]);
  124. build_tree(root, 1, n);
  125. for (int i = 1; i < n; i++) {
  126. int u, v; scanf("%d%d", &u, &v);
  127. push(u, v), push(v, u);
  128. }
  129. depth[rt] = 0, dfs(rt, 0);
  130. dfs2(rt, rt);
  131. init();
  132. for (int i = 1; i <= m; i++) {
  133. int tp, x, y;
  134. long long z;
  135. scanf("%d", &tp);
  136. if (tp == 1) {
  137. scanf("%d%d%lld", &x, &y, &z);
  138. int c = lca(x, y);
  139. add_path(x, z), add_path(y, z);
  140. add_path(c, -2*z);
  141. modify(root, id[c], id[c], z);
  142. } else if (tp == 2) {
  143. scanf("%d%d", &x, &y);
  144. int c = lca(x, y);
  145. printf("%lld\n", ((query_path(x)+query_path(y)-2*query_path(c)+query(root, id[c], id[c]))%P+P)%P);
  146. } else if (tp == 3) {
  147. scanf("%d%lld", &x, &z);
  148. add_son(x, z);
  149. } else if (tp == 4) {
  150. scanf("%d", &x);
  151. printf("%lld\n", query_son(x));
  152. } else throw;
  153. }
  154. return 0;
  155. }

dfs序

bzoj4034: [HAOI2015]树上操作
这个题其实树剖很好写,不过dfs序的思路太神辣所以必须发...http://www.cnblogs.com/liyinggang/p/5965981.html

pdw写错+10086...
虽然dfs序理论复杂度O(nlgn)但是由于写法太渣跑的还没有链剖快...

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. const int MAXN = 100005*8;
  4. int n, m;
  5. int lc[MAXN], rc[MAXN], l[MAXN], r[MAXN];
  6. long long sum[MAXN], lazy[MAXN];
  7. long long num[MAXN], num_tmp[MAXN];
  8. int root = 0, top_ds = 0;
  9. void build(int &nd, int opl, int opr)
  10. {
  11. nd = ++top_ds, sum[nd] = 0;
  12. l[nd] = opl, r[nd] = opr;
  13. if (opl < opr) {
  14. build(lc[nd], opl, (opl+opr)/2);
  15. build(rc[nd], (opl+opr)/2+1, opr);
  16. num[nd] = num[lc[nd]] + num[rc[nd]];
  17. } else num[nd] = num_tmp[opl];
  18. }
  19. void pdw(int nd)
  20. {
  21. if (!lazy[nd]) return;
  22. sum[nd] += num[nd]*lazy[nd];
  23. if (lc[nd]) lazy[lc[nd]] += lazy[nd];
  24. if (rc[nd]) lazy[rc[nd]] += lazy[nd];
  25. lazy[nd] = 0;
  26. }
  27. void modify(int nd, int opl, int opr, long long dat)
  28. {
  29. if (opl == l[nd] && opr == r[nd]) lazy[nd] += dat, pdw(nd);
  30. else {
  31. pdw(nd);
  32. int mid = (l[nd]+r[nd])>>1;
  33. if (opr <= mid) modify(lc[nd], opl, opr, dat);
  34. else if (opl >= mid+1) modify(rc[nd], opl, opr, dat);
  35. else modify(lc[nd], opl, mid, dat), modify(rc[nd], mid+1, opr, dat);
  36. pdw(lc[nd]), pdw(rc[nd]);
  37. sum[nd] = sum[lc[nd]] + sum[rc[nd]];
  38. }
  39. }
  40. void display(int nd, int tab)
  41. {
  42. if (!nd) return;
  43. for (int i = 1; i <= tab; i++) putchar(' ');
  44. printf("[%d,%d] --> sum = %lld, lazy = %lld, num = %lld\n", l[nd], r[nd], sum[nd], lazy[nd], num[nd]);
  45. display(lc[nd], tab+2);
  46. display(rc[nd], tab+2);
  47. }
  48. long long query(int nd, int opl, int opr)
  49. {
  50. pdw(nd);
  51. if (opl == l[nd] && opr == r[nd]) return sum[nd];
  52. else {
  53. int mid = (l[nd]+r[nd])>>1;
  54. if (opr <= mid) return query(lc[nd], opl, opr);
  55. else if (opl >= mid+1) return query(rc[nd], opl, opr);
  56. else return query(lc[nd], opl, mid)+query(rc[nd], mid+1, opr);
  57. }
  58. }
  59. struct node {
  60. int to, next;
  61. } edge[MAXN];
  62. int head[MAXN], top = 0;
  63. void push(int i, int j)
  64. { edge[++top] = (node) {j, head[i]}, head[i] = top; }
  65. int in[MAXN], out[MAXN], ds_top = 0;
  66. int rk[MAXN];
  67. void dfs(int nd, int f)
  68. {
  69. in[nd] = ++ds_top; num_tmp[in[nd]] = 1;
  70. for (int i = head[nd]; i; i = edge[i].next) {
  71. int to = edge[i].to;
  72. if (to == f) continue;
  73. dfs(to, nd);
  74. }
  75. out[nd] = ++ds_top; num_tmp[out[nd]] = -1;
  76. }
  77. void modify_point(int nd, long long dt)
  78. {
  79. modify(root, in[nd], in[nd], dt);
  80. modify(root, out[nd], out[nd], dt);
  81. }
  82. void modify_tree(int nd, long long dt)
  83. { modify(root, in[nd], out[nd], dt); }
  84. long long query_path(int nd)
  85. { return query(root, in[1], in[nd]); }
  86. int main()
  87. {
  88. scanf("%d%d", &n, &m);
  89. for (int i = 1; i <= n; i++) scanf("%d", &rk[i]);
  90. for (int i = 1; i < n; i++) {
  91. int u, v; scanf("%d%d", &u, &v);
  92. push(u, v), push(v, u);
  93. }
  94. dfs(1, 0);
  95. build(root, 1, 2*n);
  96. for (int i = 1; i <= n; i++) {
  97. modify_point(i, rk[i]);
  98. }
  99. for (int i = 1; i <= m; i++) {
  100. int tp, a;
  101. long long b;
  102. scanf("%d", &tp);
  103. if (tp == 1) {
  104. scanf("%d%lld", &a, &b);
  105. modify_point(a, b);
  106. } else if (tp == 2) {
  107. scanf("%d%lld", &a, &b);
  108. modify_tree(a, b);
  109. } else {
  110. scanf("%d", &a);
  111. printf("%lld\n", query_path(a));
  112. }
  113. }
  114. return 0;
  115. }

lct

bzoj3832 Tree
http://hzwer.com/4422.html

1.5h,脑残原因:zig的时候先修改了p的fa,才判断is_rt(p)...

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. const int MAXN = 500005;
  4. int chl[MAXN][2], fa[MAXN], dat[MAXN], sum[MAXN], top = 0;
  5. int rev[MAXN], stk[MAXN], stop = 0, n, m;
  6. bool is_rt(int nd)
  7. { return chl[fa[nd]][0] != nd && chl[fa[nd]][1] != nd; }
  8. void pdw(int nd)
  9. {
  10. if (!rev[nd]) return;
  11. int &lc = chl[nd][0], &rc = chl[nd][1];
  12. if (lc) rev[lc] ^= 1;
  13. if (rc) rev[rc] ^= 1;
  14. swap(lc, rc), rev[nd] = 0;
  15. }
  16. inline void update(int nd)
  17. {
  18. sum[nd] = dat[nd]^sum[chl[nd][0]]^sum[chl[nd][1]];
  19. }
  20. void zig(int nd)
  21. {
  22. int p = fa[nd], g = fa[p];
  23. int tp = chl[p][0] != nd, tg = chl[g][0] != p;
  24. int son = chl[nd][tp^1];
  25. if (!is_rt(p)) chl[g][tg] = nd;
  26. fa[son] = p, fa[p] = nd, fa[nd] = g;
  27. chl[nd][tp^1] = p, chl[p][tp] = son;
  28. update(p), update(nd);
  29. }
  30. void splay(int nd)
  31. {
  32. stk[stop = 1] = nd;
  33. for (int i = nd; !is_rt(i); i = fa[i]) stk[++stop] = fa[i];
  34. while (stop) pdw(stk[stop--]);
  35. while (!is_rt(nd)) {
  36. int p = fa[nd], g = fa[p], tp = chl[p][0] != nd, tg = chl[g][0] != p;
  37. if (is_rt(p)) { zig(nd); break; }
  38. else if (tp == tg) zig(p), zig(nd);
  39. else zig(nd), zig(nd);
  40. }
  41. }
  42. void access(int x)
  43. {
  44. for (int y = 0; x; x = fa[y = x])
  45. splay(x), chl[x][1] = y, update(x);
  46. }
  47. void make_rt(int x)
  48. {
  49. access(x), splay(x);
  50. rev[x] ^= 1;
  51. }
  52. int find_fa(int x)
  53. {
  54. access(x), splay(x);
  55. while (chl[x][0]) {
  56. if (x == chl[x][0]) throw;
  57. x = chl[x][0];
  58. }
  59. return x;
  60. }
  61. void link(int x, int y)
  62. {
  63. if (find_fa(x) == find_fa(y)) return;
  64. make_rt(x), fa[x] = y;
  65. access(x);
  66. }
  67. void cut(int x, int y)
  68. {
  69. if (find_fa(x) != find_fa(y)) return;
  70. make_rt(x);
  71. access(y), splay(y);
  72. if (chl[y][0] == x) chl[y][0] = 0, fa[x] = 0;
  73. }
  74. int query(int x, int y)
  75. {
  76. make_rt(x), access(y), splay(y);
  77. if (find_fa(y) != x) return -1;
  78. return sum[y];
  79. }
  80. void change(int x, int dt)
  81. {
  82. make_rt(x), splay(x), dat[x] = dt, update(x);
  83. }
  84. int main()
  85. {
  86. scanf("%d%d", &n, &m);
  87. for (int i = 1; i <= n; i++) scanf("%d", &dat[i]), update(i);
  88. for (int i = 1; i <= m; i++) {
  89. int tp, x, y;
  90. scanf("%d%d%d", &tp, &x, &y);
  91. if (tp == 0)
  92. printf("%d\n", query(x, y));
  93. else if (tp == 1)
  94. link(x, y);
  95. else if (tp == 2)
  96. cut(x, y);
  97. else change(x, y);
  98. }
  99. return 0;
  100. }

bzoj2843: 极地旅行社

Description

不久之前,Mirko建立了一个旅行社,名叫“极地之梦”。这家旅行社在北极附近购买了N座冰岛,并且提供观光服
务。当地最受欢迎的当然是帝企鹅了,这些小家伙经常成群结队的游走在各个冰岛之间。Mirko的旅行社遭受一次
重大打击,以至于观光游轮已经不划算了。旅行社将在冰岛之间建造大桥,并用观光巴士来运载游客。Mirko希望
开发一个电脑程序来管理这些大桥的建造过程,以免有不可预料的错误发生。这些冰岛从1到N标号。一开始时这些
岛屿没有大桥连接,并且所有岛上的帝企鹅数量都是知道的。每座岛上的企鹅数量虽然会有所改变,但是始终在[0
, 1000]之间。你的程序需要处理以下三种命令:

1."bridge A B"——在A与B之间建立一座大桥(A与B是不同的岛屿)。由于经费限制,这项命令被接受,当且仅当
A与B不联通。若这项命令被接受,你的程序需要输出"yes",之
后会建造这座大桥。否则,你的程序需要输出"no"。
2."penguins A X"——根据可靠消息,岛屿A此时的帝企鹅数量变为X。这项命令只是用来提供信息的,你的程序不
需要回应。
3."excursion A B"——一个旅行团希望从A出发到B。若A与B连通,你的程序需要输出这个旅行团一路上所能看到的
帝企鹅数量(包括起点A与终点B),若不联通,你的程序需要输出"impossible"。

Input

第一行一个正整数N,表示冰岛的数量。
第二行N个范围[0,1000]的整数,为每座岛屿初始的帝企鹅数量。
第三行一个正整数M,表示命令的数量。接下来M行即命令,为题目描述所示。
1<=N<=30000,1<=M<=100000

1604′′

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. const int MAXN = 30005;
  4. int chl[MAXN][2], fa[MAXN], rev[MAXN], stk[MAXN], sum[MAXN], dat[MAXN], top = 0;
  5. inline bool is_rt(int nd)
  6. { return chl[fa[nd]][0] != nd && chl[fa[nd]][1] != nd; }
  7. inline void update(int nd)
  8. { sum[nd] = sum[chl[nd][0]]+sum[chl[nd][1]]+dat[nd]; }
  9. void pdw(int nd)
  10. {
  11. if (!rev[nd]) return;
  12. int &lc = chl[nd][0], &rc = chl[nd][1];
  13. if (lc) rev[lc] ^= 1;
  14. if (rc) rev[rc] ^= 1;
  15. swap(lc, rc), rev[nd] = 0;
  16. }
  17. void zig(int nd)
  18. {
  19. int p = fa[nd], g = fa[p];
  20. int tp = chl[p][0] != nd, tg = chl[g][0] != p, son = chl[nd][tp^1];
  21. if (son) fa[son] = p;
  22. if (!is_rt(p)) chl[g][tg] = nd;
  23. fa[p] = nd, fa[nd] = g;
  24. chl[nd][tp^1] = p, chl[p][tp] = son;
  25. update(p), update(nd);
  26. }
  27. void splay(int nd)
  28. {
  29. stk[top = 1] = nd;
  30. for (int i = nd; !is_rt(i); i = fa[i]) stk[++top] = fa[i];
  31. while (top) pdw(stk[top--]);
  32. while (!is_rt(nd)) {
  33. int p = fa[nd], g = fa[p];
  34. int tp = chl[p][0] != nd, tg = chl[g][0] != p;
  35. if (is_rt(p)) {zig(nd); break; }
  36. else if (tp == tg) zig(p), zig(nd);
  37. else zig(nd), zig(nd);
  38. }
  39. }
  40. void access(int x)
  41. {
  42. for (int y = 0; x; x = fa[y = x])
  43. splay(x), chl[x][1] = y, update(x);
  44. }
  45. void make_rt(int x)
  46. { access(x), splay(x), rev[x] ^= 1; }
  47. int find(int x)
  48. {
  49. access(x), splay(x);
  50. while (chl[x][0]) x = chl[x][0];
  51. return x;
  52. }
  53. void link(int x, int y)
  54. {
  55. if (find(x) == find(y)) return;
  56. make_rt(x), access(x), splay(x);
  57. fa[x] = y;
  58. }
  59. void change(int x, int dt)
  60. { make_rt(x), splay(x), dat[x] = dt, update(x); }
  61. int query(int x, int y)
  62. { return make_rt(x), access(y), splay(y), sum[y]; }
  63. int n, m;
  64. char str[20];
  65. int main()
  66. {
  67. scanf("%d", &n);
  68. for (int i = 1; i <= n; i++) scanf("%d",&dat[i]), update(i);
  69. scanf("%d", &m);
  70. for (int i = 1; i <= m; i++) {
  71. int x, y;
  72. scanf("%s %d %d", str, &x, &y);
  73. if (str[0] == 'e') {
  74. if (find(x) != find(y)) puts("impossible");
  75. else printf("%d\n", query(x, y));
  76. } else if (str[0] == 'p') {
  77. change(x, y);
  78. } else if (str[0] == 'b') {
  79. if (find(x) == find(y)) puts("no");
  80. else
  81. puts("yes"), link(x, y);
  82. }
  83. }
  84. return 0;
  85. }

数据结构

splay

bzoj1269: [AHOI2006]文本编辑器editor
被pdw支配的恐惧...
几个小操作的先后顺序一定要小心小心再小心啊...这次由于先检查siz后pushdown导致1h+调试...
2h

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. const int MAXN = 1024*1024*4;
  4. int chl[MAXN][2], fa[MAXN], dat[MAXN], siz[MAXN], rev[MAXN];
  5. int top = 0, root = 0;
  6. inline void update(int nd)
  7. { if(!nd) return; siz[nd] = siz[chl[nd][0]]+siz[chl[nd][1]]+1; }
  8. int stk[MAXN], skp = 0;
  9. void pdw(int nd)
  10. {
  11. if (!rev[nd]) return;
  12. int &lc = chl[nd][0], &rc = chl[nd][1];
  13. rev[lc] ^= (lc != 0), rev[rc] ^= (rc != 0);
  14. swap(lc, rc), rev[nd] = 0;
  15. }
  16. void zig(int nd)
  17. {
  18. pdw(nd);
  19. int p = fa[nd], g = fa[p];
  20. int tp = chl[p][0] != nd, tg = chl[g][0] != p, son = chl[nd][tp^1];
  21. if (g) chl[g][tg] = nd; else root = nd;
  22. if (son) fa[son] = p;
  23. chl[nd][tp^1] = p, chl[p][tp] = son;
  24. fa[p] = nd, fa[nd] = g;
  25. update(p), update(nd);
  26. }
  27. void splay(int nd, int tar = 0)
  28. {
  29. stk[skp = 1] = nd;
  30. for (int i = nd; fa[i]; i = fa[i]) stk[++skp] = fa[i];
  31. while (skp) pdw(stk[skp--]);
  32. while (fa[nd] != tar) {
  33. int p = fa[nd], g = fa[p];
  34. int tp = chl[p][0] != nd, tg = chl[g][0] != p;
  35. if (g == tar) {zig(nd); break; }
  36. else if (tp == tg) zig(p), zig(nd);
  37. else zig(nd), zig(nd);
  38. }
  39. }
  40. void dfs(int nd, int key)
  41. {
  42. if (!nd) return;
  43. // pdw(nd);
  44. // for (int i = 1; i <= tab; i++) putchar(' ');
  45. printf("nd = %d, lc = %d, rc = %d, dat = %c, fa = %d-- siz = %d, rev = %d\n", nd, chl[nd][0], chl[nd][1], dat[nd], fa[nd], siz[nd], rev[nd]);
  46. dfs(chl[nd][0], key);
  47. // putchar(dat[nd]); if (key == nd) putchar('|');
  48. dfs(chl[nd][1], key);
  49. }
  50. int kth(int k)
  51. {
  52. int nd = root;
  53. while (pdw(nd), siz[chl[nd][0]] != k) {
  54. nd = siz[chl[nd][0]] > k ? chl[nd][0] : (k -= siz[chl[nd][0]]+1, chl[nd][1]);
  55. }
  56. return nd;
  57. }
  58. int rk(int nd)
  59. {
  60. splay(nd);
  61. return siz[chl[nd][0]];
  62. }
  63. int go_prev(int nd)
  64. { return kth(rk(nd)-1); }
  65. int go_next(int nd)
  66. { return kth(rk(nd)+1); }
  67. void print(int nd)
  68. { putchar(dat[go_next(nd)]); puts(""); }
  69. int insert(int nd, int x)
  70. {
  71. int nx = go_next(nd);
  72. splay(nd);
  73. splay(nx, root);
  74. pdw(root), pdw(nx);
  75. chl[nx][0] = ++top, fa[top] = nx, dat[top] = x, update(top), update(nx), update(nd);
  76. return top;
  77. }
  78. void del(int nd, int len)
  79. {
  80. int l = nd, r = kth(rk(nd)+len+1);
  81. splay(l), splay(r, root);
  82. pdw(l), pdw(r);
  83. chl[r][0] = 0, update(r), update(l);
  84. }
  85. int reverse(int nd, int len)
  86. {
  87. int l = nd, r = kth(rk(nd)+len+1), k = rk(nd);
  88. splay(l), splay(r, root);
  89. pdw(l), pdw(r);
  90. rev[chl[r][0]] ^= 1;
  91. return kth(k);
  92. }
  93. int n, k;
  94. char str[20], s[MAXN];
  95. void get_str(char str[])
  96. {
  97. int k = -1, c;
  98. do c = getchar(); while(c < 32 || c > 126);
  99. while (c >= 32 && c <= 126) {
  100. str[++k] = c;
  101. c = getchar();
  102. }
  103. str[++k] = '\0';
  104. }
  105. int main()
  106. {
  107. root = ++top, dat[top] = 0, chl[root][1] = ++top, dat[top] = 1;
  108. fa[top] = top-1;
  109. update(top), update(top-1);
  110. scanf("%d", &n);
  111. int nd = top-1;
  112. for (int i = 1; i <= n; i++) {
  113. scanf("%s", str);
  114. switch(str[0]) {
  115. case 'M': scanf("%d", &k); nd = kth(k); break;
  116. case 'I':
  117. scanf("%d", &k);
  118. get_str(s);
  119. for (int i = 0, x = nd; i < k; i++)
  120. x = insert(x, s[i]);
  121. break;
  122. case 'D': scanf("%d", &k), del(nd, k); break;
  123. case 'R': scanf("%d", &k), nd = reverse(nd, k); break;
  124. case 'G': print(nd); break;
  125. case 'P': nd = go_prev(nd); break;
  126. case 'N': nd = go_next(nd); break;
  127. }
  128. }
  129. return 0;
  130. }

线段树

主席树

无修改区间k大。

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. const int MAXN = 100005, lgn = 21;
  4. int lc[MAXN*lgn], rc[MAXN*lgn], l[MAXN*lgn], r[MAXN*lgn], sum[MAXN*lgn];
  5. int root[MAXN], top = 0;
  6. int n, m;
  7. void build(int &nd, int opl, int opr)
  8. {
  9. nd = ++top;
  10. l[nd] = opl, r[nd] = opr, sum[nd] = 0;
  11. if (opl < opr)
  12. build(lc[nd], opl, (opl+opr)/2), build(rc[nd], (opl+opr)/2+1, opr);
  13. }
  14. void push(int prev, int &nd, int pos)
  15. {
  16. nd = ++top;
  17. l[nd] = l[prev], r[nd] = r[prev];
  18. if (l[prev] == r[prev]) sum[nd] = sum[prev]+1;
  19. else {
  20. int mid = (l[prev]+r[prev])/2;
  21. if (pos <= mid) push(lc[prev], lc[nd], pos), rc[nd] = rc[prev];
  22. else push(rc[prev], rc[nd], pos), lc[nd] = lc[prev];
  23. sum[nd] = sum[lc[nd]]+sum[rc[nd]];
  24. }
  25. }
  26. void dfs(int nd, int tab = 0)
  27. {
  28. if (!nd) return;
  29. for (int i = 1; i <= tab; i++) putchar(' ');
  30. printf("[%d,%d] -- sum = %d\n", l[nd], r[nd], sum[nd]);
  31. dfs(lc[nd], tab+2), dfs(rc[nd], tab+2);
  32. }
  33. int query(int opl, int opr, int k)
  34. {
  35. int i = 1, j = n, mid;
  36. int a = root[opl-1], b = root[opr];
  37. k--;
  38. while (i < j) {
  39. mid = (i+j)>>1;
  40. if (sum[lc[b]]-sum[lc[a]] <= k) k -= sum[lc[b]]-sum[lc[a]], i = mid+1, a = rc[a], b = rc[b];
  41. else j = mid, a = lc[a], b = lc[b];
  42. }
  43. return i;
  44. }
  45. int d[MAXN];
  46. int dx[MAXN];
  47. void dx_init()
  48. {
  49. memcpy(dx, d, sizeof d);
  50. sort(dx+1, dx+n+1);
  51. }
  52. int dx_num(int nd)
  53. { return lower_bound(dx+1, dx+n+1, nd)-dx; }
  54. int main()
  55. {
  56. scanf("%d%d", &n, &m);
  57. build(root[0], 1, n);
  58. for (int i = 1; i <= n; i++)
  59. scanf("%d", &d[i]);
  60. dx_init();
  61. for (int i = 1; i <= n; i++) {
  62. push(root[i-1], root[i], dx_num(d[i]));
  63. }
  64. for (int i = 1; i <= m; i++) {
  65. int u, v, k;
  66. scanf("%d%d%d", &u, &v, &k);
  67. cout << dx[query(u, v, k)] << endl;
  68. }
  69. return 0;
  70. }

其他

FFT

大爷题解:http://www.cnblogs.com/iiyiyi/p/5717520.html

好像把一道好题变成练模板了..之后补分析吧..

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. const int MAXN = 300005;
  4. int rev[MAXN], n;
  5. typedef complex<double> Complex;
  6. Complex A[MAXN];
  7. const double PI = acos(-1);
  8. void fft(Complex a[], int n, int flag)
  9. {
  10. int lgn = int(log2(n)+0.01);
  11. rev[0] = 0;
  12. for (int i = 1; i < n; i++) rev[i] = (rev[i>>1]>>1)|((1<<(lgn-1))*(i&1));
  13. for (int i = 0; i < n; i++) A[i] = a[rev[i]];
  14. for (int k = 2; k <= n; k <<= 1) {
  15. Complex dw = Complex(cos(2*PI/k), flag*sin(2*PI/k));
  16. for (int i = 0; i < n; i += k) {
  17. Complex w = Complex(1, 0), u, v;
  18. for (int j = 0; j < (k>>1); j++) {
  19. u = A[i+j], v = w*A[i+j+(k>>1)];
  20. A[i+j] = u+v, A[i+j+(k>>1)] = u-v;
  21. w *= dw;
  22. }
  23. }
  24. }
  25. for (int i = 0; i < n; i++)
  26. a[i] = A[i]/(flag==1?Complex(1,0):Complex(n,0));
  27. }
  28. long long k[MAXN];
  29. int dat[MAXN];
  30. Complex a[MAXN], b[MAXN], c[MAXN];
  31. int main()
  32. {
  33. scanf("%d", &n);
  34. int N = 1, mx = 0;
  35. for (int i = 0; i < n; i++) {
  36. int t; scanf("%d", &t); dat[i] = t;
  37. mx = max(mx, t);
  38. a[t] += Complex(1, 0);
  39. b[2*t] += Complex(1, 0);
  40. c[3*t] += Complex(1, 0);
  41. }
  42. while (N <= mx*3) N<<=1;
  43. fft(a, N, 1), fft(b, N, 1), fft(c, N, 1);
  44. for (int i = 0; i < N; i++)
  45. a[i]=(a[i]*a[i]*a[i]-Complex(3, 0)*a[i]*b[i]+Complex(2, 0)*c[i])/Complex(6, 0)+(a[i]*a[i]-b[i])/Complex(2, 0)+a[i];
  46. fft(a, N, -1);
  47. for (int i = 0; i < N; i++) {
  48. k[i] += (long long)(a[i].real()+0.1);
  49. }
  50. for (int i = 0; i < N; i++)
  51. if (k[i])
  52. printf("%d %lld\n", i, k[i]);
  53. return 0;
  54. }

Tarjan

bzoj2140 稳定婚姻

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. const int MAXN = 10005, MAXM = 100005;
  4. struct node {
  5. int to, next;
  6. } edge[MAXM];
  7. int head[MAXN], top = 0;
  8. void push(int i, int j)
  9. { edge[++top] = (node){j, head[i]}, head[i] = top; }
  10. int dfn[MAXN], low[MAXN], stk[MAXN], instk[MAXN], stop = 0, dfs_top = 0;
  11. int gp[MAXN], gp_top = 0;
  12. int n, m, strtop = 0;
  13. map<string, int> tab;
  14. string str[MAXN];
  15. string s1, s2;
  16. void tarjan(int nd)
  17. {
  18. stk[++stop] = nd, instk[nd] = 1, dfn[nd] = low[nd] = ++dfs_top;
  19. for (int i = head[nd]; i; i = edge[i].next) {
  20. int to = edge[i].to;
  21. if (!dfn[to]) tarjan(to), low[nd] = min(low[nd], low[to]);
  22. else if (instk[to]) low[nd] = min(low[nd], dfn[to]);
  23. }
  24. if (dfn[nd] == low[nd]) {
  25. int now = 0; gp_top++;
  26. // printf(" -- Group %d --\n", gp_top);
  27. do {
  28. now = stk[stop--];
  29. gp[now] = gp_top;
  30. instk[now] = 0;
  31. // cerr << str[now] << " ";
  32. } while (now != nd);
  33. // puts("");
  34. }
  35. }
  36. int cpx[MAXN], cpy[MAXN];
  37. int main()
  38. {
  39. scanf("%d", &n);
  40. for (int i = 1; i <= n; i++) {
  41. cin >> s1 >> s2;
  42. if (!tab.count(s1)) tab[s1] = ++strtop, str[strtop] = s1;
  43. if (!tab.count(s2)) tab[s2] = ++strtop, str[strtop] = s2;
  44. push(tab[s2], tab[s1]);
  45. cpx[i] = tab[s1], cpy[i] = tab[s2];
  46. }
  47. scanf("%d", &m);
  48. for (int i = 1; i <= m; i++) {
  49. cin >> s1 >> s2;
  50. push(tab[s1], tab[s2]);
  51. }
  52. for (int i = 1; i <= strtop; i++)
  53. if (!dfn[i])
  54. tarjan(i);
  55. for (int i = 1; i <= n; i++)
  56. if (gp[cpx[i]] == gp[cpy[i]])
  57. puts("Unsafe");
  58. else
  59. puts("Safe");
  60. return 0;
  61. }

dinic

CQOI2015 网络吞吐量

spfa居然写跪了...没救了这

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. const int MAXN = 2005, MAXM = 200005;
  4. struct node {
  5. int to, next;
  6. long long flow;
  7. int neg;
  8. } edge[MAXM];
  9. int head[MAXN], top = 0;
  10. void push(int i, int j, long long f)
  11. {
  12. ++top, edge[top] = (node){j, head[i], f, top+1}, head[i] = top;
  13. ++top, edge[top] = (node){i, head[j], 0, top-1}, head[j] = top;
  14. }
  15. const long long inf = 23333333333333ll;
  16. int S, T, n, m;
  17. int lev[MAXN], vis[MAXN], bfstime = 0;
  18. queue<int> que;
  19. bool bfs()
  20. {
  21. que.push(S), lev[S] = 0, vis[S] = ++bfstime;
  22. while (!que.empty()) {
  23. int t = que.front(); que.pop();
  24. for (int i = head[t]; i; i = edge[i].next) {
  25. int to = edge[i].to;
  26. long long d = edge[i].flow;
  27. if (!d || vis[to] == bfstime) continue;
  28. vis[to] = bfstime, que.push(to), lev[to] = lev[t]+1;
  29. }
  30. }
  31. return vis[T] == bfstime;
  32. }
  33. long long dfs(int nd, long long flow = inf)
  34. {
  35. if (!flow || nd == T) return flow;
  36. long long t, ans = 0;
  37. for (int i = head[nd]; i; i = edge[i].next) {
  38. int to = edge[i].to;
  39. long long d = edge[i].flow;
  40. if (!d || lev[to] != lev[nd]+1) continue;
  41. t = dfs(to, min(flow, d));
  42. ans += t, flow -= t;
  43. edge[i].flow -= t, edge[edge[i].neg].flow += t;
  44. }
  45. if (flow) lev[nd] = -1;
  46. return ans;
  47. }
  48. long long dinic()
  49. {
  50. long long ans = 0;
  51. while (bfs()) ans += dfs(S);
  52. return ans;
  53. }
  54. long long dis[MAXN];
  55. int inq[MAXN];
  56. long long rk[MAXN];
  57. node g2[MAXM];
  58. int h2[MAXN], tp = 0;
  59. void push2(int i, int j, long long k)
  60. { ++tp, g2[tp] = (node){j, h2[i], k, 0}, h2[i] = tp; }
  61. void spfa()
  62. {
  63. memset(dis, 127/3, sizeof dis);
  64. memset(inq, 0, sizeof inq);
  65. dis[S] = 0, que.push(S), inq[S] = 1;
  66. while (!que.empty()) {
  67. int t = que.front(); que.pop(), inq[t] = 0;
  68. for (int i = h2[t]; i; i = g2[i].next) {
  69. int to = g2[i].to, d = g2[i].flow;
  70. if (dis[to] > dis[t] + d) {
  71. dis[to] = dis[t] + d;
  72. if (!inq[to])
  73. inq[to] = 1, que.push(to);
  74. }
  75. }
  76. }
  77. }
  78. int main()
  79. {
  80. scanf("%d%d", &n, &m), S = 1, T = n+n;
  81. for (int i = 1; i <= m; i++) {
  82. int u, v;
  83. long long d; scanf("%d%d%lld", &u, &v, &d);
  84. push2(u, v, d), push2(v, u, d);
  85. }
  86. for (int i = 1; i <= n; i++) scanf("%lld", &rk[i]);
  87. spfa();
  88. for (int i = 1; i <= n; i++)
  89. for (int j = h2[i]; j; j = g2[j].next) {
  90. int to = g2[j].to;
  91. long long d = g2[j].flow;
  92. if (dis[to] == dis[i] + d) {
  93. push(i+n, to, inf);
  94. // cout << i << "--" << d << "->" << to << endl;
  95. }
  96. }
  97. push(1, n+1, inf), push(n, n+n, inf);
  98. for (int i = 2; i < n; i++) push(i, i+n, rk[i]);
  99. cout << dinic() << endl;
  100. return 0;
  101. }

spfa费用流

[Noi2008]志愿者招募

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. const int MAXN = 2005, MAXM = 100005;
  4. struct node {
  5. int to, next;
  6. long long flow, cost;
  7. int neg;
  8. } edge[MAXM];
  9. int head[MAXN], top = 0, S = 2000, T = 2001;
  10. long long inf = 23333333333333ll;
  11. void push(int i, int j, long long f, long long c)
  12. {
  13. ++top, edge[top] = (node){j, head[i], f, c, top+1}, head[i] = top;
  14. ++top, edge[top] = (node){i, head[j], 0, -c, top-1}, head[j] = top;
  15. }
  16. void push_lim(int i, int j, long long mf)
  17. {
  18. push(S, j, mf, 0), push(i, T, mf, 0);
  19. push(i, j, inf, 0);
  20. }
  21. long long dis[MAXN];
  22. int vis[MAXN], pre[MAXN], pre_edge[MAXN], n, m;
  23. queue<int> que;
  24. bool spfa(long long &cost)
  25. {
  26. memset(dis, 127/3, sizeof dis);
  27. memset(vis, 0, sizeof vis);
  28. memset(pre, 0, sizeof pre);
  29. memset(pre_edge, 0, sizeof pre_edge);
  30. vis[S] = 1, dis[S] = 0, que.push(S);
  31. while (!que.empty()) {
  32. int t = que.front(); que.pop(); vis[t] = 0;
  33. for (int i = head[t]; i; i = edge[i].next) {
  34. int to = edge[i].to, c = edge[i].cost;
  35. if (!edge[i].flow) continue;
  36. if (dis[to] > dis[t] + c) {
  37. dis[to] = dis[t] + c;
  38. pre[to] = t, pre_edge[to] = i;
  39. if (!vis[to])
  40. vis[to] = 1, que.push(to);
  41. }
  42. }
  43. }
  44. if (dis[T] >= inf) return 0;
  45. long long mf = inf;
  46. for (int i = T; i != S; i = pre[i]) mf = min(mf, edge[pre_edge[i]].flow);
  47. for (int i = T; i != S; i = pre[i]) edge[pre_edge[i]].flow -= mf, edge[edge[pre_edge[i]].neg].flow += mf;
  48. cost += dis[T]*mf;
  49. return 1;
  50. }
  51. long long mcf()
  52. {
  53. long long ans = 0;
  54. while (spfa(ans));
  55. return ans;
  56. }
  57. int main()
  58. {
  59. scanf("%d%d", &n, &m);
  60. for (int i = 1; i <= n; i++) {
  61. long long u; scanf("%lld", &u);
  62. push_lim(i, i+1, u);
  63. }
  64. for (int i = 1; i <= m; i++) {
  65. int l, r; long long cost;
  66. scanf("%d%d%lld", &l, &r, &cost);
  67. push(r+1, l, inf, cost);
  68. }
  69. cout << mcf() << endl;
  70. return 0;
  71. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注