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

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