[关闭]
@ljt12138 2017-07-12T20:26:01.000000Z 字数 2452 阅读 748

Codeforces Round #423 (Div. 1)


A. String Reconstruction

题意:给定若干个限制,表示字符串第个开始匹配。要求构造一个字典序最小的合法串。
花神游历各国弱化版。用并查集维护下一个没有确定的位置即可。

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. const int MAXN = 2000005;
  4. string str[MAXN];
  5. int n;
  6. vector<int> vec[MAXN];
  7. char s[MAXN];
  8. int fa[MAXN];
  9. inline int findf(int nd)
  10. { return fa[nd]?fa[nd]=findf(fa[nd]):nd; }
  11. void link(int i, int j)
  12. {
  13. i = findf(i), j = findf(j);
  14. if (i != j) fa[i] = j;
  15. }
  16. char S[MAXN];
  17. int main()
  18. {
  19. scanf("%d", &n);
  20. int max_r = 0;
  21. for (int i = 1; i <= n; i++) {
  22. scanf("%s", s);
  23. str[i] = s;
  24. int num, d; scanf("%d", &num);
  25. for (int j = 1; j <= num; j++) {
  26. scanf("%d", &d);
  27. vec[i].push_back(d);
  28. }
  29. // cerr << vec[i][num-1]+str[i].size()-1 << endl;
  30. max_r = max(max_r, int(vec[i][num-1]+str[i].size()-1));
  31. }
  32. for (int i = 1; i <= max_r; i++) S[i] = '-';
  33. memset(fa, 0, sizeof fa);
  34. for (int i = 1; i <= n; i++) {
  35. for (int j = 0; j < vec[i].size(); j++) {
  36. int pos = findf(vec[i][j]), pt = pos-vec[i][j];
  37. while (pt < str[i].size()) {
  38. S[pos] = str[i][pt];
  39. if (S[pos-1] != '-') link(pos-1, pos);
  40. link(pos, pos+1);
  41. pos = findf(pos), pt = pos-vec[i][j];
  42. }
  43. }
  44. }
  45. for (int i = 1; i <= max_r; i++) {
  46. if (S[i] == '-')
  47. putchar('a');
  48. else
  49. putchar(S[i]);
  50. }
  51. puts("");
  52. return 0;
  53. }

B. High Load

题意:构造一个个节点个叶子的树,使得任意两个叶子距离的最大值最小。

时,显然就是搞一个菊花,剩余部分直接连在菊花的根上。

否则安排个节点连接个叶子,递归处理。

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. int n, k;
  4. const int MAXN = 200005;
  5. struct node {
  6. int to, next;
  7. } edge[MAXN*2];
  8. int head[MAXN], top = 0;
  9. void push(int i, int j)
  10. {
  11. edge[++top] = (node) {j, head[i]}, head[i] = top;
  12. }
  13. int pt_top = 0;
  14. int rt;
  15. void build(int n, vector<int> &leaves)
  16. {
  17. int k = leaves.size();
  18. if (n-1 <= k) {
  19. int L = pt_top;
  20. rt = pt_top+1;
  21. for (int i = 2; i <= n; i++) {
  22. push(pt_top+i, pt_top+1);
  23. push(pt_top+1, pt_top+i);
  24. }
  25. for (int i = 0; i < n-1; i++) {
  26. push(pt_top+i+2, leaves[i]);
  27. push(leaves[i], pt_top+i+2);
  28. }
  29. for (int i = n-1; i < leaves.size(); i++) {
  30. push(leaves[i], pt_top+1);
  31. push(pt_top+1, leaves[i]);
  32. }
  33. return;
  34. }
  35. for (int i = 0; i < k; i++) {
  36. push(leaves[i], pt_top+i+1);
  37. push(pt_top+i+1, leaves[i]);
  38. }
  39. for (int i = 0; i < k; i++)
  40. leaves[i] = pt_top+i+1;
  41. pt_top += k;
  42. build(n-k, leaves);
  43. }
  44. int len_eg[MAXN], eg_top = 0;
  45. int x[MAXN], y[MAXN], xy_top = 0;
  46. void dfs(int nd, int f, int dep)
  47. {
  48. int flag = 1;
  49. for (int i = head[nd]; i; i = edge[i].next) {
  50. int to = edge[i].to;
  51. if (to == f) continue;
  52. flag = 0, ++xy_top, x[xy_top] = nd, y[xy_top] = to;
  53. dfs(to, nd, dep+1);
  54. }
  55. if (flag == 1)
  56. len_eg[++eg_top] = dep;
  57. }
  58. vector<int> vec;
  59. int main()
  60. {
  61. scanf("%d%d", &n, &k);
  62. for (int i = 1; i <= k; i++) vec.push_back(++pt_top);
  63. build(n-k, vec);
  64. dfs(rt, 0, 0);
  65. sort(len_eg+1, len_eg+eg_top);
  66. cout << len_eg[eg_top]+len_eg[eg_top-1] << endl;
  67. for (int i = 1; i <= xy_top; i++)
  68. printf("%d %d\n", x[i], y[i]);
  69. return 0;
  70. }

C. DNA Evolution

给定一个只有的字符串,有两种操作:

  1. 改变一个位置的字符
  2. 询问,问的匹配数,

考虑枚举中每一个位置的贡献,即是在中与模同余位置相同的。只需要用个树状数组大力维护一下...

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注