[关闭]
@Dmaxiya 2018-08-17T10:16:59.000000Z 字数 8115 阅读 1052

Codeforces Round #469 (Div. 2)

Codeforces


Contests 链接:Codeforces Round #469 (Div. 2)
过题数:5
排名:72/9541

A. Left-handers, Right-handers and Ambidexters

题意

个擅长使用左手的人, 个擅长使用右手的人,有 个左右手都擅长的人,要求组建一支人数为人偶数的队伍,队伍中使用左手的人数和右手的人数一样多(每个人都只能使用其中一只自己擅长的手),求队伍的最大人数。

输入

输入只包含 个整数

输出

输出能组建的队伍的最大人数。

样例

输入 输出 提示
1 4 2 6 个人中有 个人只擅长使用左手, 个两只手都擅长的人只使用左手, 个擅长使用右手的人。
5 5 5 14 个人中 个人只擅长使用左手, 个人只擅长使用右手, 个两只手都擅长的人 个人只使用
右手, 个人只使用左手。
0 2 0 0

题解

先将 个人分配给人数少的那一边,使得擅长左手的人数和擅长右手的人数尽量相等,如果还有多余人数,就自行两两组队。

过题代码

  1. #include <iostream>
  2. #include <cstdio>
  3. #include <cstdlib>
  4. #include <cmath>
  5. #include <climits>
  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 <bitset>
  15. #include <algorithm>
  16. #include <sstream>
  17. using namespace std;
  18. #define LL long long
  19. int l, r, a;
  20. int main() {
  21. #ifdef LOCAL
  22. freopen("test.txt", "r", stdin);
  23. // freopen("out.txt", "w", stdout);
  24. #endif // LOCAL
  25. ios::sync_with_stdio(false);
  26. while(scanf("%d%d%d", &l, &r, &a) != EOF) {
  27. if(l > r) {
  28. swap(l, r);
  29. }
  30. int ans = r - l;
  31. if(ans > a) {
  32. ans = 2 * (a + l);
  33. } else {
  34. ans = 2 * (ans + l) + (a - ans) / 2 * 2;
  35. }
  36. printf("%d\n", ans);
  37. }
  38. return 0;
  39. }

B. Intercepted Message

题意

给定两个长度分别为 的序列 ,要将序列 和序列 分别划分成若干段,使得序列 的第 段数字的和等于序列 的第 段数字的和,问最多能够分成多少段。

输入

第一行为两个整数 ,第二行为 个整数 ,第三行为 个整数 ,数据保证

输出

输出能够分割的最大段数。

样例

输入 输出 提示
7 6
2 5 3 1 11 4 4
7 8 2 4 1 8
3 段数字分别为:
3 3
1 10 100
1 100 10
2 可以将第 个数字分为一段,后面 个数字分为一段,由于不能修改数字的顺序,所
以我们不能将 分为 段。
1 4
4
1 1 1 1
1 序列只有一个数字,所以只能分成 段。

题解

类似于归并排序,给两个序列各加一个指针,分别移动,哪一个序列加的数字小于另一个序列的数,就将那个序列的指针往后移动,每次移动到相等,就将答案

过题代码

  1. #include <iostream>
  2. #include <cstdio>
  3. #include <cstdlib>
  4. #include <cmath>
  5. #include <climits>
  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 <bitset>
  15. #include <algorithm>
  16. #include <functional>
  17. #include <iomanip>
  18. using namespace std;
  19. #define LL long long
  20. const int maxn = 100000 + 100;
  21. int n, m, cnt;
  22. LL suma, sumb;
  23. LL a[maxn], b[maxn];
  24. int main() {
  25. #ifdef LOCAL
  26. freopen("test.txt", "r", stdin);
  27. // freopen("out.txt", "w", stdout);
  28. #endif // LOCAL
  29. ios::sync_with_stdio(false);
  30. while(scanf("%d%d", &n, &m) != EOF) {
  31. for(int i = 0; i < n; ++i) {
  32. scanf("%I64d", &a[i]);
  33. }
  34. for(int i = 0; i < m; ++i) {
  35. scanf("%I64d", &b[i]);
  36. }
  37. cnt = 0;
  38. int Index = 0;
  39. suma = sumb = 0;
  40. for(int i = 0; i < n; ++i) {
  41. suma += a[i];
  42. while(sumb < suma) {
  43. sumb += b[Index];
  44. ++Index;
  45. }
  46. if(sumb == suma) {
  47. ++cnt;
  48. suma = sumb = 0;
  49. }
  50. }
  51. printf("%d\n", cnt);
  52. }
  53. return 0;
  54. }

