[关闭]
@Dmaxiya 2018-08-17T10:22:15.000000Z 字数 8006 阅读 1048

Educational Codeforces Round 32

Codeforces


Contests 链接:Educational Codeforces Round 32
过题数:5
排名:266/8563

A. Local Extrema

题意

给定一个长度为 的序列 ,定义极值点表示某个数字 严格大于或小于它左右两边的值,即 或者 ,第一个数字和最后一个数字一定不是极值点,统计序列中极值点的个数。

输入

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

输出

输出序列中极值点的个数。

样例

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

题解

按题意从 跑一遍统计即可。

过题代码

  1. #include <iostream>
  2. #include <cstdio>
  3. #include <cstdlib>
  4. #include <cmath>
  5. #include <climits>
  6. #include <cfloat>
  7. #include <cstring>
  8. #include <string>
  9. #include <vector>
  10. #include <list>
  11. #include <queue>
  12. #include <stack>
  13. #include <map>
  14. #include <set>
  15. #include <bitset>
  16. #include <algorithm>
  17. #include <ctime>
  18. #include <functional>
  19. #include <iomanip>
  20. using namespace std;
  21. #define LL long long
  22. const int maxn = 1000 + 100;
  23. int n;
  24. int num[maxn];
  25. int main() {
  26. #ifdef LOCAL
  27. freopen("test.txt", "r", stdin);
  28. // freopen("out.txt", "w", stdout);
  29. #endif
  30. ios::sync_with_stdio(false);
  31. while(scanf("%d", &n) != EOF) {
  32. int cnt = 0;
  33. for(int i = 1; i <= n; ++i) {
  34. scanf("%d", &num[i]);
  35. }
  36. for(int i = 2; i < n; ++i) {
  37. if((num[i] > num[i - 1] && num[i] > num[i + 1]) || (num[i] < num[i - 1] && num[i] < num[i + 1])) {
  38. ++cnt;
  39. }
  40. }
  41. printf("%d\n", cnt);
  42. }
  43. return 0;
  44. }

B. Buggy Robot

题意

给机器人一个字符串指令,字符串中只包含 四种字符,分别表示上下左右四个方向,机器人的初始位置为 ,而完全正确地执行这些指令可能无法回到原点,问机器人要回到原点最多正确地执行了多少个指令。

输入

第一行为一个整数 表示指令的长度,第二行为一个字符串 ,只包含 四种字符,表示机器人接收到的指令。

输出

输出机器人最终要回到原点,最多正确地执行多少个指令。

样例

输入 输出
4
LDUR
4
5
RRRUU
0
6
LLRRRR
4

题解

统计所有字符出现的次数,分别记为 ,结果就是

过题代码

  1. #include <iostream>
  2. #include <cstdio>
  3. #include <cstdlib>
  4. #include <cmath>
  5. #include <climits>
  6. #include <cfloat>
  7. #include <cstring>
  8. #include <string>
  9. #include <vector>
  10. #include <list>
  11. #include <queue>
  12. #include <stack>
  13. #include <map>
  14. #include <set>
  15. #include <bitset>
  16. #include <algorithm>
  17. #include <ctime>
  18. #include <functional>
  19. #include <iomanip>
  20. using namespace std;
  21. #define LL long long
  22. const int maxn = 100 + 100;
  23. int n;
  24. char str[maxn];
  25. map<char, int> mp;
  26. int main() {
  27. #ifdef LOCAL
  28. freopen("test.txt", "r", stdin);
  29. // freopen("out.txt", "w", stdout);
  30. #endif
  31. ios::sync_with_stdio(false);
  32. while(scanf("%d", &n) != EOF) {
  33. mp.clear();
  34. scanf("%s", str);
  35. for(int i = 0; i < n; ++i) {
  36. ++mp[str[i]];
  37. }
  38. printf("%d\n", 2 * (min(mp['L'], mp['R']) + min(mp['U'], mp['D'])));
  39. }
  40. return 0;
  41. }

C. K-Dominant Character

题意

