結果
| 問題 |
No.364 門松木
|
| コンテスト | |
| ユーザー |
|
| 提出日時 | 2016-06-11 09:55:14 |
| 言語 | Java (openjdk 23) |
| 結果 |
AC
|
| 実行時間 | 1,425 ms / 3,000 ms |
| コード長 | 2,414 bytes |
| コンパイル時間 | 2,464 ms |
| コンパイル使用メモリ | 79,436 KB |
| 実行使用メモリ | 359,880 KB |
| 最終ジャッジ日時 | 2024-10-09 12:50:26 |
| 合計ジャッジ時間 | 40,229 ms |
|
ジャッジサーバーID (参考情報) |
judge3 / judge4 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | AC * 3 |
| other | AC * 31 |
ソースコード
package yukicoder;
import java.util.ArrayList;
import java.util.Scanner;
public class Main{
public static void main(String[] args) {
new Main().solve();
}
ArrayList<Integer>[] edges = new ArrayList[50000];
int[] A;
// dp[v][A[u]]:頂点vの子頂点uをvにつないだ時の門松列の総数
int[][] dp = new int[50001][1001];
int[] num_up = new int[50001];// num_up[v]:頂点vの持つ数字より大きい数を持つ子頂点の数
int[] num_down = new int[50001];// num_up[v]:頂点vの持つ数字より小さい数を持つ子頂点の数
int[] sc_down = new int[50001];// sc_up[v]:頂点vの子頂点がvより小さくなるような場合に含める最大の門松列の総数
int[] sc_up = new int[50001];// sc_down[v]:頂点vの子頂点がvより大きくなるな場合に含める最大の門松列の総数
int dfs(int cur, int pre) {
int ret = 0;
for (int i = 0; i < edges[cur].size(); i++) {
int u = edges[cur].get(i);
if (pre != u) {
ret = Math.max(ret, dfs(u, cur));
if (A[cur] > A[u]) {
if (dp[u][A[cur]] >= 0) {
dp[cur][A[u]] = Math.max(sc_up[u] - dp[u][A[cur]], dp[cur][A[u]]);
} else {
dp[cur][A[u]] = Math.max(num_up[u] + sc_up[u], dp[cur][A[u]]);
}
} else if (A[cur] < A[u]) {
if (dp[u][A[cur]] >= 0) {
dp[cur][A[u]] = Math.max(sc_down[u] - dp[u][A[cur]], dp[cur][A[cur]]);
} else {
dp[cur][A[u]] = Math.max(num_down[u] + sc_down[u], dp[cur][A[u]]);
}
}
}
}
for (int i = 1; i <= 1000; i++) {
if (dp[cur][i] >= 0) {
if (A[cur] > i) {
num_down[cur]++;
sc_down[cur] += dp[cur][i];
} else if (A[cur] < i) {
num_up[cur]++;
sc_up[cur] += dp[cur][i];
}
}
}
sc_down[cur] += num_down[cur] * (num_down[cur] - 1) / 2;
sc_up[cur] += num_up[cur] * (num_up[cur] - 1) / 2;
return Math.max(ret, Math.max(sc_down[cur], sc_up[cur]));
}
int N;
void solve() {
Scanner sc = new Scanner(System.in);
N = sc.nextInt();
A = new int[N];
for (int i = 0; i < 50000; i++)
edges[i] = new ArrayList<>();
for (int i = 0; i < dp.length; i++)
for (int j = 0; j < dp[0].length; j++)
dp[i][j] = -1;
for (int i = 0; i < N; i++)
A[i] = sc.nextInt();
for (int i = 0; i < N - 1; i++) {
int x = sc.nextInt() - 1;
int y = sc.nextInt() - 1;
edges[x].add(y);
edges[y].add(x);
}
int ret = dfs(0, -1);
System.out.println(ret);
}
}