C. Zebras

题意

给定一个 字符串,要求找出其中满足下列条件的子序列:

  1. 子序列中 相间;
  2. 子序列以 开头,以 结尾;
  3. 任意两个子序列之间没有交集;
  4. 所有子序列的并为整个序列。

输出找出的子序列方案,子序列的个数不必最少,只要合法即可。

输入

输入只有一行,为一个只包含 的字符串

输出

第一行输出一个整数 ,表示子序列的个数,接下去 行,每行表示一个子序列,每行第一个整数为 ,表示第 个子序列中的字符个数,接下去 个整数每个整数表示序列中的第 个元素在原字符串中的下标,下标从 开始。如果无法构造出满足条件的序列,输出

样例

输入 输出
0010100 3
3 1 3 4
3 2 5 6
1 7
111 -1

题解

将所有 字符所在的下标放到一个 中,所有 字符所在的下标放到一个 中,每次交替从这两个 中选出大于当前 或者 的下标的最小值,将这个下标记录到答案中,并从查找的集合中删去,如果某一次查找中,查找到的最后一个数字不是 ,则说明 的数量不够,需要输出 ,如果所有的 间隔序列都查找完毕,而存 的下标的集合仍为非空,则输出 ,其他情况均可以构造出满足条件的 间隔序列,最后注意把所有多出来的 都单独放到一个序列作为答案。

过题代码

  1. #include <iostream>
  2. #include <cstdio>
  3. #include <cstdlib>
  4. #include <cmath>
  5. #include <climits>
  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 <bitset>
  15. #include <algorithm>
  16. #include <sstream>
  17. using namespace std;
  18. #define LL long long
  19. const int maxn = 200000 + 100;
  20. int len, cnt, Index, num;
  21. bool flag;
  22. vector<int> G[maxn];
  23. set<int> st[2];
  24. set<int>::iterator it;
  25. char str[maxn];
  26. int main() {
  27. #ifdef LOCAL
  28. freopen("test.txt", "r", stdin);
  29. // freopen("out.txt", "w", stdout);
  30. #endif // LOCAL
  31. ios::sync_with_stdio(false);
  32. while(scanf("%s", str + 1) != EOF) {
  33. cnt = 0;
  34. flag = true;
  35. len = strlen(str + 1);
  36. st[0].clear();
  37. st[1].clear();
  38. for(int i = 1; i <= len; ++i) {
  39. st[str[i] - '0'].insert(i);
  40. }
  41. while(!st[0].empty() && !st[1].empty()) {
  42. Index = 0;
  43. G[++cnt].clear();
  44. it = st[0].begin();
  45. while(it != st[0].end() && it != st[1].end()) {
  46. num = *it;
  47. G[cnt].push_back(num);
  48. st[Index].erase(it);
  49. Index = 1 - Index;
  50. it = st[Index].upper_bound(num);
  51. }
  52. if(str[G[cnt].back()] == '1') {
  53. flag = false;
  54. break;
  55. }
  56. }
  57. if(!st[1].empty() || !flag) {
  58. printf("-1\n");
  59. continue;
  60. }
  61. while(!st[0].empty()) {
  62. G[++cnt].clear();
  63. G[cnt].push_back(*st[0].begin());
  64. st[0].erase(st[0].begin());
  65. }
  66. printf("%d\n", cnt);
  67. for(int i = 1; i <= cnt; ++i) {
  68. len = G[i].size();
  69. printf("%d", len);
  70. for(int j = 0; j < len; ++j) {
  71. printf(" %d", G[i][j]);
  72. }
  73. printf("\n");
  74. }
  75. }
  76. return 0;
  77. }

