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

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. ,询问大小为 的钱包能否放下集合中的所有票据。

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

输出

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

样例

输入
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. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注