如果在给定的字符串中,对于任意一个长度不小于 的子串,都包含字符 ,那么这个字符串就是 字符主导的字符串,现在给定一个字符串 ,要求可能满足条件的最小的 值。

输入

输入为一个只包含小写字符的字符串

输出

输出可能满足条件的最小的 值。

样例

输入 输出
abacaba 2
zzzzz 1
abcde 3

题解

对于在字符串中出现的每一个字符,都求出它对应的 值,取最小的那个 就是答案,而对于每一个字符 ,求 值的方法就是将所有距离最近的两个 ,求出它们距离的最大值,最后再对字符串的首尾做一次处理即可。

过题代码

  1. #include <iostream>
  2. #include <cstdio>
  3. #include <cstdlib>
  4. #include <cmath>
  5. #include <climits>
  6. #include <cfloat>
  7. #include <cstring>
  8. #include <string>
  9. #include <vector>
  10. #include <list>
  11. #include <queue>
  12. #include <stack>
  13. #include <map>
  14. #include <set>
  15. #include <bitset>
  16. #include <algorithm>
  17. #include <ctime>
  18. #include <functional>
  19. #include <iomanip>
  20. using namespace std;
  21. #define LL long long
  22. const int maxn = 100000 + 100;
  23. char str[maxn];
  24. int num[30], last[maxn];
  25. int main() {
  26. #ifdef LOCAL
  27. freopen("test.txt", "r", stdin);
  28. // freopen("out.txt", "w", stdout);
  29. #endif
  30. ios::sync_with_stdio(false);
  31. while(scanf("%s", str) != EOF) {
  32. int len = strlen(str);
  33. memset(num, 0, sizeof(num));
  34. memset(last, -1, sizeof(last));
  35. for(int i = 0; str[i]; ++i) {
  36. int w = str[i] - 'a';
  37. num[w] = max(num[w], i - last[w]);
  38. last[w] = i;
  39. }
  40. int ans = maxn;
  41. for(int i = 0; i < 26; ++i) {
  42. if(last[i] != -1) {
  43. num[i] = max(num[i], len - last[i]);
  44. ans = min(ans, num[i]);
  45. }
  46. }
  47. printf("%d\n", ans);
  48. }
  49. return 0;
  50. }

D. Almost Identity Permutations

题意

如果一个 的排列为 ,那么它至少有 个数字满足 ,问给定 ,有多少个这样的序列满足条件。

输入

输入只包含两个整数

输出

输出满足条件的序列的数量。

样例

输入 输出
4 1 1
4 2 7
5 3 31
5 4 76

题解

本题由于 非常小,所以可以对每一个 分类讨论穷举所有情况

  1. 时,有 个数字在原位,那么最后一个数字一定也在原位,所以只有一种情况;
  2. 时,有 个数字在原位,那么最后剩下的两个数字不在原位的情况只有一种,所有情况就是 ,在加上 的情况的方案数就是答案;
  3. 时,除了 的情况,当有 个数字在原位时,剩下 个数字都不在原位的情况只有 种,所以总共有 种情况;
  4. 时,除了 的情况,当有 个数字不在原位时,剩下 个数字不在原位的情况有 种,所以总共有 种情况。

