[关闭]
@Dmaxiya 2019-01-16T08:47:11.000000Z 字数 7550 阅读 1717

Educational Codeforces Round 58

Codeforces


Contests 链接:Educational Codeforces Round 58
过题数:4
排名:985/6146

A. Minimum Integer

题意

输出不在范围 内的最小的正整数 ,要求 是 的整数倍。

输入

第一行为一个整数 ,接下去有 行,第 行的三个整数分别为 。

输出

对于每一行询问,输出对应的答案。

样例

输入
5
2 4 2
5 10 4
3 10 1
1 2 3
4 6 5
输出
6
4
1
3
10

题解

若 在 范围内,则输出 ,否则输出 。

过题代码

  1. #include <cstdio>
  2. #include <cstdlib>
  3. #include <cstring>
  4. #include <cmath>
  5. #include <cfloat>
  6. #include <climits>
  7. #include <iostream>
  8. #include <string>
  9. #include <vector>
  10. #include <list>
  11. #include <queue>
  12. #include <stack>
  13. #include <map>
  14. #include <set>
  15. #include <algorithm>
  16. #include <bitset>
  17. #include <sstream>
  18. using namespace std;
  19. #define LL long long
  20. int T;
  21. int l, r, x;
  22. int main() {
  23. #ifdef Dmaxiya
  24. freopen("test.txt", "r", stdin);
  25. #endif // Dmaxiya
  26. ios::sync_with_stdio(false);
  27. scanf("%d", &T);
  28. while(T--) {
  29. scanf("%d%d%d", &l, &r, &x);
  30. if(x >= l && x <= r) {
  31. printf("%d\n", r / x * x + x);
  32. } else {
  33. printf("%d\n", x);
  34. }
  35. }
  36. return 0;
  37. }

B. Accordion

题意

用一个字符串来表示一个手风琴,其必须要满足的格式为:由 [ 开头,接着是一个 :,往后是连续的多个或零个 |,接着是一个 : 和 ]。给定一个字符串,问能否通过删除一些字符,使得最终剩下的字符串可以表示成一个手风琴,若能,求最长剩余字符串长度。

输入

输入仅包含一个字符串 ,其中只包含小写字母以及 [、]、:、| 这几种符号。

输出

如果无法满足题意,则输出 ,否则输出能表示成手风琴的最长的字符串。

样例

输入
|[a:b:|]
输出
4
输入
|]:[|:]
输出
-1

题解

先找出最左边的 [ 下标 以及最右边的 ] 的下标 ,要求 ,接着找在 [l,r] 范围内最左边的 : 以及最右边的 :,最后将这两个冒号间所有的 | 个数统计出来,答案就是 | 的个数 。

过题代码

  1. #include <cstdio>
  2. #include <cstdlib>
  3. #include <cstring>
  4. #include <cmath>
  5. #include <cfloat>
  6. #include <climits>
  7. #include <iostream>
  8. #include <string>
  9. #include <vector>
  10. #include <list>
  11. #include <queue>
  12. #include <stack>
  13. #include <map>
  14. #include <set>
  15. #include <algorithm>
  16. #include <bitset>
  17. #include <sstream>
  18. using namespace std;
  19. #define LL long long
  20. const int maxn = 500000 + 100;
  21. int len;
  22. char str[maxn];
  23. int main() {
  24. #ifdef Dmaxiya
  25. freopen("test.txt", "r", stdin);
  26. #endif // Dmaxiya
  27. ios::sync_with_stdio(false);
  28. while(scanf("%s", str + 1) != EOF) {
  29. len = strlen(str + 1);
  30. int l = -1;
  31. int r = -1;
  32. for(int i = 1; i <= len; ++i) {
  33. if(str[i] == '[') {
  34. l = i;
  35. break;
  36. }
  37. }
  38. for(int i = len; i >= 1; --i) {
  39. if(str[i] == ']') {
  40. r = i;
  41. break;
  42. }
  43. }
  44. if(l == -1 || r == -1 || r <= l) {
  45. printf("-1\n");
  46. continue;
  47. }
  48. int ll = -1;
  49. int rr = -1;
  50. for(int i = l + 1; i < r; ++i) {
  51. if(str[i] == ':') {
  52. if(ll == -1) {
  53. ll = i;
  54. }
  55. rr = i;
  56. }
  57. }
  58. if(ll == -1 || rr == -1 || ll >= rr) {
  59. printf("-1\n");
  60. continue;
  61. }
  62. int ans = 4;
  63. for(int i = ll + 1; i < rr; ++i) {
  64. if(str[i] == '|') {
  65. ++ans;
  66. }
  67. }
  68. printf("%d\n", ans);
  69. }
  70. return 0;
  71. }

