1+ import java .util .ArrayList ;
2+ import java .util .Arrays ;
3+ import java .util .List ;
4+
5+ public class Solution3544 {
6+ private List <Integer >[] g ;
7+ private int [] nums ;
8+ private int k ;
9+ private long [][][] memo ;
10+
11+ public long subtreeInversionSum (int [][] edges , int [] nums , int k ) {
12+ int n = nums .length ;
13+ this .nums = nums ;
14+ this .k = k ;
15+ g = new ArrayList [n ];
16+ Arrays .setAll (g , e -> new ArrayList <>());
17+ for (int [] e : edges ) {
18+ g [e [0 ]].add (e [1 ]);
19+ g [e [1 ]].add (e [0 ]);
20+ }
21+ memo = new long [n ][k + 1 ][2 ];
22+ for (int i = 0 ; i < n ; i ++) {
23+ for (int j = 0 ; j < k + 1 ; j ++) {
24+ memo [i ][j ][0 ] = Long .MIN_VALUE ;
25+ memo [i ][j ][1 ] = Long .MAX_VALUE ;
26+ }
27+ }
28+ return dfs (0 , -1 , k )[0 ];
29+ }
30+
31+ private long [] dfs (int x , int fa , int d ) {
32+ long mx = nums [x ], mn = nums [x ];
33+ if (memo [x ][d ][0 ] != Long .MIN_VALUE ) return memo [x ][d ];
34+ for (Integer y : g [x ]) {
35+ if (y == fa ) continue ;
36+ long [] sub = dfs (y , x , Math .min (d + 1 , k ));
37+ mx += sub [0 ];
38+ mn += sub [1 ];
39+ }
40+ if (d >= k ) {
41+ long mx2 = -nums [x ], mn2 = -nums [x ];
42+ for (Integer y : g [x ]) {
43+ if (y == fa ) continue ;
44+ long [] sub = dfs (y , x , 1 );
45+ mx2 -= sub [1 ];
46+ mn2 -= sub [0 ];
47+ }
48+ mx = Math .max (mx , mx2 );
49+ mn = Math .min (mn , mn2 );
50+ }
51+ return memo [x ][d ] = new long []{mx , mn };
52+ }
53+ }
54+ /*
55+ 3544. 子树反转和
56+ https://leetcode.cn/problems/subtree-inversion-sum/description/
57+
58+ 第 156 场双周赛 T4。
59+
60+ 给你一棵以节点 0 为根节点包含 n 个节点的无向树,节点编号从 0 到 n - 1。该树由长度为 n - 1 的二维整数数组 edges 表示,其中 edges[i] = [ui, vi] 表示节点 ui 和 vi 之间有一条边。
61+ 同时给你一个整数 k 和长度为 n 的整数数组 nums,其中 nums[i] 表示节点 i 的值。
62+ 你可以对部分节点执行 反转操作 ,该操作需满足以下条件:
63+ - 子树反转操作:
64+ - 当你反转一个节点时,以该节点为根的子树中所有节点的值都乘以 -1。
65+ - 反转之间的距离限制:
66+ - 你只能在一个节点与其他已反转节点“足够远”的情况下反转它。
67+ - 具体而言,如果你反转两个节点 a 和 b,并且其中一个是另一个的祖先(即 LCA(a, b) = a 或 LCA(a, b) = b),那么它们之间的距离(它们之间路径上的边数)必须至少为 k。
68+ 返回应用 反转操作 后树上节点值的 最大可能 总和 。
69+ 在一棵有根树中,某个节点 v 的子树是指所有路径到根节点包含 v 的节点集合。
70+ 提示:
71+ 2 <= n <= 5 * 10^4
72+ edges.length == n - 1
73+ edges[i] = [ui, vi]
74+ 0 <= ui, vi < n
75+ nums.length == n
76+ -5 * 10^4 <= nums[i] <= 5 * 10^4
77+ 1 <= k <= 50
78+ 输入保证 edges 表示的是一棵合法的树。
79+
80+ 树形 DP
81+ 时间复杂度 O(nk)。
82+ 有 O(n) 的做法。
83+ rating 2551 (clist.by)
84+ */
0 commit comments