diff --git a/content/posts/leetcode.md b/content/posts/leetcode.md index 1656e00..80691fb 100644 --- a/content/posts/leetcode.md +++ b/content/posts/leetcode.md @@ -5989,3 +5989,68 @@ func abs(num int)int{ ### 总结 本题的关键之一在于理解把多余的硬币传上去和从父节点拿硬币从从步数上来说是等价的. 另一重要的等价性就是父节点和一个子节点都有多余硬币, 另一个子节点需要硬币时, 无论是把父节点的硬币分配给子节点还是把另一个子节点多余的硬币分配给子节点, 最终对步数的贡献都是相同的. 因为若把父节点的硬币给子节点(1步), 另一个子节点的硬币要向上传递(2步), 总共要3步. 而将另一个子节点的硬币分给这个子节点(2步), 父节点硬币向上传递(1步)也需要3步. 所以对于每个子树来说, 重要的是其能传递或者需要多少硬币, 至于内部分配情况对于总步数没有影响. + +## day82 2024-05-19 + +### 3068. Find the Maximum Sum of Node Values + +There exists an undirected tree with n nodes numbered 0 to n - 1. You are given a 0-indexed 2D integer array edges of length n - 1, where edges[i] = [ui, vi] indicates that there is an edge between nodes ui and vi in the tree. You are also given a positive integer k, and a 0-indexed array of non-negative integers nums of length n, where nums[i] represents the value of the node numbered i. + +Alice wants the sum of values of tree nodes to be maximum, for which Alice can perform the following operation any number of times (including zero) on the tree: + +Choose any edge [u, v] connecting the nodes u and v, and update their values as follows: +nums[u] = nums[u] XOR k +nums[v] = nums[v] XOR k +Return the maximum possible sum of the values Alice can achieve by performing the operation any number of times. + +![0519eCBsOE5jrZYo](https://testingcf.jsdelivr.net/gh/game-loader/picbase@master/uPic/0519eCBsOE5jrZYo.png) + +### 题解 + +本题为一道难题, 一个关键点在于意识到其实任意两个相邻节点可以同时与k进行异或运算等价于该树中任意两个节点可以同时与k进行异或运算而不影响其他节点的值, 原因在于对任一节点与k异或两次后会恢复原来节点的值, 因此这种与k进行异或的操作相当于具有传递性. 如a,b,c三个节点, a,b连通, b,c连通, a,b与k进行异或操作后, b,c再进行异或操作,此时b的值恢复为原来的值, 相当于a,c与k进行异或操作. 考虑这是一个连通图, 所有节点之间都有路径相连, 因此遍历所有节点将所有与k异或后值会变大的节点异或后的值保存下来, 如果有奇数个则找到与k异或后值变小的节点中减少的值最小的节点, 比较变大节点的增量和减少节点的减量, 根据值较大的节点进行操作. 在本图一定为连通图的情况下, 其实具体的边已经不重要了. 这种"操作"的传递性与昨天的题目在思路上有几分相似之处. 通过传递性去掉了相邻节点的限制, 进而可以直接通过全局的计算直接得到最终结果而不需要诸如动态规划等比较费时费空间的操作. + +### 代码 + +```go +func maximumValueSum(nums []int, k int, edges [][]int) int64 { + mindecrease := 0 + mindec := math.MaxInt + decsum := 0 + incnum := 0 + minincrease := 0 + mininc := math.MaxInt + incsum := 0 + result := 0 + for _,value := range nums{ + xor := value ^ k + if xor > value{ + incamount := xor - value + if incamount < mininc{ + mininc = incamount + minincrease = xor + } + incsum += xor + incnum++ + }else{ + decamount := value - xor + if decamount < mindec{ + mindec = decamount + mindecrease = value + } + decsum += value + } + } + if incnum % 2 == 1{ + if mindec <= mininc{ + result = incsum + decsum - mindecrease + (mindecrease ^ k) + }else{ + result = decsum + incsum - minincrease + (minincrease ^ k) + } + }else{ + result = incsum + decsum + } + return int64(result) + +} + +```