[关闭]
@Dmaxiya 2018-08-17T10:24:43.000000Z 字数 6999 阅读 1092

Educational Codeforces Round 24

Codeforces


Contests 链接:Educational Codeforces Round 24
过题数:2
排名:902/5771

A. Diplomas and Certificates

题意

总共有 个学生,有一部分学生获得了 ,有另一部分学生获得了 ,而其他学生什么都没有获得,其中获得 的学生称为 ,问在保证 人数不超过 的条件下,获得使 最大的情况。

输入

输入包含两个整数

输出

分别输出获得 和什么都没获得的人数。

样例

输入 输出
18 2 3 6 9
9 10 0 0 9
1000000000000 5 83333333333 416666666665 500000000002
1000000000000 499999999999 1 499999999999 500000000000

题解

只要确定获得 的人数就可以确定另外两个人数,

过题代码

  1. #include <iostream>
  2. #include <cstdio>
  3. #include <cstdlib>
  4. #include <cmath>
  5. #include <sstream>
  6. #include <cstring>
  7. #include <string>
  8. #include <vector>
  9. #include <list>
  10. #include <queue>
  11. #include <stack>
  12. #include <map>
  13. #include <set>
  14. #include <algorithm>
  15. using namespace std;
  16. #define LL long long
  17. LL n, k, ans;
  18. int main() {
  19. #ifdef Dmaxiya
  20. freopen("test.txt", "r", stdin);
  21. #endif // Dmaxiya
  22. ios::sync_with_stdio(false);
  23. while(scanf("%I64d%I64d", &n, &k) != EOF) {
  24. ans = n / 2 / (k + 1);
  25. printf("%I64d %I64d %I64d\n", ans, ans * k, n - ans * (k + 1));
  26. }
  27. return 0;
  28. }

B. Permutation Game

题意

构造一个 的排列 ,使得对于一个长度为 的序列 ,当 时,总是满足 ,当 大于 时,将结果减去

输入

第一行为两个整数 ,第二行为 个整数

输出

如果无法构造出满足条件的序列,则输出 ,否则输出 个整数,如果有多解输出任意一组解。

样例

输入 输出 提示
4 5
2 3 1 4 4
3 1 2 4 开始:



3 3
3 1 2
-1

题解

首先根据 先生成一个 序列,先计算这个序列中每个数字出现的次数,如果某个数字出现的次数大于 ,则这个序列是非法的,接着将这个序列中没有被用到的数据放进去,使得 序列成为一个 的排列,最后再扫一遍 序列,判断是否对于每个 都满足题给条件。

过题代码

  1. #include <iostream>
  2. #include <cstdio>
  3. #include <cstdlib>
  4. #include <cmath>
  5. #include <sstream>
  6. #include <cstring>
  7. #include <string>
  8. #include <vector>
  9. #include <list>
  10. #include <queue>
  11. #include <stack>
  12. #include <map>
  13. #include <set>
  14. #include <algorithm>
  15. using namespace std;
  16. #define LL long long
  17. const int maxn = 100 + 100;
  18. int n, m;
  19. int num[maxn], ans[maxn], cnt[maxn];
  20. int main() {
  21. #ifdef Dmaxiya
  22. freopen("test.txt", "r", stdin);
  23. #endif // Dmaxiya
  24. ios::sync_with_stdio(false);
  25. while(scanf("%d%d", &n, &m) != EOF) {
  26. memset(cnt, 0, sizeof(cnt));
  27. memset(ans, 0, sizeof(ans));
  28. for(int i = 1; i <= m; ++i) {
  29. scanf("%d", &num[i]);
  30. }
  31. for(int i = 1; i < m; ++i) {
  32. int tmp = num[i + 1] - num[i];
  33. tmp = (tmp % n + n) % n;
  34. if(tmp == 0) {
  35. tmp = n;
  36. }
  37. ans[num[i]] = tmp;
  38. }
  39. bool flag = true;
  40. for(int i = 1; i <= n; ++i) {
  41. if(ans[i] == 0) {
  42. continue;
  43. }
  44. ++cnt[ans[i]];
  45. if(cnt[ans[i]] == 2) {
  46. flag =false;
  47. break;
  48. }
  49. }
  50. if(!flag) {
  51. printf("-1\n");
  52. continue;
  53. }
  54. for(int i = 1; i <= n; ++i) {
  55. if(ans[i] == 0) {
  56. for(int j = 1; j <= n; ++j) {
  57. if(cnt[j] == 0) {
  58. ++cnt[j];
  59. ans[i] = j;
  60. break;
  61. }
  62. }
  63. }
  64. }
  65. for(int i = 1; i < m; ++i) {
  66. int tmp = num[i] + ans[num[i]];
  67. tmp = (tmp % n + n) % n;
  68. if(tmp == 0) {
  69. tmp = n;
  70. }
  71. if(tmp != num[i + 1]) {
  72. flag = false;
  73. break;
  74. }
  75. }
  76. if(!flag) {
  77. printf("-1\n");
  78. continue;
  79. }
  80. for(int i = 1; i <= n; ++i) {
  81. if(i != 1) {
  82. printf(" ");
  83. }
  84. printf("%d", ans[i]);
  85. }
  86. printf("\n");
  87. }
  88. return 0;
  89. }