C. Division and Union

题意

给定 条线段,第 条线段的两个端点分别为 ,将这 条线段分别放入两个非空集合中,要求从这两个集合中分别任意取一条线段出来,这两条线段没有任何公共部分。

输入

第一行为一个整数 ,接下去有 组数据,每组数据第一行为一个整数 ,数据保证所有数据的 的总和不超过 ,接下去 行每行两个整数 。

输出

对于每组数据输出一行,若某组数据无解,则输出 ,否则输出 个整数 , 表示第 条线段被分到第 个集合中, 表示第 条线段被分到第 个集合中,若有多解则输出任意一个。

样例

输入
3
2
5 5
2 3
3
3 5
2 3
2 3
3
3 3
4 4
5 5
输出
2 1
-1
1 1 2
提示
在第一组数据中,两条线段应被放到不同的集合中,但答案并不一定必须是 2 1,也可以是 1 2。
在第二组数据中,第三条线段与前两条线段相交,因此它们应该被分在同一个集合中,这样另一个集合就会为空,不满足题意,因此答案为 。
在第三组数据中,我们可以以任意方式将三条线段分配到两个不同的集合中,只要这两个集合非空就是合法的,因此总共有 种合法的答案。

题解

将每条线段的两个端点拆开,左区间 标为 ,右区间 标为 ,以端点大小为主关键字从小到大、以下标为此关键词从小到大排序,最后对整个数组扫一遍,遇到左端点则放入集合中,遇到右端点则从集合中删除,最后用并查集维护相互覆盖的线段,只要存在至少两个连通块,就存在答案,将其中一个连通块中的线段放到集合 中,其他的连通块放入集合 中。

过题代码

  1. #include <cstdio>
  2. #include <cstdlib>
  3. #include <cstring>
  4. #include <cmath>
  5. #include <cfloat>
  6. #include <climits>
  7. #include <iostream>
  8. #include <string>
  9. #include <vector>
  10. #include <list>
  11. #include <queue>
  12. #include <stack>
  13. #include <map>
  14. #include <set>
  15. #include <algorithm>
  16. #include <bitset>
  17. #include <sstream>
  18. using namespace std;
  19. #define LL long long
  20. const int maxn = 100000 + 100;
  21. struct Node {
  22. int Index, x;
  23. };
  24. bool operator<(const Node &a, const Node &b) {
  25. return a.x == b.x? a.Index < b.Index: a.x < b.x;
  26. }
  27. int T, n, l, r;
  28. Node node[maxn << 1];
  29. set<int> st;
  30. int fa[maxn], ans[maxn];
  31. void Init() {
  32. for(int i = 1; i <= n; ++i) {
  33. fa[i] = i;
  34. }
  35. }
  36. int Find(int x) {
  37. return x == fa[x]? x: fa[x] = Find(fa[x]);
  38. }
  39. void unit(int x, int y) {
  40. int xx = Find(x);
  41. int yy = Find(y);
  42. fa[xx] = yy;
  43. }
  44. int main() {
  45. #ifdef Dmaxiya
  46. freopen("test.txt", "r", stdin);
  47. #endif // Dmaxiya
  48. ios::sync_with_stdio(false);
  49. scanf("%d", &T);
  50. while(T--) {
  51. scanf("%d", &n);
  52. st.clear();
  53. Init();
  54. for(int i = 1; i <= n; ++i) {
  55. scanf("%d%d", &l, &r);
  56. node[i].Index = i;
  57. node[i].x = l;
  58. node[i + n].Index = -i;
  59. node[i + n].x = r + 1;
  60. }
  61. sort(node + 1, node + 1 + 2 * n);
  62. for(int i = 1; i <= 2 * n; ) {
  63. while(i <= 2 * n && node[i].Index < 0) {
  64. st.erase(-node[i].Index);
  65. ++i;
  66. }
  67. if(i == 2 * n + 1) {
  68. break;
  69. }
  70. int f;
  71. if(st.empty()) {
  72. f = node[i].Index;
  73. } else {
  74. f = *st.begin();
  75. }
  76. while(i <= 2 * n && node[i].Index > 0) {
  77. st.insert(node[i].Index);
  78. unit(node[i].Index, f);
  79. ++i;
  80. }
  81. }
  82. bool flag = false;
  83. int f = Find(1);
  84. for(int i = 1; i <= n; ++i) {
  85. if(Find(i) == f) {
  86. ans[i] = 1;
  87. } else {
  88. flag = true;
  89. ans[i] = 2;
  90. }
  91. }
  92. if(!flag) {
  93. printf("-1\n");
  94. continue;
  95. }
  96. for(int i = 1; i <= n; ++i) {
  97. if(i != 1) {
  98. printf(" ");
  99. }
  100. printf("%d", ans[i]);
  101. }
  102. printf("\n");
  103. }
  104. return 0;
  105. }