D. A Leapfrog in the Array

题意

最初有一个长度为 的数组,数组的每个偶数位都是空的,数组的 位上的数字为 ,然后将这个数组的最后一个数字放到数组的最后一个空着的位上,不断执行这个操作,直到数组中不再有空位为止,最终数组的长度为 ,对于一个长度为 的的初始数组,操作如下:

对于一个长度为 的最终数组, 次询问它的第 位上的数字的值。

输入

第一行为两个整数,接下去 行每行一个整数

输出

对于每次询问,输出最终数组 位上的数字。

样例

输入 输出 提示
4 3
2
3
4
3
2
4
最终数组如上图所示。
13 4
10
5
4
8
13
3
8
9
最终数组为:

题解

对于每次询问,若 为奇数,则答案为 ,否则将 位上的数字还原到原来的位置上,第 位上的数字,假设它左边所有的奇数位的数字都已经归位,偶数位上的数字都已经到它的后面,现在到这个位置上的数字还原,那么它左边的数字有 个,右边的数字有 ,因此这个数字一次还原的位置为 ,不断还原下去,直到 为奇数为止。

过题代码

  1. #include <iostream>
  2. #include <cstdio>
  3. #include <cstdlib>
  4. #include <cmath>
  5. #include <climits>
  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 <bitset>
  15. #include <algorithm>
  16. #include <functional>
  17. #include <iomanip>
  18. using namespace std;
  19. #define LL long long
  20. LL n, q;
  21. LL x, Index;
  22. int main() {
  23. #ifdef LOCAL
  24. freopen("test.txt", "r", stdin);
  25. // freopen("out.txt", "w", stdout);
  26. #endif // LOCAL
  27. ios::sync_with_stdio(false);
  28. while(scanf("%I64d%I64d", &n, &q) != EOF) {
  29. while(q--) {
  30. scanf("%I64d", &x);
  31. while(x % 2 == 0) {
  32. x += n - x / 2;
  33. }
  34. printf("%I64d\n", (x + 1) / 2);
  35. }
  36. }
  37. return 0;
  38. }

E. Data Center Maintenance

题意

个银行, 个客户,每个客户都把自己的资料放在 个银行,一天总共有 小时,每个银行每天都要维护一小时,这一小时内银行无法工作,但是这一小时客户仍然可以在另一个银行提取资料,于是客户就可以一天 小时随时提取资料。现在要选择 个银行进行实验,每个进行实验的银行,它每天的维护时间都推迟一小时,如果原来的维护时间是 时,进行实验后银行的维护时间就为 时。问最少选择几个银行(至少一个)进行实验,才能仍然保证每一个客户随时都能提取到资料。

输入

第一行为 个整数 ,第二行为 个整数 表示第 个银行一天内需要维护的时间点。接下去 行每行两个整数 ,表示第 个客户把资料存放在第 和第 个银行。数据保证最初每一个客户都可以在一天的任意时刻取得资料。

输出

第一行为一个整数 ,表示最少可以进行实验的银行数量,第二行为 个整数 ,表示 个进行实验的银行编号,如果有多解,输出任意一个。

样例

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

题解

如果某个客户将他的资料放在两个维护时间相邻的银行,第一个银行的维护时间 和第二个银行的维护时间 的关系为 ,那么第一个银行一旦进行实验,第二个银行也需要进行实验,否则两个银行的维护时间就会相同,于是我们将所有客户存放资料的两个银行,如果满足上面的条件,就从第一个银行连一条有向边到第二个银行,表示如果前一个银行开始了维护,那么后面的银行同时也需要进行维护。如果这张有向图是一个 ,那么只需要维护被指向的最后一个银行即可,如果有向图上存在环,就对有向图进行 缩点成一个 ,然后找到出度为 的点中点数最少的环。