C. Sofa Thief

题意

在一个 的仓库里,有 个沙发,每个沙发占两个相邻的位置,用两个坐标 表示,对于两个沙发 ,如果存在 ,则表示 沙发在 沙发的左边,如果存在 ,则表示 沙发在 沙发的右边,如果存在 ,则表示 沙发在 沙发的上面,如果存在 ,则表示 沙发在 沙发的下面,其中 分别属于沙发 与沙发 的其中一个横坐标或纵坐标。注意对于两个沙发, 可能既在 的左边也在 的右边。
现在给出某个沙发的左边、右边、上面、下面各有多少个沙发,找出满足条件的沙发。

输入

第一行包含一个整数 ,第二行为两个整数 ,接下去 行,每行四个整数 ,表示每个沙发的坐标,数据保证任意两个坐标都不会相同,且对同一个沙发的坐标描述一定是相邻的。最后一行为四个整数 ,表示要找的沙发需要符合的四个方向的沙发数量。数据保证最多只有一个沙发符合条件。

输出

如果不存在满足条件的沙发,就输出 ,否则输出满足条件的沙发编号,沙发编号按照输入顺序从 编号。

样例

输入 输出 提示
2
3 2
3 1 3 2
1 2 2 2
1 0 0 1
1
3
10 10
1 2 1 1
5 5 6 5
6 4 5 4
2 1 2 0
2 · 第一个沙发的左边没有任何沙发,右边有两个沙发,上面没有沙发,下面有两个沙发;
· 对于第二个沙发:
· 对于第三个沙发:
因此第 个沙发满足给出的条件。
2
2 2
2 1 1 1
1 2 2 2
1 0 0 0
-1 · 对于第一个沙发:
· 对于第二个沙发:
没有沙发满足

题解

假设第 个沙发的 ,由于上下左右四个方向的判定是类似的,因此这里只讨论左边的情况,可以推广到另外三个方向的情况:
由左边的判定方法可知:第 个沙发左边的沙发个数等于满足 的沙发个数(一个沙发只要有一个点满足条件,就能计入答案),我们可以通过对每个沙发的贡献做前缀和来 求出 。对于第 个沙发,它对所有满足 的沙发都有贡献,因此可以在 处标记一个 ,最后做一个前缀和即可查询到任意一个沙发左边的沙发个数。
对其他三个方向也做同样的判断。

过题代码

  1. #include <iostream>
  2. #include <cstdio>
  3. #include <cstdlib>
  4. #include <cmath>
  5. #include <sstream>
  6. #include <cstring>
  7. #include <string>
  8. #include <vector>
  9. #include <list>
  10. #include <queue>
  11. #include <stack>
  12. #include <map>
  13. #include <set>
  14. #include <algorithm>
  15. using namespace std;
  16. #define LL long long
  17. const int maxn = 100000 + 100;
  18. int d, n, m, ans;
  19. int node[maxn][4], cnt[4];
  20. int Sum[4][maxn], Ends[4][2], dx[4];
  21. int main() {
  22. #ifdef Dmaxiya
  23. freopen("test.txt", "r", stdin);
  24. #endif // Dmaxiya
  25. ios::sync_with_stdio(false);
  26. while(scanf("%d", &d) != EOF) {
  27. ans = -1;
  28. memset(Sum, 0, sizeof(Sum));
  29. scanf("%d%d", &n, &m);
  30. dx[0] = dx[2] = 1;
  31. dx[1] = dx[3] = -1;
  32. Ends[0][1] = n + 1;
  33. Ends[1][0] = n - 1;
  34. Ends[2][1] = m + 1;
  35. Ends[3][0] = m - 1;
  36. Ends[1][1] = Ends[3][1] = 0;
  37. Ends[0][0] = Ends[2][0] = 2;
  38. for(int i = 1; i <= d; ++i) {
  39. for(int j = 0; j < 4; ++j) {
  40. scanf("%d", &node[i][j]);
  41. }
  42. swap(node[i][1], node[i][2]);
  43. if(node[i][0] < node[i][1]) {
  44. swap(node[i][0], node[i][1]);
  45. }
  46. if(node[i][2] < node[i][3]) {
  47. swap(node[i][2], node[i][3]);
  48. }
  49. ++Sum[0][node[i][1] + 1];
  50. ++Sum[1][node[i][0] - 1];
  51. ++Sum[2][node[i][3] + 1];
  52. ++Sum[3][node[i][2] - 1];
  53. }
  54. for(int i = 0; i < 4; ++i) {
  55. for(int j = Ends[i][0]; j != Ends[i][1]; j += dx[i]) {
  56. Sum[i][j] += Sum[i][j - dx[i]];
  57. }
  58. }
  59. for(int i = 0; i < 4; ++i) {
  60. scanf("%d", &cnt[i]);
  61. }
  62. for(int i = 1; i <= d; ++i) {
  63. bool flag = true;
  64. for(int j = 0; j < 4; ++j) {
  65. int tmp = Sum[j][node[i][j]];
  66. if(node[i][j] != node[i][j ^ 1]) {
  67. --tmp;
  68. }
  69. if(tmp != cnt[j]) {
  70. flag = false;
  71. break;
  72. }
  73. }
  74. if(flag) {
  75. ans = i;
  76. break;
  77. }
  78. }
  79. printf("%d\n", ans);
  80. }
  81. return 0;
  82. }