D. GCD Counting

题意

给定一棵 个节点的树,树上的每个点都有一个权值 ,定义 表示从节点 到节点 的路径上所有节点(包括 两点)权值的 ,定义 表示从节点 到节点 的路径上所有节点的数量,对于任意一个节点有 。求在 的 对中, 的最大值。

输入

第一行为一个整数 ,第二行为 个整数 ,接下去 行每行两个整数 ,表示节点 与节点 之间有一条连边,数据保证所有的边可以构成一棵树。

输出

如果不存在满足条件的答案,输出 ,否则输出满足条件的 的最大值。

样例

输入
3
2 3 4
1 2
2 3
输出
1
输入
3
2 3 4
1 3
2 3
输出
2
输入
3
1 1 1
1 2
2 3
输出
0

题解

定义 表示以第 个节点为根,从其任意一个子节点往下的一条链,这条链上所有节点权值的 为 的倍数的最长长度,则可以得到 递推式:

其中 为节点 的所有子节点, 为 的所有质因子,答案为:

其中 表示序列中的次大值。

过题代码

  1. #include <cstdio>
  2. #include <cstdlib>
  3. #include <cstring>
  4. #include <cmath>
  5. #include <cfloat>
  6. #include <climits>
  7. #include <iostream>
  8. #include <string>
  9. #include <vector>
  10. #include <list>
  11. #include <queue>
  12. #include <stack>
  13. #include <map>
  14. #include <set>
  15. #include <algorithm>
  16. #include <bitset>
  17. #include <sstream>
  18. using namespace std;
  19. #define LL long long
  20. const int maxn = 200000 + 100;
  21. int n, ans, u, v;
  22. int num[maxn];
  23. vector<int> G[maxn];
  24. vector<int> fac[maxn];
  25. map<int, int> dp[maxn];
  26. map<int, int>::iterator it;
  27. int cnt;
  28. int prime[maxn];
  29. bool vis[maxn];
  30. void Prime(int n) {
  31. for(int i = 2; i <= n; ++i) {
  32. if(!vis[i]) {
  33. prime[cnt++] = i;
  34. }
  35. for(int j = 0; j < cnt && i <= n / prime[j]; ++j) {
  36. int k = i * prime[j];
  37. vis[k] = true;
  38. if(i % prime[j] == 0) {
  39. break;
  40. }
  41. }
  42. }
  43. }
  44. void dfs(int f, int x) {
  45. int len = G[x].size();
  46. for(int i = 0; i < len; ++i) {
  47. int pos = G[x][i];
  48. if(pos == f) {
  49. continue;
  50. }
  51. dfs(x, pos);
  52. }
  53. len = fac[num[x]].size();
  54. for(int i = 0; i < len; ++i) {
  55. int ffac = fac[num[x]][i];
  56. int MMax = 0;
  57. int Max = 0;
  58. int llen = G[x].size();
  59. for(int j = 0; j < llen; ++j) {
  60. int pos = G[x][j];
  61. if(pos == f) {
  62. continue;
  63. }
  64. it = dp[pos].find(ffac);
  65. if(it == dp[pos].end()) {
  66. continue;
  67. }
  68. if(it->second >= Max) {
  69. MMax = Max;
  70. Max = it->second;
  71. } else if(it->second > MMax) {
  72. MMax = it->second;
  73. }
  74. }
  75. ans = max(ans, 1 + Max + MMax);
  76. dp[x][ffac] = 1 + Max;
  77. }
  78. }
  79. int main() {
  80. #ifdef Dmaxiya
  81. freopen("test.txt", "r", stdin);
  82. #endif // Dmaxiya
  83. ios::sync_with_stdio(false);
  84. Prime(maxn - 1);
  85. for(int i = 0; i < cnt; ++i) {
  86. for(int j = prime[i]; j < maxn; j += prime[i]) {
  87. fac[j].push_back(prime[i]);
  88. }
  89. }
  90. scanf("%d", &n);
  91. for(int i = 1; i <= n; ++i) {
  92. scanf("%d", &num[i]);
  93. }
  94. for(int i = 1; i < n; ++i) {
  95. scanf("%d%d", &u, &v);
  96. G[u].push_back(v);
  97. G[v].push_back(u);
  98. }
  99. dfs(1, 1);
  100. printf("%d\n", ans);
  101. return 0;
  102. }

