1+ import java .util .ArrayList ;
2+ import java .util .Arrays ;
3+ import java .util .List ;
4+
5+ public class Solution3515 {
6+ private List <Integer >[] g ;
7+ private int [] in , out , weight ;
8+ private int clock ;
9+ private BIT tr ;
10+
11+ public int [] treeQueries (int n , int [][] edges , int [][] queries ) {
12+ g = new ArrayList [n + 1 ];
13+ Arrays .setAll (g , e -> new ArrayList <>());
14+ for (int [] e : edges ) {
15+ int x = e [0 ], y = e [1 ];
16+ g [x ].add (y );
17+ g [y ].add (x );
18+ }
19+ in = new int [n + 1 ];
20+ out = new int [n + 1 ];
21+ dfs (1 , 0 );
22+
23+ weight = new int [n + 1 ];
24+ tr = new BIT (n );
25+ for (int [] e : edges ) {
26+ update (e [0 ], e [1 ], e [2 ]);
27+ }
28+
29+ List <Integer > ans = new ArrayList <>();
30+ for (int [] q : queries ) {
31+ if (q [0 ] == 1 ) {
32+ update (q [1 ], q [2 ], q [3 ]);
33+ } else {
34+ ans .add (tr .query (in [q [1 ]]));
35+ }
36+ }
37+ return ans .stream ().mapToInt (i -> i ).toArray ();
38+ }
39+
40+ private void dfs (int x , int fa ) {
41+ in [x ] = ++clock ; // 进来的时间
42+ for (int y : g [x ]) {
43+ if (y == fa ) continue ;
44+ dfs (y , x );
45+ }
46+ out [x ] = clock ; // 离开的时间
47+ }
48+
49+ private void update (int x , int y , int w ) {
50+ // 保证 y 是 x 的儿子
51+ if (in [x ] > in [y ]) {
52+ y = x ;
53+ }
54+ int d = w - weight [y ]; // 边权的增量
55+ weight [y ] = w ;
56+ // 把子树 y 中的最短路长度都增加 d(用差分树状数组维护)
57+ tr .add (in [y ], d );
58+ tr .add (out [y ] + 1 , -d );
59+ }
60+
61+ static class BIT {
62+ int n ;
63+ int [] tree ;
64+
65+ public BIT (int n ) {
66+ this .n = n ;
67+ tree = new int [n + 1 ];
68+ }
69+
70+ int lb (int x ) {
71+ return x & -x ;
72+ }
73+
74+ void add (int pos , int val ) {
75+ for (; pos <= n ; pos += lb (pos )) tree [pos ] += val ;
76+ }
77+
78+ int query (int pos ) {
79+ int ret = 0 ;
80+ for (; pos > 0 ; pos -= lb (pos )) ret += tree [pos ];
81+ return ret ;
82+ }
83+ }
84+ }
85+ /*
86+ 3515. 带权树中的最短路径
87+ https://leetcode.cn/problems/shortest-path-in-a-weighted-tree/description/
88+
89+ 第 154 场双周赛 T4。
90+
91+ 给你一个整数 n 和一个以节点 1 为根的无向带权树,该树包含 n 个编号从 1 到 n 的节点。它由一个长度为 n - 1 的二维数组 edges 表示,其中 edges[i] = [ui, vi, wi] 表示一条从节点 ui 到 vi 的无向边,权重为 wi。
92+ 同时给你一个二维整数数组 queries,长度为 q,其中每个 queries[i] 为以下两种之一:
93+ - [1, u, v, w'] – 更新 节点 u 和 v 之间边的权重为 w',其中 (u, v) 保证是 edges 中存在的边。
94+ - [2, x] – 计算 从根节点 1 到节点 x 的 最短 路径距离。
95+ 返回一个整数数组 answer,其中 answer[i] 是对于第 i 个 [2, x] 查询,从节点 1 到 x 的最短路径距离。
96+ 提示:
97+ 1 <= n <= 10^5
98+ edges.length == n - 1
99+ edges[i] == [ui, vi, wi]
100+ 1 <= ui, vi <= n
101+ 1 <= wi <= 10^4
102+ 输入保证 edges 构成一棵合法的树。
103+ 1 <= queries.length == q <= 10^5
104+ queries[i].length == 2 或 4
105+ - queries[i] == [1, u, v, w'],或者
106+ - queries[i] == [2, x]
107+ - 1 <= u, v, x <= n
108+ - (u, v) 一定是 edges 中的一条边。
109+ - 1 <= w' <= 10^4
110+
111+ DFS 时间戳 + 差分树状数组
112+ https://leetcode.cn/problems/shortest-path-in-a-weighted-tree/solutions/3649372/dfs-shi-jian-chuo-chai-fen-shu-zhuang-sh-h8q3/
113+ rating 2344 (clist.by)
114+ */
0 commit comments