CF 474 C.Subsequence Counting

https://codeforces.com/problemset/problem/960/C
题目描述:
给你两个数 x 和 d,范围在 [1,1e9] 内。定义一个非空子序列 b 是好的,需满足 max(b)-min(b) < d请你构造任意一个满足要求的整数数组 a,要求 a 的长度不超过 1e4,a[i] 均在 [1,1e18] 范围内,且满足:a 恰好有 x 个非空好子序列。(子序列不要求是连续的)
如果无法构造,输出 -1;否则输出 a 的长度和 a 的元素。

思路:分成互不相干的多组数即可

  1. static void solve() {
  2. int n = ni(), d = ni();
  3. long x = 1;
  4. List<long[]> res = new ArrayList<>(100);
  5. int cnt = 0;
  6. while (n > 0) {
  7. int c = (int)(Math.log(n) / Math.log(2));
  8. if (c == 0) {
  9. res.add(new long[]{1, x});
  10. cnt++;
  11. break;
  12. }
  13. n = n - (int)(Math.pow(2, c)) + 1;
  14. res.add(new long[]{c, x});
  15. x += d;
  16. cnt += c;
  17. }
  18. out.println(cnt);
  19. for (long[] p : res) {
  20. while (p[0] -- > 0)
  21. out.print(p[1] + " ");
  22. }
  23. }

CF 469 A. Zebras

https://codeforces.com/problemset/problem/949/A

给你一个只包含 01 的字符串 s,长度不超过 2e5。

请你将 s 拆分成若干个子序列(子序列不要求连续),使得每个子序列都是长度为奇数的,从 0 开始的 01 交替串,例如 0 010 01010 等等

如果无法拆分,输出 -1;否则输出组成这些子序列的下标数组(从 1 开始)。可以输出任意一种符合要求的解。

思路:
分奇偶顺序模拟
无解情况:
最终存在偶数串
存在起始为1的串

  1. static void solve() {
  2. String s = ns();
  3. Deque<List<Integer>> even = new ArrayDeque<>(), odd = new ArrayDeque<>();
  4. boolean flag = true;
  5. for (int i = 0; i < s.length(); i++) {
  6. if (s.charAt(i) == '0') {
  7. List<Integer> t = even.isEmpty() ? new ArrayList<>() : even.pop();
  8. t.add(i + 1);
  9. odd.push(t);
  10. } else {
  11. if (odd.isEmpty()) {
  12. flag = false;
  13. break;
  14. }
  15. List<Integer> t = odd.pop();
  16. t.add(i + 1);
  17. even.push(t);
  18. }
  19. }
  20. if (!flag || !even.isEmpty()) {
  21. out.println(-1);
  22. return;
  23. }
  24. out.println(odd.size());
  25. while (!odd.isEmpty()) {
  26. var t = odd.pop();
  27. out.print(t.size() + " ");
  28. for (int x : t)
  29. out.print(x + " ");
  30. out.println();
  31. }
  32. }

CF 540 E. Yet Another Ball Problem

https://codeforces.com/problemset/problem/1118/E

给你两个数 m 和 n(均在 [2,2e5] 范围内)
请你构造 m 个互不相同的 pair,需满足:
1. 每个 pair 包含两个在 [1,n] 内的不同整数。
2. 两个相邻的 pair,第一个数不能相同,第二个数也不能相同。
如果不能构造,输出 NO,否则输出 YES 和这 m 个 pair

思路:
见代码

  1. import java.util.*;
  2. public class Main {
  3. public static void main(String[] args) {
  4. Scanner sc = new Scanner(System.in);
  5. int m = sc.nextInt(), n = sc.nextInt();
  6. long can = 1L * n * (n - 1);
  7. if (can < m) {
  8. System.out.println("NO");
  9. } else {
  10. System.out.println("YES");
  11. label: for (int i = 1; i <= n; i++) {
  12. for (int j = i + 1; j <= n; j++) {
  13. System.out.println(i + " " + j);
  14. if (--m == 0)
  15. break label;
  16. System.out.println(j + " " + i);
  17. if (--m == 0)
  18. break label;
  19. }
  20. }
  21. }
  22. }
  23. }

CF 1092 C. Prefixes and Suffixes


给你一个整数 n(2<=n<=100) 和 2n-2 个字符串,这 2n-2 个字符串恰好是某个未知的字符串的所有真前缀和真后缀,即长度从1 到 n-1的字符串各有两个。
请按输入顺序回答每个字符串是前缀还是后缀,前缀输出 ‘P’,后缀输出 ‘S’,如果答案不止一种,回答任意一种即可。
字符串均由小写字母组成。