过题代码

  1. #include <iostream>
  2. #include <cstdio>
  3. #include <cstdlib>
  4. #include <cmath>
  5. #include <climits>
  6. #include <cfloat>
  7. #include <cstring>
  8. #include <string>
  9. #include <vector>
  10. #include <list>
  11. #include <queue>
  12. #include <stack>
  13. #include <map>
  14. #include <set>
  15. #include <bitset>
  16. #include <algorithm>
  17. #include <ctime>
  18. #include <functional>
  19. #include <iomanip>
  20. using namespace std;
  21. #define LL long long
  22. const int maxn = 1000 + 100;
  23. int n, k;
  24. LL C[maxn][maxn];
  25. void Init() {
  26. C[0][0] = 1;
  27. for(int i = 1; i < maxn; ++i) {
  28. for(int j = 0; j <= i; ++j) {
  29. if(j == 0 || j == i) {
  30. C[i][j] = 1;
  31. } else {
  32. C[i][j] = C[i - 1][j - 1] + C[i - 1][j];
  33. }
  34. }
  35. }
  36. }
  37. int main() {
  38. #ifdef LOCAL
  39. freopen("test.txt", "r", stdin);
  40. // freopen("out.txt", "w", stdout);
  41. #endif
  42. ios::sync_with_stdio(false);
  43. Init();
  44. while(scanf("%d%d", &n, &k) != EOF) {
  45. LL ans = 0;
  46. if(k >= 1) {
  47. ans += 1;
  48. }
  49. if(k >= 2) {
  50. ans += C[n][2];
  51. }
  52. if(k >= 3) {
  53. ans += C[n][3] * 2;
  54. }
  55. if(k >= 4) {
  56. ans += C[n][4] * 9;
  57. }
  58. printf("%I64d\n", ans);
  59. }
  60. return 0;
  61. }

E. Maximum Subsequence

题意

给定一个长度为 的序列 ,从中选出 个数字,它们的下标分别为 ,要使得 的值最大,求这个最大值。

输入

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

输出

输出答案。

样例

输入 输出 提示
4 4
5 2 4 1
3 可以选择第 和第 个数字,这两个数字对 取模的值为
3 20
199 41 299
19 可以选择第 个数字。

题解

本题如果 枚举每个数字选或者不选的话,总的时间复杂度为 ,肯定要超时,但是可以将整个数组分成两部分进行 次枚举,再对这两部分进行贪心二分求和即可,这样总的时间复杂度可以降到

过题代码

  1. #include <iostream>
  2. #include <cstdio>
  3. #include <cstdlib>
  4. #include <cmath>
  5. #include <climits>
  6. #include <cfloat>
  7. #include <cstring>
  8. #include <string>
  9. #include <vector>
  10. #include <list>
  11. #include <queue>
  12. #include <stack>
  13. #include <map>
  14. #include <set>
  15. #include <bitset>
  16. #include <algorithm>
  17. #include <ctime>
  18. #include <functional>
  19. #include <iomanip>
  20. using namespace std;
  21. #define LL long long
  22. const int maxn = 100;
  23. int n, m, ans;
  24. int num[maxn];
  25. set<int> st[2];
  26. set<int>::iterator it, itt;
  27. void get_st(int begin, int end, set<int> &st) {
  28. st.clear();
  29. st.insert(0);
  30. for(int i = 0; i < (1 << (end - begin)); ++i) {
  31. int tmp = 0;
  32. for(int j = 0; j < end - begin; ++j) {
  33. if(((i >> j) & 1) == 1) {
  34. tmp = (tmp + num[j + begin]) % m;
  35. }
  36. }
  37. st.insert(tmp);
  38. }
  39. }
  40. int main() {
  41. #ifdef LOCAL
  42. freopen("test.txt", "r", stdin);
  43. // freopen("out.txt", "w", stdout);
  44. #endif
  45. ios::sync_with_stdio(false);
  46. while(scanf("%d%d", &n, &m) != EOF) {
  47. ans = 0;
  48. for(int i = 0; i < n; ++i) {
  49. scanf("%d", &num[i]);
  50. }
  51. get_st(0, (n + 1) / 2, st[0]);
  52. get_st((n + 1) / 2, n, st[1]);
  53. for(it = st[0].begin(); it != st[0].end(); ++it) {
  54. for(int i = 1; i <= 2; ++i) {
  55. itt = st[1].lower_bound(m * i - *it);
  56. if(itt != st[1].begin()) {
  57. --itt;
  58. ans = max(ans, (*it + *itt) % m);
  59. }
  60. }
  61. }
  62. printf("%d\n", ans);
  63. }
  64. return 0;
  65. }

G. Xor-MST

题意

给定一个 个节点的完全图,每个节点的权值为 ,任意两个节点之间的边权值为 ,求最小生成树的边权和。

输入

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

