A - Adjacent Product
题目:
给N个数字 A1 到 AN,定义 Bi = Bi-1 x Bi,按顺序输出 B1 到 BN-1
思路:
直接模拟
package atcoder.beginner.abc346;
import java.io.*;
import java.nio.file.Files;
import java.nio.file.Paths;
public class A {
static void solve() throws IOException {
int n = pInt(in.readLine());
int[] a = pIntArray(0);
for (int i = 0 ; i < n - 1; i ++) out.print(a[i] * a[i + 1] + " ");
}
public static void main(String[] args) throws IOException {
int t = 1;
// t = Integer.parseInt(in.readLine());
while (t -- > 0) {
solve();
}
in.close();
out.flush();
out.close();
}
private static InputStream is = System.in;
private static final BufferedReader in = new BufferedReader(new InputStreamReader(is));
private static final PrintWriter out = new PrintWriter(System.out);
private static int pInt(String s) {
return Integer.parseInt(s);
}
private static long pLong(String s) {
return Long.parseLong(s);
}
private static String[] pStringArray() throws IOException {
return in.readLine().split(" ");
}
private static int[] pIntArray(int start) throws IOException {
String[] s = pStringArray();
int[] arr = new int[start + s.length];
for (int i = start, j = 0; i < arr.length; i++, j ++) {
arr[i] = Integer.parseInt(s[j]);
}
return arr;
}
}
B - Piano
题目:
定义字符串 s
为 wbwbwwbwbwbw
无限次重复,判断是否存在子串包含 W
个 w
字符 和 B
个 b
字符
思路:
题目所给的 W 和 B 加起来最多为 200,那只需要重复上面的字符串到达 400 长度即可;
然后使用 滑动窗口 统计区间内的字符出现次数,满足题目要求就输出 Yes
package atcoder.beginner.abc346;
import java.io.*;
import java.nio.file.Files;
import java.nio.file.Paths;
public class B {
static void solve() throws IOException {
StringBuilder sb = new StringBuilder();
String s = "wbwbwwbwbwbw";
int n = s.length(), repeat = 0;
while (repeat <= 400) {
sb.append(s);
repeat += n;
}
String[] ins = pStringArray();
int w = pInt(ins[0]), b = pInt(ins[1]);
int l = 0, r = w + b - 1, wCnt = 0, bCnt = 0;
for (int i = l; i <= r; i ++) {
if (sb.charAt(i) == 'w') {
wCnt ++;
} else {
bCnt ++;
}
}
while (r < sb.length()) {
if (w == wCnt && b == bCnt) {
out.println("Yes");
return;
}
l ++;
r ++;
if (r == sb.length()) {
break;
}
if (sb.charAt(l - 1) == 'w') {
wCnt --;
} else {
bCnt --;
}
if (sb.charAt(r) == 'w') {
wCnt ++;
} else {
bCnt ++;
}
}
out.println("No");
}
public static void main(String[] args) throws IOException {
int t = 1;
// t = Integer.parseInt(in.readLine());
while (t -- > 0) {
solve();
}
in.close();
out.flush();
out.close();
}
private static InputStream is = System.in;
private static final BufferedReader in = new BufferedReader(new InputStreamReader(is));
private static final PrintWriter out = new PrintWriter(System.out);
private static int pInt(String s) {
return Integer.parseInt(s);
}
private static long pLong(String s) {
return Long.parseLong(s);
}
private static String[] pStringArray() throws IOException {
return in.readLine().split(" ");
}
private static int[] pIntArray(int start) throws IOException {
String[] s = pStringArray();
int[] arr = new int[start + s.length];
for (int i = start, j = 0; i < arr.length; i++, j ++) {
arr[i] = Integer.parseInt(s[j]);
}
return arr;
}
}
C - Σ
题目:
给一个整数 K
,以及 N
个整数的序列 A
,输出从1到 K
中不包含在 A 序列中的整数总和
思路:
K很大,而N比较小,可以先计算 1 到 K 的所有数总和
(
1
+
K
)
⋅
K
2
\frac{(1 + K) \cdot K}{2}
2(1+K)⋅K,然后用集合维护A序列,只有在集合中先前没出现的整数才减去
package atcoder.beginner.abc346;
import java.io.*;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.HashSet;
import java.util.Set;
public class C {
static void solve() throws IOException {
String[] ins = pStringArray();
long n = pLong(ins[0]), k = pLong(ins[1]);
long ans = (1L + k) * k / 2;
Set<Long> st = new HashSet<>();
ins = pStringArray();
for (int i = 0; i < n; i ++) {
long x = pLong(ins[i]);
if (x > k) continue;
if (!st.contains(x)) {
st.add(x);
ans -= x;
}
}
out.println(ans);
}
public static void main(String[] args) throws IOException {
int t = 1;
// t = Integer.parseInt(in.readLine());
while (t -- > 0) {
solve();
}
in.close();
out.flush();
out.close();
}
private static InputStream is = System.in;
private static final BufferedReader in = new BufferedReader(new InputStreamReader(is));
private static final PrintWriter out = new PrintWriter(System.out);
private static int pInt(String s) {
return Integer.parseInt(s);
}
private static long pLong(String s) {
return Long.parseLong(s);
}
private static String[] pStringArray() throws IOException {
return in.readLine().split(" ");
}
private static int[] pIntArray(int start) throws IOException {
String[] s = pStringArray();
int[] arr = new int[start + s.length];
for (int i = start, j = 0; i < arr.length; i++, j ++) {
arr[i] = Integer.parseInt(s[j]);
}
return arr;
}
}
D - Gomamayo Sequence
题目:
给一个长度为 N
且仅由 0
和 1
组成的的字符串 s
,如果只有一对相邻字符对相同那么称该字符串为 好字符串;
对于每个
1
≤
i
≤
N
1\le i \le N
1≤i≤N,可以选择将位置 i
的字符最多取反一次(1变成0,0变成1), 执行操作需要花费
c
o
s
t
i
cost_i
costi ,求将该字符串变成好字符串所需要的最小花费。
思路:
只有一对相邻字符对相同,那么意味着其他部分的字符串为 01
或 10
交替;
假设 i
和 i+1
位置字符相同,
- 前面部分可能为
10101..
或者01010...
- 后面部分可能为
...10101
或者...01010
可以统计每个位置前部分和后面部分转换成 01
交替或者 10
交替的字符串的花费值,然后枚举所有位置,答案为前面部分的花费值加上后面部分的花费值;
package atcoder.beginner.abc346;
import java.io.*;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Arrays;
public class D {
static void solve() throws IOException {
int n = pInt(in.readLine());
String s = in.readLine();
int[] cost = pIntArray(0);
// pre0: 0101... pre1:1010...
long[] pre0 = new long[n + 1], pre1 = new long[n + 1];
// suf0: ...1010 suf1: ...0101
long[] suf0 = new long[n + 1], suf1 = new long[n + 1];
for (int i = 0; i < n; i ++) {
pre0[i + 1] = pre0[i];
pre1[i + 1] = pre1[i];
if (i % 2 == 0) {
if (s.charAt(i) == '0') {
pre1[i + 1] += cost[i];
} else {
pre0[i + 1] += cost[i];
}
} else {
if (s.charAt(i) == '0') {
pre0[i + 1] += cost[i];
} else {
pre1[i + 1] += cost[i];
}
}
}
for (int i = n - 1; i >= 0; i --) {
suf0[i] = suf0[i + 1];
suf1[i] = suf1[i + 1];
if (i % 2 == 0) {
if (s.charAt(i) == '0') {
suf0[i] += cost[i];
} else {
suf1[i] += cost[i];
}
} else {
if (s.charAt(i) == '0') {
suf1[i] += cost[i];
} else {
suf0[i] += cost[i];
}
}
}
long ans = Long.MAX_VALUE;
for (int i = 1; i < n; i ++) {
ans = Math.min(ans, Math.min(pre0[i] + suf0[i], pre1[i] + suf1[i]));
}
out.println(ans);
}
public static void main(String[] args) throws IOException {
int t = 1;
// t = Integer.parseInt(in.readLine());
while (t -- > 0) {
solve();
}
in.close();
out.flush();
out.close();
}
private static InputStream is = System.in;
private static final BufferedReader in = new BufferedReader(new InputStreamReader(is));
private static final PrintWriter out = new PrintWriter(System.out);
private static int pInt(String s) {
return Integer.parseInt(s);
}
private static long pLong(String s) {
return Long.parseLong(s);
}
private static String[] pStringArray() throws IOException {
return in.readLine().split(" ");
}
private static int[] pIntArray(int start) throws IOException {
String[] s = pStringArray();
int[] arr = new int[start + s.length];
for (int i = start, j = 0; i < arr.length; i++, j ++) {
arr[i] = Integer.parseInt(s[j]);
}
return arr;
}
}
E - Paint
题目:
给
H
⋅
W
H \cdot W
H⋅W 的矩阵,每个单元格最开始被涂上颜色 0,执行 M
次操作:
- T1 == 1 给矩阵的第 Ai 行涂上颜色 Xi
- T2 == 2 给矩阵的第 Ai 行涂上颜色 Xi
执行完上述操作后,输出所有颜色的出现次数
思路:
越早涂上去的颜色很可能会被后面的操作被覆盖,而后面涂上去的颜色不会被前面的操作覆盖
因此可以将操作倒序执行,最开始矩阵上没有涂上颜色(设为-1
),越靠后的操作实际上是给对应行/列涂上颜色,比该操作靠前的操作并不会覆盖该操作;
只需要统计每行/列被涂上颜色的数量,就能计算出每次涂上对应颜色的单元格数量;
最后还需要将 0 统计上去。
package atcoder.beginner.abc346;
import java.io.*;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.*;
public class E {
static void solve() throws IOException {
String[] ins = pStringArray();
int H = pInt(ins[0]), W = pInt(ins[1]), M = pInt(ins[2]);
Map<Integer, Long> count = new HashMap<>();
boolean[] row = new boolean[H + 1], col = new boolean[W + 1];
// 操作数组,需要逆序遍历,因此要记录下来
int[][] ops = new int[M][3];
for (int i = 0; i < M; i ++) {
ins = pStringArray();
for (int j = 0; j < 3; j ++) {
ops[i][j] = pInt(ins[j]);
}
}
// 统计已经被上色的行列数量
int colCnt = 0, rowCnt = 0;
for (int i = M - 1; i >= 0; i --) {
int t = ops[i][0], a = ops[i][1], x = ops[i][2];
if (t == 1) {
if (!row[a]) {
row[a] = true;
rowCnt ++;
int finalColCnt = colCnt;
count.compute(x, (key, value) -> {
// 一行的单元格数量W - 已经被上色的列数量
long v = (value == null ? 0 : value) + W - finalColCnt;
return v == 0 ? null : v;
});
}
} else {
if (!col[a]) {
col[a] = true;
colCnt ++;
int finalRowCnt = rowCnt;
count.compute(x, (key, value) -> {
// 一列的单元格数量H - 已经被上色的行数量
long v = (value == null ? 0 : value) + H - finalRowCnt;
return v == 0 ? null : v;
});
}
}
}
// 统计 0 的个数
long sum = (long) H * W;
for (long value : count.values()) {
sum -= value;
}
if (sum != 0) {
count.put(0, count.getOrDefault(0, 0L) + sum);
}
out.println(count.size());
Map.Entry<Integer, Long>[] arr = new Map.Entry[count.size()];
count.entrySet().toArray(arr);
Arrays.sort(arr, Comparator.comparingLong(o -> o.getKey()));
for (int i = 0; i < arr.length; i ++) {
out.println(arr[i].getKey() + " " + arr[i].getValue());
}
}
public static void main(String[] args) throws IOException {
int t = 1;
// t = Integer.parseInt(in.readLine());
while (t -- > 0) {
solve();
}
in.close();
out.flush();
out.close();
}
private static InputStream is = System.in;
private static final BufferedReader in = new BufferedReader(new InputStreamReader(is));
private static final PrintWriter out = new PrintWriter(System.out);
private static int pInt(String s) {
return Integer.parseInt(s);
}
private static long pLong(String s) {
return Long.parseLong(s);
}
private static String[] pStringArray() throws IOException {
return in.readLine().split(" ");
}
private static int[] pIntArray(int start) throws IOException {
String[] s = pStringArray();
int[] arr = new int[start + s.length];
for (int i = start, j = 0; i < arr.length; i++, j ++) {
arr[i] = Integer.parseInt(s[j]);
}
return arr;
}
}