思路:
假设长度为n - 1的串为p, q则原串s = p + q[-1] || q + p[-1]
分别考虑这两种情况哪个符合
时间复杂度:O(n3)

  1. static int N = 110;
  2. static String[] o = new String[2 * N];
  3. static char[] res = new char[2 * N];
  4. static String[][] a = new String[N][2];
  5. static int[][] b = new int[N][2];
  6. static int n;
  7. static void solve() {
  8. n = ni();
  9. for (int i = 0; i < 2 * n - 2; i++) {
  10. String s = ns();
  11. o[i] = s;
  12. int len = s.length();
  13. if (a[len][0] == null) {
  14. a[len][0] = s;
  15. b[len][0] = i;
  16. }
  17. else {
  18. a[len][1] = s;
  19. b[len][1] = i;
  20. }
  21. }
  22. String s1 = a[n - 1][0] + a[n - 1][1].charAt(n - 2);
  23. String s2 = a[n - 1][1] + a[n - 1][0].charAt(n - 2);
  24. if (!check(s1)) check(s2);
  25. for (int i = 0; i < 2 * n - 2; i++) {
  26. out.print(res[i]);
  27. }
  28. }
  29. static boolean check(String s) {
  30. for (int i = 1; i < n; i++) {
  31. String x = a[i][0], y = a[i][1];
  32. String p = s.substring(0, i), q = s.substring(n - i, n);
  33. if (x.equals(p) && y.equals(q)) {
  34. res[b[i][0]] = 'P';
  35. res[b[i][1]] = 'S';
  36. } else if (x.equals(q) && y.equals(p)) {
  37. res[b[i][1]] = 'P';
  38. res[b[i][0]] = 'S';
  39. } else {
  40. return false;
  41. }
  42. }
  43. return true;
  44. }

CF 439 C. Devu and Partitioning of the Array
【易错题】
输入整数 n, k(1<=k<=n<=1e5) 和 p(0<=p<=k),以及 n 个不同的整数表示数组 a(1<=a[i]<=1e9)。

请你将 a 分割为 k 个子序列(子序列不要求连续),使得恰好有 p 个子序列的和均为偶数,k-p 个子序列的和均为奇数。

若不能分割,输出 “NO”;否则输出 “YES” 和 k 行,每行第一个数表示子序列的大小,然后是子序列的数。
输出任意一种合法方案,输出的顺序与输入的顺序无关。

思路:
设k - p = q
设数组中偶数个数为e, 奇数个数为o
需满足o >= q && (o - q) % 2 == 0 && e + (o - q) / 2 >= p
如何快速构造?
p > 0最后一组偶数特殊考虑,否则,最后一组奇数特殊考虑
先给奇数分配,再给偶数分配(哪种能选就选哪种(要么单独一个偶数,要么两个奇数))
剩余数字一组即可

  1. static final int N = 100010;
  2. static Queue<Integer>[] num = new LinkedList[2];
  3. static int n, p, q;
  4. static void solve() {
  5. n = ni();
  6. int all = ni();
  7. p = ni();
  8. q = all - p;
  9. for (int i = 0; i < 2; i++)
  10. num[i] = new LinkedList<>();
  11. for (int i = 0; i < n; i++) {
  12. int x = ni();
  13. num[x & 1].offer(x);
  14. }
  15. int e = num[0].size(), o = num[1].size();
  16. if (o < q || (o - q) % 2 != 0 || (o - q) / 2 + e < p) {
  17. out.println("NO");
  18. return;
  19. }
  20. out.println("YES");
  21. if (p == 0) q--;
  22. for (int i = 0; i < q; i++)
  23. out.println(1 + " " + num[1].poll());
  24. while (p-- > 1) {
  25. if (!num[0].isEmpty()) {
  26. out.println(1 + " " + num[0].poll());
  27. } else {
  28. out.println(2 + " " + num[1].poll() + " " + num[1].poll());
  29. }
  30. }
  31. out.print(num[0].size() + num[1].size() + " ");
  32. while (!num[0].isEmpty())
  33. out.print(num[0].poll() + " ");
  34. while (!num[1].isEmpty())
  35. out.print(num[1].poll() + " ");
  36. }

CF 1032 C. Playing Piano

输入 n (≤1e5) 和一个长为 n 的数组 a (1≤a[i]≤2e5)。
构造一个长为 n 的数组 b,满足:
1. 1≤b[i]≤5;
2. 如果 a[i]3. 如果 a[i]>a[i+1],则 b[i]>b[i+1];
4. 如果 a[i]=a[i+1],则 b[i]≠b[i+1];

如果不存在这样的 b 则输出 -1,否则输出任意一个满足要求的 b。

思路:
https://www.luogu.com.cn/blog/endlesscheng/solution-cf1032c
贪心构造,代码不好写

  1. static int N = 100010;
  2. static int[] a = new int[N];
  3. static int[] f = new int[N];
  4. static int n;
  5. static void solve() {
  6. n = ni();
  7. for (int i = 1; i <= n; i++)
  8. a[i] = ni();
  9. if (n == 1) {
  10. out.println(1);
  11. return;
  12. }
  13. int d = a[2] > a[1] ? 1 : (a[2] < a[1] ? -1 : 0);
  14. f[1] = d >= 0 ? 1 : 5;
  15. boolean flag = true;
  16. for (int i = 2; i <= n; i++) {
  17. if (a[i] > a[i - 1]) {
  18. if (i > 2 && a[i - 1] <= a[i - 2]) {
  19. f[i - 1] = 1;
  20. if (f[i - 2] == 1)
  21. f[i - 1] = 2;
  22. }
  23. f[i] = f[i - 1] + 1;
  24. } else if (a[i] < a[i - 1]) {
  25. if (i > 2 && a[i - 1] >= a[i - 2]) {
  26. f[i - 1] = 5;
  27. if (f[i - 2] == 5)
  28. f[i - 1] = 4;
  29. }
  30. f[i] = f[i - 1] - 1;
  31. } else {
  32. f[i] = (f[i - 1] - 1) % 3 + 2;
  33. }
  34. if (f[i] < 1 || f[i] > 5) {
  35. flag = false;
  36. break;
  37. }
  38. }
  39. if (!flag) out.println(-1);
  40. else {
  41. for (int i = 1; i <= n; i++)
  42. out.print(f[i] + " ");
  43. }
  44. }