D. Multicolored Cars

题意

两个人在车里可以看到窗外一辆辆行驶过的车,每辆车都有一个颜色 最开始分别选一种颜色 ,每经过一辆车,就统计到目前为止颜色为 的车的数量 和颜色为 的车的数量 ,对于经过的每一辆车:

  • 如果 ,则 获胜;
  • 如果 ,则 获胜;
  • 否则两人平局。

知道将要经过的每一辆车的颜色,现在 已经选择了一种颜色 ,问 应该选择什么颜色才能获胜?

输入

第一行包含两个整数 ,第二行包含 个整数

输出

如果 可以获胜,则输出他应该选择的颜色 ,否则输出 。数据保证如果 可以获胜,那么在 内一定存在一种颜色可以使 获胜,如果有多解输出任意一组。

样例

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

题解

首先将所有颜色都作为可能的答案,每出现一种颜色,就将这种颜色的出现次数 ,接着将所有出现次数小于 的数字删除,最后剩下来的的颜色就是答案,如果最后没有数字留下,则输出

过题代码

  1. #include <iostream>
  2. #include <cstdio>
  3. #include <cstdlib>
  4. #include <cmath>
  5. #include <sstream>
  6. #include <cstring>
  7. #include <string>
  8. #include <vector>
  9. #include <list>
  10. #include <queue>
  11. #include <stack>
  12. #include <map>
  13. #include <set>
  14. #include <algorithm>
  15. using namespace std;
  16. #define LL long long
  17. const int maxn = 1000000 + 100;
  18. struct Node {
  19. int cnt, num;
  20. Node() {}
  21. Node(int c, int n) {
  22. cnt = c;
  23. num = n;
  24. }
  25. };
  26. bool operator<(const Node &a, const Node &b) {
  27. return (a.cnt == b.cnt? a.num < b.num: a.cnt > b.cnt);
  28. }
  29. int n, A, c;
  30. bool vis[maxn];
  31. int cnt[maxn];
  32. set<Node> st;
  33. set<Node>::iterator it;
  34. vector<set<Node>::iterator> vct;
  35. int main() {
  36. #ifdef Dmaxiya
  37. freopen("test.txt", "r", stdin);
  38. #endif // Dmaxiya
  39. ios::sync_with_stdio(false);
  40. while(scanf("%d%d", &n, &A) != EOF) {
  41. st.clear();
  42. memset(cnt, 0, sizeof(cnt));
  43. memset(vis, 0, sizeof(vis));
  44. for(int i = 1; i <= 1000000; ++i) {
  45. st.insert(Node(0, i));
  46. }
  47. for(int i = 0; i < n; ++i) {
  48. scanf("%d", &c);
  49. if(vis[c]) {
  50. continue;
  51. }
  52. it = st.find(Node(cnt[c], c));
  53. st.erase(it);
  54. ++cnt[c];
  55. st.insert(Node(cnt[c], c));
  56. it = st.upper_bound(Node(cnt[A] - 1, 0));
  57. vct.clear();
  58. for(; it != st.end(); ++it) {
  59. vct.push_back(it);
  60. }
  61. int len = vct.size();
  62. for(int i = 0; i < len; ++i) {
  63. vis[vct[i]->num] = true;
  64. st.erase(vct[i]);
  65. }
  66. }
  67. st.erase(Node(cnt[A], A));
  68. if(st.empty()) {
  69. printf("-1\n");
  70. continue;
  71. }
  72. it = st.begin();
  73. printf("%d\n", it->num);
  74. }
  75. return 0;
  76. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注