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] + " ");
}
}