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 的元素。
思路:分成互不相干的多组数即可
static void solve() {int n = ni(), d = ni();long x = 1;List<long[]> res = new ArrayList<>(100);int cnt = 0;while (n > 0) {int c = (int)(Math.log(n) / Math.log(2));if (c == 0) {res.add(new long[]{1, x});cnt++;break;}n = n - (int)(Math.pow(2, c)) + 1;res.add(new long[]{c, x});x += d;cnt += c;}out.println(cnt);for (long[] p : res) {while (p[0] -- > 0)out.print(p[1] + " ");}}
CF 469 A. Zebras
https://codeforces.com/problemset/problem/949/A
给你一个只包含 01 的字符串 s,长度不超过 2e5。
请你将 s 拆分成若干个子序列(子序列不要求连续),使得每个子序列都是长度为奇数的,从 0 开始的 01 交替串,例如 0 010 01010 等等
如果无法拆分,输出 -1;否则输出组成这些子序列的下标数组(从 1 开始)。可以输出任意一种符合要求的解。
思路:
分奇偶顺序模拟
无解情况:
最终存在偶数串
存在起始为1的串
static void solve() {String s = ns();Deque<List<Integer>> even = new ArrayDeque<>(), odd = new ArrayDeque<>();boolean flag = true;for (int i = 0; i < s.length(); i++) {if (s.charAt(i) == '0') {List<Integer> t = even.isEmpty() ? new ArrayList<>() : even.pop();t.add(i + 1);odd.push(t);} else {if (odd.isEmpty()) {flag = false;break;}List<Integer> t = odd.pop();t.add(i + 1);even.push(t);}}if (!flag || !even.isEmpty()) {out.println(-1);return;}out.println(odd.size());while (!odd.isEmpty()) {var t = odd.pop();out.print(t.size() + " ");for (int x : t)out.print(x + " ");out.println();}}
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
思路:
见代码
import java.util.*;public class Main {public static void main(String[] args) {Scanner sc = new Scanner(System.in);int m = sc.nextInt(), n = sc.nextInt();long can = 1L * n * (n - 1);if (can < m) {System.out.println("NO");} else {System.out.println("YES");label: for (int i = 1; i <= n; i++) {for (int j = i + 1; j <= n; j++) {System.out.println(i + " " + j);if (--m == 0)break label;System.out.println(j + " " + i);if (--m == 0)break label;}}}}}
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)
static int N = 110;static String[] o = new String[2 * N];static char[] res = new char[2 * N];static String[][] a = new String[N][2];static int[][] b = new int[N][2];static int n;static void solve() {n = ni();for (int i = 0; i < 2 * n - 2; i++) {String s = ns();o[i] = s;int len = s.length();if (a[len][0] == null) {a[len][0] = s;b[len][0] = i;}else {a[len][1] = s;b[len][1] = i;}}String s1 = a[n - 1][0] + a[n - 1][1].charAt(n - 2);String s2 = a[n - 1][1] + a[n - 1][0].charAt(n - 2);if (!check(s1)) check(s2);for (int i = 0; i < 2 * n - 2; i++) {out.print(res[i]);}}static boolean check(String s) {for (int i = 1; i < n; i++) {String x = a[i][0], y = a[i][1];String p = s.substring(0, i), q = s.substring(n - i, n);if (x.equals(p) && y.equals(q)) {res[b[i][0]] = 'P';res[b[i][1]] = 'S';} else if (x.equals(q) && y.equals(p)) {res[b[i][1]] = 'P';res[b[i][0]] = 'S';} else {return false;}}return true;}
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最后一组偶数特殊考虑,否则,最后一组奇数特殊考虑
先给奇数分配,再给偶数分配(哪种能选就选哪种(要么单独一个偶数,要么两个奇数))
剩余数字一组即可
static final int N = 100010;static Queue<Integer>[] num = new LinkedList[2];static int n, p, q;static void solve() {n = ni();int all = ni();p = ni();q = all - p;for (int i = 0; i < 2; i++)num[i] = new LinkedList<>();for (int i = 0; i < n; i++) {int x = ni();num[x & 1].offer(x);}int e = num[0].size(), o = num[1].size();if (o < q || (o - q) % 2 != 0 || (o - q) / 2 + e < p) {out.println("NO");return;}out.println("YES");if (p == 0) q--;for (int i = 0; i < q; i++)out.println(1 + " " + num[1].poll());while (p-- > 1) {if (!num[0].isEmpty()) {out.println(1 + " " + num[0].poll());} else {out.println(2 + " " + num[1].poll() + " " + num[1].poll());}}out.print(num[0].size() + num[1].size() + " ");while (!num[0].isEmpty())out.print(num[0].poll() + " ");while (!num[1].isEmpty())out.print(num[1].poll() + " ");}
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
贪心构造,代码不好写
static int N = 100010;static int[] a = new int[N];static int[] f = new int[N];static int n;static void solve() {n = ni();for (int i = 1; i <= n; i++)a[i] = ni();if (n == 1) {out.println(1);return;}int d = a[2] > a[1] ? 1 : (a[2] < a[1] ? -1 : 0);f[1] = d >= 0 ? 1 : 5;boolean flag = true;for (int i = 2; i <= n; i++) {if (a[i] > a[i - 1]) {if (i > 2 && a[i - 1] <= a[i - 2]) {f[i - 1] = 1;if (f[i - 2] == 1)f[i - 1] = 2;}f[i] = f[i - 1] + 1;} else if (a[i] < a[i - 1]) {if (i > 2 && a[i - 1] >= a[i - 2]) {f[i - 1] = 5;if (f[i - 2] == 5)f[i - 1] = 4;}f[i] = f[i - 1] - 1;} else {f[i] = (f[i - 1] - 1) % 3 + 2;}if (f[i] < 1 || f[i] > 5) {flag = false;break;}}if (!flag) out.println(-1);else {for (int i = 1; i <= n; i++)out.print(f[i] + " ");}}