输出

输出最小生成树的边权和。

样例

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

题解

由贪心可以知道,高 位都相同的所有数字一定先合并到同一个连通块内,再和高 位相同的数字进行合并,这样得到的异或的和才能最小,因此问题转化为求解在高 位都相同,而第 位不同的情况下,两个子连通块的合并,合并的方式为:对于第 位为 的连通块内的所有数字,查找第 位为 的连通块内的所有数字的异或值最小的那一对数字,暴力是 的,可以用字典树将查找优化到 ,解决了两个连通块之间的连边代价计算之后,再加上两个连通块各自的子连通块(第 位不同的情况)连通的代价,一直递归下去,直到某个连通块不再存在元素或者到达第 位停止递归,总的时间复杂度为

过题代码

  1. #include <iostream>
  2. #include <cstdio>
  3. #include <cstdlib>
  4. #include <cmath>
  5. #include <climits>
  6. #include <cfloat>
  7. #include <cstring>
  8. #include <string>
  9. #include <vector>
  10. #include <list>
  11. #include <queue>
  12. #include <stack>
  13. #include <map>
  14. #include <set>
  15. #include <bitset>
  16. #include <algorithm>
  17. #include <ctime>
  18. #include <functional>
  19. #include <iomanip>
  20. using namespace std;
  21. #define LL long long
  22. const int maxn = 200000 + 100;
  23. const int maxcnt = 200000 * 30 + 100;
  24. struct Tree {
  25. int root, cnt;
  26. int tree[maxcnt][2];
  27. int create() {
  28. ++cnt;
  29. memset(tree[cnt], 0, sizeof(tree[cnt]));
  30. return cnt;
  31. }
  32. void Init() {
  33. cnt = 0;
  34. root = create();
  35. }
  36. int id(int x, int Index) {
  37. return ((x >> Index) & 1);
  38. }
  39. void add(int x) {
  40. int pos = root;
  41. for(int i = 30; i >= 0; --i) {
  42. int w = id(x, i);
  43. if(tree[pos][w] == 0) {
  44. tree[pos][w] = create();
  45. }
  46. pos = tree[pos][w];
  47. }
  48. }
  49. int query(int x) {
  50. int ret = 0;
  51. int pos = root;
  52. for(int i = 30; i >= 0; --i) {
  53. int w = id(x, i);
  54. if(tree[pos][w] == 0) {
  55. w = !w;
  56. ret |= (1 << i);
  57. }
  58. pos = tree[pos][w];
  59. }
  60. return ret;
  61. }
  62. };
  63. int n;
  64. int num[maxn];
  65. Tree t;
  66. LL dfs(int L, int R, int depth) {
  67. if(L + 1 >= R || depth == -1) {
  68. return 0;
  69. }
  70. LL ret = 0;
  71. int M = R;
  72. for(int i = L; i < R; ++i) {
  73. if(((num[i] >> depth) & 1) == 1) {
  74. M = i;
  75. break;
  76. }
  77. }
  78. ret += dfs(L, M, depth - 1) + dfs(M, R, depth - 1);
  79. if(M != L && R != M) {
  80. t.Init();
  81. for(int i = M; i < R; ++i) {
  82. t.add(num[i]);
  83. }
  84. int tmp = INT_MAX;
  85. for(int i = L; i < M; ++i) {
  86. tmp = min(tmp, t.query(num[i]));
  87. }
  88. ret += tmp;
  89. }
  90. return ret;
  91. }
  92. int main() {
  93. #ifdef LOCAL
  94. freopen("test.txt", "r", stdin);
  95. // freopen("out.txt", "w", stdout);
  96. #endif
  97. ios::sync_with_stdio(false);
  98. while(scanf("%d", &n) != EOF) {
  99. for(int i = 1; i <= n; ++i) {
  100. scanf("%d", &num[i]);
  101. }
  102. sort(num + 1, num + 1 + n);
  103. printf("%I64d\n", dfs(1, n + 1, 30));
  104. }
  105. return 0;
  106. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注