Acwing第41周周赛
前两道题都比较简单,自己在第三道题卡了很久…
1、组合字符串(简单)
简单的一次模拟
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
String s1 = scan.next();
String s2 = scan.next();
StringBuilder ans = new StringBuilder();
int i = 0;
int j = 0;
ans.append(s1.charAt(i++));
while (j == 0) {
if (i >= s1.length()) {
ans.append(s2.charAt(j++));
break;
}
if (s1.charAt(i) < s2.charAt(j)) {
ans.append(s1.charAt(i++));
} else {
ans.append(s2.charAt(j++));
}
}
System.out.println(ans.toString());
}
}
2、消灭老鼠(中等)(直线表示方法)
这道题嘛,考察直线的表示方程,如何用非分数的形式来保存直线?
我们知道斜率可以表示为:
k
=
y
2
−
y
1
x
2
−
x
1
k = \frac{y2-y1}{x2-x1}
k=x2−x1y2−y1
我们用这个斜率和b表示直线:
y
=
y
2
−
y
1
x
2
−
x
1
x
+
b
y = \frac{y2-y1}{x2-x1}x + b
y=x2−x1y2−y1x+b
好,为了避免分数的存在,我们把分母乘开,并把所有项移到同一侧:
(
x
1
−
x
2
)
y
+
(
y
2
−
y
1
)
x
+
(
x
2
−
x
1
)
b
=
0
(x1 - x2)y + (y2-y1)x + (x2 - x1)b = 0
(x1−x2)y+(y2−y1)x+(x2−x1)b=0
好了,这样就得到了非常简单的表达形式,我们只需要求得这三个数,并对三个数约分即可。
import java.util.HashSet;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
int n = scan.nextInt();
// 激光枪所在位置
int x2 = scan.nextInt();
int y2 = scan.nextInt();
int[] mouses = new int[n];
// 计算当前点与与激光枪形成直线,求直线条数即可(去重)
HashSet<String> set = new HashSet<>();
// (y1 - y2) * x + (x2 - x1) * y + (x1 * y2 - x2 * y1) = 0
for (int i = 0; i < n; i++) {
int x1 = scan.nextInt();
int y1 = scan.nextInt();
int a = y1 - y2;
int b = x2 - x1;
int c = x1 * y2 - x2 * y1;
// 三数约分
int div = gcd(a, gcd(b, c));
a /= div;
b /= div;
c /= div;
String tmp = a + "x" + "+" + b + "y" + "+" + c;
set.add(tmp);
}
System.out.println(set.size());
}
public static int gcd(int a, int b) {
return b == 0 ? a : gcd(b, a % b);
}
}
3、树的DFS(困难)(DFS序)
考察的内容很简单,N叉树的前序遍历,但是每查询一次都要去搜索当前根节点,我们发现其实整体的前序遍历顺序的相对位置是不变的,我们只需要从根节点开始遍历一次即可,在这个期间统计好:以每个节点为根节点的子树大小,以及该节点在DFS序中的下标位置,以及DFS序。
import java.util.*;
import java.io.*;
public class Main {
// 记录DFS序
static int[] seq;
// 存储树
static List<Integer>[] Trees;
// 记录每个树节点的子树大小
static int[] size;
// 记录当前根节点在DFS序中的位置
static int[] idx;
// 记录下标
static int index = 0;
static BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
static BufferedWriter out = new BufferedWriter(new OutputStreamWriter(System.out));
public static void main(String[] args) throws IOException{
String[] str = in.readLine().trim().split(" ");
int n = Integer.parseInt(str[0]);
int q = Integer.parseInt(str[1]);
Trees = new LinkedList[n + 1];
seq = new int[n + 1];
size = new int[n + 1];
idx = new int[n + 1];
for (int i = 0; i < n + 1; i++) {
Trees[i] = new LinkedList<>();
}
str = in.readLine().trim().split(" ");
for (int i = 2; i <= n; i++) {
int parent = Integer.parseInt(str[i - 2]);
// 第i号节点的父节点
Trees[parent].add(i);
}
dfs(1);
while (q-- > 0) {
str = in.readLine().trim().split(" ");
int u = Integer.parseInt(str[0]);
int k = Integer.parseInt(str[1]);
if (k > size[u]) out.write("-1\n");
else out.write(seq[idx[u] + k - 1] + "\n");
}
out.flush();
}
static void dfs(int root) {
// 前序遍历
// 更新子树大小
size[root] = 1;
// 记录DFS序
seq[index] = root;
// 记录当前跟节点在DFS序中的位置
idx[root] = index;
// 存储下标更新
index++;
// 遍历所有孩子
for (int next : Trees[root]) {
dfs(next);
// 统计以当前节点为根节点的子树大小(一定要写在中序位置!!)
size[root] += size[next];
}
}
}