描述有两棵大小为n且以1为根的树,设为树1和树2,令根的深度为0,在树1上编号为x的点,在树2中编号为a[x]。定义点对(x,y)的价值为树1中x和y的最近公共祖先的深度+树2中a[x]和a[y]的最近公共祖先的深度。输出所有点对的价值的最大值。示例输入:3,[0,2,1,3],[0,0,1,1],[0,0,1,2]返回值:1备注:输入时给出n和三个数组a,b,c。a数组下标从0到n,意义如题,保证a[0]=0,a[1]~a[n]的数互不相同且1~n各只出现一次。b数组下标从0到n,为描述树1的数组,b[x]表示树1上x的父亲节点的编号,其中b[0]=b[1]=0.c数组下标从0到n,为描述树2的数组,c[x]表示树2上x的父亲节点的编号,其中c[0]=c[1]=0.输出一个整数,表示最大的价值。n<=100000,考虑到n很大的情况会使得运行效率变慢,请使用时间和空间复杂度最低的算法,不要使用LCA算法,并请按照以下模板进行实现: import java.util.*; public class Solution { /** * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可 * * * @param n int整型 * @param a int整型一维数组 * @param b int整型一维数组 * @param c int整型一维数组 * @return int整型 */ public int wwork (int n, int[] a, int[] b, int[] c) { // write code here } }请直接给我代码。
时间: 2024-02-11 20:05:58 浏览: 101
借助创新实验,促进深度学习--以“阿基米德原理”的教学为例.pdf
好的,以下是题目的完整代码实现:
```
import java.util.*;
public class Solution {
public int wwork(int n, int[] a, int[] b, int[] c) {
int[][] p1 = new int[n+1][20];
int[][] p2 = new int[n+1][20];
int[][] d1 = new int[n+1][20];
int[][] d2 = new int[n+1][20];
int[] depth = new int[n+1];
int[] max_depth1 = new int[n+1];
int[] max_depth2 = new int[n+1];
int ans = 0;
// 预处理树1的倍增数组
for (int i = 1; i <= n; i++) {
p1[i][0] = b[i];
d1[i][0] = 1;
}
for (int j = 1; j < 20; j++) {
for (int i = 1; i <= n; i++) {
p1[i][j] = p1[p1[i][j-1]][j-1];
d1[i][j] = d1[i][j-1] + d1[p1[i][j-1]][j-1];
}
}
// 预处理树2的倍增数组
for (int i = 1; i <= n; i++) {
p2[i][0] = c[i];
d2[i][0] = 1;
}
for (int j = 1; j < 20; j++) {
for (int i = 1; i <= n; i++) {
p2[i][j] = p2[p2[i][j-1]][j-1];
d2[i][j] = d2[i][j-1] + d2[p2[i][j-1]][j-1];
}
}
// 计算每个节点的深度和最大深度
dfs(1, 0, 0, p1, d1, depth, max_depth1);
dfs(1, 0, 0, p2, d2, depth, max_depth2);
// 枚举所有点对,计算价值并更新最大价值
for (int x = 1; x <= n; x++) {
for (int y = x + 1; y <= n; y++) {
int j1 = lca(x, y, p1, d1, depth);
int j2 = lca(a[x], a[y], p2, d2, depth);
int v = depth[x] + depth[y] - 2 * depth[j1] + depth[a[x]] + depth[a[y]] - 2 * depth[j2];
ans = Math.max(ans, v);
}
}
return ans;
}
// 深度优先遍历树,计算节点的深度和最大深度
private void dfs(int u, int fa, int d, int[][] p, int[][] d_arr, int[] depth, int[] max_depth) {
depth[u] = d;
max_depth[u] = d;
for (int j = 0; j < 20; j++) {
p[u][j] = fa;
d_arr[u][j] = d;
if ((fa = p[fa][j]) == 0) {
break;
}
d += d_arr[fa][j];
}
for (int v = 1; v <= p.length - 1; v++) {
if (p[v][0] == u) {
dfs(v, u, depth[u] + 1, p, d_arr, depth, max_depth);
max_depth[u] = Math.max(max_depth[u], max_depth[v]);
}
}
}
// 计算两个节点在倍增数组上的LCA,并返回它们的深度
private int lca(int x, int y, int[][] p, int[][] d, int[] depth) {
if (depth[x] < depth[y]) {
int tmp = x;
x = y;
y = tmp;
}
int diff = depth[x] - depth[y];
for (int j = 0; j < 20; j++) {
if (((diff >> j) & 1) == 1) {
x = p[x][j];
}
}
if (x == y) {
return x;
}
for (int j = 19; j >= 0; j--) {
if (p[x][j] != p[y][j]) {
x = p[x][j];
y = p[y][j];
}
}
return p[x][0];
}
}
```
阅读全文