过题代码

  1. #include <iostream>
  2. #include <cstdio>
  3. #include <cstdlib>
  4. #include <cmath>
  5. #include <climits>
  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 <bitset>
  15. #include <algorithm>
  16. #include <functional>
  17. #include <iomanip>
  18. using namespace std;
  19. #define LL long long
  20. const int maxn = 100000 + 100;
  21. int n, m, h, v, u, ans_cnt;
  22. int ans[maxn];
  23. int num[maxn];
  24. int top, bcnt, dcnt;
  25. int sta[maxn], dfn[maxn], low[maxn], belong[maxn], deg[maxn];
  26. bool ins[maxn];
  27. int cnt[maxn];
  28. vector<int> G[maxn];
  29. vector<int> GG[maxn];
  30. void dfs(int x) {
  31. dfn[x] = low[x] = ++dcnt;
  32. ins[x] = true;
  33. sta[top++] = x;
  34. int len = G[x].size();
  35. for(int i = 0; i < len; ++i) {
  36. int pos = G[x][i];
  37. if(dfn[pos] == 0) {
  38. dfs(pos);
  39. low[x] = min(low[x], low[pos]);
  40. } else if(ins[pos]) {
  41. low[x] = min(low[x], dfn[pos]);
  42. }
  43. }
  44. if(dfn[x] == low[x]) {
  45. ++bcnt;
  46. int pos;
  47. do {
  48. pos = sta[--top];
  49. ins[pos] = false;
  50. belong[pos] = bcnt;
  51. ++cnt[bcnt];
  52. } while(pos != x);
  53. }
  54. }
  55. void Tarjan() {
  56. bcnt = top = dcnt = 0;
  57. memset(cnt, 0, sizeof(cnt));
  58. memset(deg, 0, sizeof(deg));
  59. memset(dfn, 0, sizeof(dfn));
  60. memset(ins, 0, sizeof(ins));
  61. for(int i = 1; i <= n; ++i) {
  62. if(dfn[i] == 0) {
  63. dfs(i);
  64. }
  65. }
  66. for(int i = 1; i <= bcnt; ++i) {
  67. GG[i].clear();
  68. }
  69. for(int i = 1; i <= n; ++i) {
  70. int len = G[i].size();
  71. for(int j = 0; j < len; ++j) {
  72. int pos = G[i][j];
  73. int u = belong[i];
  74. int v = belong[pos];
  75. if(u != v) {
  76. GG[u].push_back(v);
  77. ++deg[u];
  78. }
  79. }
  80. }
  81. }
  82. int main() {
  83. #ifdef LOCAL
  84. freopen("test.txt", "r", stdin);
  85. // freopen("out.txt", "w", stdout);
  86. #endif // LOCAL
  87. ios::sync_with_stdio(false);
  88. while(scanf("%d%d%d", &n, &m, &h) != EOF) {
  89. ans_cnt = 0;
  90. for(int i = 1; i <= n; ++i) {
  91. G[i].clear();
  92. }
  93. for(int i = 1; i <= n; ++i) {
  94. scanf("%d", &num[i]);
  95. }
  96. for(int i = 0; i < m; ++i) {
  97. scanf("%d%d", &u, &v);
  98. if((num[u] + 1) % h == num[v]) {
  99. G[u].push_back(v);
  100. }
  101. if((num[v] + 1) % h == num[u]) {
  102. G[v].push_back(u);
  103. }
  104. }
  105. Tarjan();
  106. int Min = INT_MAX;
  107. int Index;
  108. for(int i = 1; i <= bcnt; ++i) {
  109. if(deg[i] == 0 && cnt[i] < Min) {
  110. Min = cnt[i];
  111. Index = i;
  112. }
  113. }
  114. for(int i = 1; i <= n; ++i) {
  115. if(belong[i] == Index) {
  116. ans[ans_cnt++] = i;
  117. }
  118. }
  119. printf("%d\n", ans_cnt);
  120. for(int i = 0; i < ans_cnt; ++i) {
  121. if(i != 0) {
  122. printf(" ");
  123. }
  124. printf("%d", ans[i]);
  125. }
  126. printf("\n");
  127. }
  128. return 0;
  129. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注