[关闭]
@Dmaxiya 2018-08-17T10:15:40.000000Z 字数 4260 阅读 962

Codeforces Round #474 (Div. 1 + Div. 2)

Codeforces


Contests 链接:Codeforces Round #474 (Div. 1 + Div. 2)
过题数:2
排名:1055/8670

A. Check the string

题意

一个只包含有 abc 三种字符的字符串,字符串分为三段,依次为连续的 a 字符、连续的 b 字符和连续的 c 字符,其中 c 字符的个数等于 a 字符或者 b 字符的个数,问给定的字符串是否满足以上条件。

输入

输入为一个字符串 ,字符串中只包含 abc 三种字符。

输出

如果满足条件,则输出 ,否则输出

样例

输入
aaabccc
输出
YES
提示
c 字符的数量等于 a 字符的数量。
输入
bbacc
输出
NO
提示
c 字符的数量等于 b 字符的数量,但是字符的顺序不正确。
输入
aabc
输出
YES
提示
c 字符的数量等于 b 字符的数量。

题解

按题意检查格式。

过题代码

  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 = 5000 + 100;
  21. int Count[3];
  22. char str[maxn];
  23. int main() {
  24. #ifdef LOCAL
  25. freopen("test.txt", "r", stdin);
  26. // freopen("out.txt", "w", stdout);
  27. #endif // LOCAL
  28. ios::sync_with_stdio(false);
  29. while(scanf("%s", str) != EOF) {
  30. bool flag = true;
  31. int cnt = 0;
  32. memset(Count, 0, sizeof(Count));
  33. for(int i = 0; str[i]; ++i) {
  34. int w = str[i] - 'a';
  35. ++Count[w];
  36. if(cnt + 1 == w) {
  37. ++cnt;
  38. } else if(cnt != w) {
  39. flag = false;
  40. break;
  41. }
  42. }
  43. for(int i = 0; i < 3; ++i) {
  44. if(Count[i] == 0) {
  45. flag = false;
  46. break;
  47. }
  48. }
  49. if(!flag) {
  50. printf("NO\n");
  51. continue;
  52. }
  53. if(Count[2] == Count[0] || Count[1] == Count[2]) {
  54. printf("YES\n");
  55. } else {
  56. printf("NO\n");
  57. }
  58. }
  59. return 0;
  60. }

B. Minimize the error

题意

给定两个长度为 的序列 ,定义两个序列的误差 ,可以对 序列进行 次操作,对 序列进行 次操作,每次操作可以选择序列中任意一个字符,将它的值加 或减 ,问两个序列分别经过 次和 次操作后的最小误差值。

输入

第一行为三个整数 ,第二行为 个整数 ,第三行为 个整数 ,其中

输出

输出修改后两个序列的最小误差值。

样例

输入
2 0 0
1 2
2 3
输出
2
提示
我们无法对两个序列做任何操作,因此
输入
2 1 0
1 2
2 2
输出
0
提示
序列的第一个元素 ,就可以使两个序列的最小误差为
输入
2 5 7
3 4
14 4
输出
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 = 1000 + 100;
  21. int n, k1, k2;
  22. int a[maxn], b[maxn];
  23. priority_queue<int> que;
  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%d", &n, &k1, &k2) != EOF) {
  31. while(!que.empty()) {
  32. que.pop();
  33. }
  34. for(int i = 0; i < n; ++i) {
  35. scanf("%d", &a[i]);
  36. }
  37. for(int i = 0; i < n; ++i) {
  38. scanf("%d", &b[i]);
  39. que.push(abs(a[i] - b[i]));
  40. }
  41. k1 += k2;
  42. for(int i = 0; i < k1; ++i) {
  43. int tmp = que.top();
  44. que.pop();
  45. if(tmp != 0) {
  46. --tmp;
  47. } else {
  48. ++tmp;
  49. }
  50. que.push(tmp);
  51. }
  52. LL ans = 0;
  53. while(!que.empty()) {
  54. LL tmp = que.top();
  55. que.pop();
  56. ans += tmp * tmp;
  57. }
  58. printf("%I64d\n", ans);
  59. }
  60. return 0;
  61. }

C. Subsequence Counting

题意

给定整数 ,构造一个长度为 的序列,这个序列总共有 个非空子序列,要求将所有非空子序列中的子序列最大值减最小值大于等于 的所有子序列删去后,剩下 个子序列。

输入

输入包含两个整数

输出

第一行输出一个整数 ,表示构造出来的序列长度,第二行为 个整数 ,如果无法构造出满足条件的序列,输出

样例

输入
10 5
输出
6
5 50 7 15 6 100
提示
将所有最大值减最小值大于等于 的子序列删除后,剩下的序列为:,还剩下 个子序列。
输入
4 2
输出
4
10 100 1000 10000
提示
将所有最大值减最小值大于等于 的子序列删去后,就是每个数字独立成为一个子序列,个数为

题解

分解成 ,其中 个相同的数字就可以得到 个非空子序列,对于每个 输出 个相同的数字,让任意两个不同的数字间隔为 ,就可以构造出合法的序列,不存在无法构造数列的情况。

过题代码

  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 = 70;
  21. int cnt;
  22. LL x, d;
  23. LL two[maxn];
  24. LL *it;
  25. LL ans[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. two[0] = 1;
  33. for(int i = 1; i < 63; ++i) {
  34. two[i] = two[i - 1] * 2;
  35. }
  36. for(int i = 0; i < 63; ++i) {
  37. --two[i];
  38. }
  39. while(scanf("%I64d%I64d", &x, &d) != EOF) {
  40. bool flag = false;
  41. cnt = 0;
  42. LL n = 0;
  43. while(x != 0) {
  44. it = upper_bound(two, two + 63, x);
  45. --it;
  46. x -= *it;
  47. ans[cnt++] = it - two;
  48. n += ans[cnt - 1];
  49. }
  50. printf("%I64d\n", n);
  51. for(int i = 0; i < cnt; ++i) {
  52. for(int j = 0; j < ans[i]; ++j) {
  53. if(flag) {
  54. printf(" ");
  55. }
  56. printf("%I64d", i * d + 1);
  57. flag = true;
  58. }
  59. }
  60. printf("\n");
  61. }
  62. return 0;
  63. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注