E. Polycarp's New Job

题意

给定两种操作:

  1. 从一个初始为空的集合中加入一张大小为 的票据;
  2. 询问大小为 的钱包是否能装下所有票据。

对于所有已经被加入集合的票据,满足以下任意一个条件,则钱包能够装下所有票据:

  1. 且 ;
  2. 且 。

对于每次询问,输出钱包是否能够装下集合中所有的票据。

输入

第一行包含一个整数 ,接下去有 次操作,每次操作格式为以下两个之一:

  1. ,表示加入一张大小为 的票据;
  2. ,询问大小为 的钱包能否放下集合中的所有票据。

数据保证在第一个询问 之前至少存在一个询问 ,并且至少存在一个询问 。

输出

对于每次询问,输出 或 ,表示答案。

样例

输入
9
+ 3 2
+ 2 3
? 1 20
? 3 3
? 2 3
+ 1 5
? 10 10
? 1 5
+ 1 1
输出
NO
YES
YES
YES
NO

题解

对于每次放入的票据,每次取短边的最大值和长边的最大值,对于每次询问,只要短边的最大值小于等于钱包的短边,长边的最大值小于等于钱包的长边即可。

过题代码

  1. #include <cstdio>
  2. #include <cstdlib>
  3. #include <cstring>
  4. #include <cmath>
  5. #include <cfloat>
  6. #include <climits>
  7. #include <iostream>
  8. #include <string>
  9. #include <vector>
  10. #include <list>
  11. #include <queue>
  12. #include <stack>
  13. #include <map>
  14. #include <set>
  15. #include <algorithm>
  16. #include <bitset>
  17. #include <sstream>
  18. using namespace std;
  19. #define LL long long
  20. int n, l, r, maxl, maxr;
  21. char ch[2];
  22. int main() {
  23. #ifdef Dmaxiya
  24. freopen("test.txt", "r", stdin);
  25. #endif // Dmaxiya
  26. ios::sync_with_stdio(false);
  27. while(scanf("%d", &n) != EOF) {
  28. maxl = 0;
  29. maxr = 0;
  30. for(int i = 0; i < n; ++i) {
  31. scanf("%s%d%d", ch, &l, &r);
  32. if(l > r) {
  33. swap(l, r);
  34. }
  35. if(ch[0] == '+') {
  36. maxl = max(maxl, l);
  37. maxr = max(maxr, r);
  38. } else {
  39. if(l >= maxl && r >= maxr) {
  40. printf("YES\n");
  41. } else {
  42. printf("NO\n");
  43. }
  44. }
  45. }
  46. }
  47. return 0;
  48. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注