Before attempting this problem, you should be comfortable with:
Tree Traversal (DFS) - Used to traverse the tree structure and combine subtree results
Dynamic Programming - Tracking even/odd parity states to ensure valid XOR operation counts
Bit Manipulation (XOR) - Understanding XOR properties, including self-cancellation (a ^ k ^ k = a)
Greedy Algorithms - The optimal greedy approach selects nodes based on delta values
1. Depth First Search
Intuition
A key insight is that applying XOR with k on an edge affects both endpoints. If we apply the operation on the same edge twice, the effects cancel out. This means we can effectively choose any pair of nodes to XOR (not just adjacent ones) by applying operations along the path between them.
For each node, we have two choices: keep its original value or XOR it with k. However, since each operation affects two nodes simultaneously, we must XOR an even number of nodes in total. We use DFS to track two states for each subtree: the maximum sum when an even number of nodes are XORed, and when an odd number are XORed.
Algorithm
Build an adjacency list from the given edges.
Perform a DFS starting from node 0, passing the parent to avoid revisiting.
For each node, maintain a pair res[0] (even XOR count) and res[1] (odd XOR count):
Initially, res[0] = nums[node] and res[1] = nums[node] ^ k.
classSolution{/**
* @param {number[]} nums
* @param {number} k
* @param {number[][]} edges
* @return {number}
*/maximumValueSum(nums, k, edges){const n = nums.length;const adj = Array.from({length: n },()=>[]);for(const[u, v]of edges){
adj[u].push(v);
adj[v].push(u);}constdfs=(node, parent)=>{let res =[nums[node], nums[node]^ k];for(const child of adj[node]){if(child === parent)continue;const cur =dfs(child, node);const tmp =[];
tmp[0]= Math.max(res[0]+ cur[0], res[1]+ cur[1]);
tmp[1]= Math.max(res[1]+ cur[0], res[0]+ cur[1]);
res = tmp;}return res;};returndfs(0,-1)[0];}}
publicclassSolution{privateList<int>[] adj;publiclongMaximumValueSum(int[] nums,int k,int[][] edges){int n = nums.Length;
adj =newList<int>[n];for(int i =0; i < n; i++) adj[i]=newList<int>();foreach(var edge in edges){
adj[edge[0]].Add(edge[1]);
adj[edge[1]].Add(edge[0]);}returnDfs(0,-1, nums, k)[0];}privatelong[]Dfs(int node,int parent,int[] nums,int k){long[] res ={ nums[node], nums[node]^ k };foreach(int child in adj[node]){if(child == parent)continue;long[] cur =Dfs(child, node, nums, k);long[] tmp =newlong[2];
tmp[0]= Math.Max(res[0]+ cur[0], res[1]+ cur[1]);
tmp[1]= Math.Max(res[1]+ cur[0], res[0]+ cur[1]);
res = tmp;}return res;}}
funcmaximumValueSum(nums []int, k int, edges [][]int)int64{
n :=len(nums)
adj :=make([][]int, n)for i :=range adj {
adj[i]=[]int{}}for_, edge :=range edges {
adj[edge[0]]=append(adj[edge[0]], edge[1])
adj[edge[1]]=append(adj[edge[1]], edge[0])}var dfs func(node, parent int)[2]int64
dfs =func(node, parent int)[2]int64{
res :=[2]int64{int64(nums[node]),int64(nums[node]^ k)}for_, child :=range adj[node]{if child == parent {continue}
cur :=dfs(child, node)
tmp :=[2]int64{}
tmp[0]=max64(res[0]+cur[0], res[1]+cur[1])
tmp[1]=max64(res[1]+cur[0], res[0]+cur[1])
res = tmp
}return res
}returndfs(0,-1)[0]}funcmax64(a, b int64)int64{if a > b {return a
}return b
}
class Solution {privatelateinitvar adj: Array<MutableList<Int>>funmaximumValueSum(nums: IntArray, k: Int, edges: Array<IntArray>): Long {val n = nums.size
adj =Array(n){ mutableListOf<Int>()}for(edge in edges){
adj[edge[0]].add(edge[1])
adj[edge[1]].add(edge[0])}returndfs(0,-1, nums, k)[0]}privatefundfs(node: Int, parent: Int, nums: IntArray, k: Int): LongArray {var res =longArrayOf(nums[node].toLong(),(nums[node]xor k).toLong())for(child in adj[node]){if(child == parent)continueval cur =dfs(child, node, nums, k)val tmp =LongArray(2)
tmp[0]=maxOf(res[0]+ cur[0], res[1]+ cur[1])
tmp[1]=maxOf(res[1]+ cur[0], res[0]+ cur[1])
res = tmp
}return res
}}
classSolution{privatevar adj:[[Int]]=[]funcmaximumValueSum(_ nums:[Int],_ k:Int,_ edges:[[Int]])->Int{let n = nums.count
adj =Array(repeating:[Int](), count: n)for edge in edges {
adj[edge[0]].append(edge[1])
adj[edge[1]].append(edge[0])}returndfs(0,-1, nums, k)[0]}privatefuncdfs(_ node:Int,_ parent:Int,_ nums:[Int],_ k:Int)->[Int]{var res =[nums[node], nums[node]^ k]for child in adj[node]{if child == parent {continue}let cur =dfs(child, node, nums, k)var tmp =[Int](repeating:0, count:2)
tmp[0]=max(res[0]+ cur[0], res[1]+ cur[1])
tmp[1]=max(res[1]+ cur[0], res[0]+ cur[1])
res = tmp
}return res
}}
Time & Space Complexity
Time complexity: O(n)
Space complexity: O(n)
2. Dynamic Programming (Top-Down)
Intuition
Since we must XOR an even number of nodes, we can ignore the tree structure entirely and treat this as a selection problem. For each node, we decide whether to XOR it or not, while tracking whether we have selected an odd or even count so far. This naturally leads to a DP formulation where the state is the current index and the parity of nodes XORed.
Algorithm
Create a memoization table dp[i][xorCnt] where i is the node index and xorCnt is 0 (even) or 1 (odd).
Base case: dp[n][0] = 0 (valid: even count at the end) and dp[n][1] = -infinity (invalid: odd count).
For each position i, recursively compute:
Option 1: Keep nums[i] as is, add to dfs(i + 1, xorCnt).
Option 2: Use nums[i] ^ k, add to dfs(i + 1, xorCnt ^ 1) (toggle parity).
Take the maximum of both options.
Return dfs(0, 0) to get the maximum sum starting with even parity.
classSolution{/**
* @param {number[]} nums
* @param {number} k
* @param {number[][]} edges
* @return {number}
*/maximumValueSum(nums, k, edges){const n = nums.length;const dp = Array.from({length: n +1},()=>[null,null]);
dp[n][0]=0;
dp[n][1]=-Infinity;constdfs=(i, xorCnt)=>{if(dp[i][xorCnt]!==null)return dp[i][xorCnt];let res = nums[i]+dfs(i +1, xorCnt);
res = Math.max(res,(nums[i]^ k)+dfs(i +1, xorCnt ^1));return(dp[i][xorCnt]= res);};returndfs(0,0);}}
publicclassSolution{privatelong[][] dp;publiclongMaximumValueSum(int[] nums,int k,int[][] edges){int n = nums.Length;
dp =newlong[n +1][];for(int i =0; i <= n; i++){
dp[i]=newlong[]{long.MinValue,long.MinValue };}
dp[n][0]=0;
dp[n][1]=int.MinValue;returnDfs(0,0, nums, k);}privatelongDfs(int i,int xorCnt,int[] nums,int k){if(dp[i][xorCnt]!=long.MinValue){return dp[i][xorCnt];}long res = nums[i]+Dfs(i +1, xorCnt, nums, k);
res = Math.Max(res,(nums[i]^ k)+Dfs(i +1, xorCnt ^1, nums, k));return dp[i][xorCnt]= res;}}
funcmaximumValueSum(nums []int, k int, edges [][]int)int64{
n :=len(nums)
dp :=make([][2]int64, n+1)for i :=range dp {
dp[i]=[2]int64{math.MinInt64, math.MinInt64}}
dp[n][0]=0
dp[n][1]= math.MinInt32
var dfs func(i, xorCnt int)int64
dfs =func(i, xorCnt int)int64{if dp[i][xorCnt]!= math.MinInt64 {return dp[i][xorCnt]}
res :=int64(nums[i])+dfs(i+1, xorCnt)
res =max64(res,int64(nums[i]^k)+dfs(i+1, xorCnt^1))
dp[i][xorCnt]= res
return res
}returndfs(0,0)}funcmax64(a, b int64)int64{if a > b {return a
}return b
}
class Solution {privatelateinitvar dp: Array<LongArray>funmaximumValueSum(nums: IntArray, k: Int, edges: Array<IntArray>): Long {val n = nums.size
dp =Array(n +1){LongArray(2){ Long.MIN_VALUE }}
dp[n][0]=0
dp[n][1]= Int.MIN_VALUE.toLong()returndfs(0,0, nums, k)}privatefundfs(i: Int, xorCnt: Int, nums: IntArray, k: Int): Long {if(dp[i][xorCnt]!= Long.MIN_VALUE){return dp[i][xorCnt]}var res = nums[i]+dfs(i +1, xorCnt, nums, k)
res =maxOf(res,(nums[i]xor k)+dfs(i +1, xorCnt xor1, nums, k))
dp[i][xorCnt]= res
return res
}}
classSolution{privatevar dp:[[Int?]]=[]funcmaximumValueSum(_ nums:[Int],_ k:Int,_ edges:[[Int]])->Int{let n = nums.count
dp =Array(repeating:[nil,nil], count: n +1)
dp[n][0]=0
dp[n][1]=Int.min /2returndfs(0,0, nums, k)}privatefuncdfs(_ i:Int,_ xorCnt:Int,_ nums:[Int],_ k:Int)->Int{iflet cached = dp[i][xorCnt]{return cached
}var res = nums[i]+dfs(i +1, xorCnt, nums, k)
res =max(res,(nums[i]^ k)+dfs(i +1, xorCnt ^1, nums, k))
dp[i][xorCnt]= res
return res
}}
Time & Space Complexity
Time complexity: O(n)
Space complexity: O(n)
3. Dynamic Programming (Bottom-Up)
Intuition
This is the iterative version of the top-down approach. Instead of using recursion with memoization, we fill the DP table from the end to the beginning. At each position, we compute the best sum for both even and odd XOR counts based on the values already computed for subsequent positions.
Algorithm
Create a DP table dp[i][0] and dp[i][1] for each index.
publicclassSolution{publiclongmaximumValueSum(int[] nums,int k,int[][] edges){int n = nums.length;long[][] dp =newlong[n +1][2];
dp[n][1]=Integer.MIN_VALUE;for(int i = n -1; i >=0; i--){
dp[i][0]=Math.max(nums[i]+ dp[i +1][0],(nums[i]^ k)+ dp[i +1][1]);
dp[i][1]=Math.max(nums[i]+ dp[i +1][1],(nums[i]^ k)+ dp[i +1][0]);}return dp[0][0];}}
classSolution{public:longlongmaximumValueSum(vector<int>& nums,int k, vector<vector<int>>& edges){int n = nums.size();
vector<vector<longlong>>dp(n +1,vector<longlong>(2));
dp[n][1]= INT_MIN;for(int i = n -1; i >=0; i--){
dp[i][0]=max(nums[i]+ dp[i +1][0],(nums[i]^ k)+ dp[i +1][1]);
dp[i][1]=max(nums[i]+ dp[i +1][1],(nums[i]^ k)+ dp[i +1][0]);}return dp[0][0];}};
classSolution{/**
* @param {number[]} nums
* @param {number} k
* @param {number[][]} edges
* @return {number}
*/maximumValueSum(nums, k, edges){const n = nums.length;const dp = Array.from({length: n +1},()=>[0,0]);
dp[n][1]=-Infinity;for(let i = n -1; i >=0; i--){
dp[i][0]= Math.max(
nums[i]+ dp[i +1][0],(nums[i]^ k)+ dp[i +1][1],);
dp[i][1]= Math.max(
nums[i]+ dp[i +1][1],(nums[i]^ k)+ dp[i +1][0],);}return dp[0][0];}}
publicclassSolution{publiclongMaximumValueSum(int[] nums,int k,int[][] edges){int n = nums.Length;long[][] dp =newlong[n +1][];for(int i =0; i <= n; i++){
dp[i]=newlong[2];}
dp[n][1]=int.MinValue;for(int i = n -1; i >=0; i--){
dp[i][0]= Math.Max(nums[i]+ dp[i +1][0],(nums[i]^ k)+ dp[i +1][1]);
dp[i][1]= Math.Max(nums[i]+ dp[i +1][1],(nums[i]^ k)+ dp[i +1][0]);}return dp[0][0];}}
funcmaximumValueSum(nums []int, k int, edges [][]int)int64{
n :=len(nums)
dp :=make([][2]int64, n+1)
dp[n][1]= math.MinInt32
for i := n -1; i >=0; i--{
dp[i][0]=max64(int64(nums[i])+dp[i+1][0],int64(nums[i]^k)+dp[i+1][1])
dp[i][1]=max64(int64(nums[i])+dp[i+1][1],int64(nums[i]^k)+dp[i+1][0])}return dp[0][0]}funcmax64(a, b int64)int64{if a > b {return a
}return b
}
class Solution {funmaximumValueSum(nums: IntArray, k: Int, edges: Array<IntArray>): Long {val n = nums.size
val dp =Array(n +1){LongArray(2)}
dp[n][1]= Int.MIN_VALUE.toLong()for(i in n -1 downTo 0){
dp[i][0]=maxOf(nums[i]+ dp[i +1][0],(nums[i]xor k)+ dp[i +1][1])
dp[i][1]=maxOf(nums[i]+ dp[i +1][1],(nums[i]xor k)+ dp[i +1][0])}return dp[0][0]}}
classSolution{funcmaximumValueSum(_ nums:[Int],_ k:Int,_ edges:[[Int]])->Int{let n = nums.count
var dp =[[Int]](repeating:[0,0], count: n +1)
dp[n][1]=Int.min /2for i instride(from: n -1, through:0, by:-1){
dp[i][0]=max(nums[i]+ dp[i +1][0],(nums[i]^ k)+ dp[i +1][1])
dp[i][1]=max(nums[i]+ dp[i +1][1],(nums[i]^ k)+ dp[i +1][0])}return dp[0][0]}}
Time & Space Complexity
Time complexity: O(n)
Space complexity: O(n)
4. Dynamic Programming (Space Optimized)
Intuition
In the bottom-up approach, each state only depends on the immediately next state. This means we do not need to store the entire DP table. We can reduce space by keeping only two variables: one for even parity and one for odd parity, updating them as we process each element.
Algorithm
Initialize dp = [0, -infinity] representing even and odd XOR counts.
publicclassSolution{publiclongmaximumValueSum(int[] nums,int k,int[][] edges){int n = nums.length;long[] dp ={0,Long.MIN_VALUE};for(int i = n -1; i >=0; i--){long[] nextDp =newlong[2];
nextDp[0]=Math.max(nums[i]+ dp[0],(nums[i]^ k)+ dp[1]);
nextDp[1]=Math.max(nums[i]+ dp[1],(nums[i]^ k)+ dp[0]);
dp = nextDp;}return dp[0];}}
classSolution{public:longlongmaximumValueSum(vector<int>& nums,int k, vector<vector<int>>& edges){int n = nums.size();
vector<longlong> dp ={0, LLONG_MIN};for(int i = n -1; i >=0; i--){
vector<longlong>nextDp(2);
nextDp[0]=max(nums[i]+ dp[0],(nums[i]^ k)+ dp[1]);
nextDp[1]=max(nums[i]+ dp[1],(nums[i]^ k)+ dp[0]);
dp = nextDp;}return dp[0];}};
classSolution{/**
* @param {number[]} nums
* @param {number} k
* @param {number[][]} edges
* @return {number}
*/maximumValueSum(nums, k, edges){const n = nums.length;let dp =[0,-Infinity];for(let i = n -1; i >=0; i--){let nextDp =[0,0];
nextDp[0]= Math.max(nums[i]+ dp[0],(nums[i]^ k)+ dp[1]);
nextDp[1]= Math.max(nums[i]+ dp[1],(nums[i]^ k)+ dp[0]);
dp = nextDp;}return dp[0];}}
publicclassSolution{publiclongMaximumValueSum(int[] nums,int k,int[][] edges){int n = nums.Length;long[] dp ={0,long.MinValue };for(int i = n -1; i >=0; i--){long[] nextDp =newlong[2];
nextDp[0]= Math.Max(nums[i]+ dp[0],(nums[i]^ k)+ dp[1]);
nextDp[1]= Math.Max(nums[i]+ dp[1],(nums[i]^ k)+ dp[0]);
dp = nextDp;}return dp[0];}}
funcmaximumValueSum(nums []int, k int, edges [][]int)int64{
n :=len(nums)
dp :=[2]int64{0, math.MinInt64}for i := n -1; i >=0; i--{
nextDp :=[2]int64{}
nextDp[0]=max64(int64(nums[i])+dp[0],int64(nums[i]^k)+dp[1])
nextDp[1]=max64(int64(nums[i])+dp[1],int64(nums[i]^k)+dp[0])
dp = nextDp
}return dp[0]}funcmax64(a, b int64)int64{if a > b {return a
}return b
}
class Solution {funmaximumValueSum(nums: IntArray, k: Int, edges: Array<IntArray>): Long {val n = nums.size
var dp =longArrayOf(0, Long.MIN_VALUE)for(i in n -1 downTo 0){val nextDp =LongArray(2)
nextDp[0]=maxOf(nums[i]+ dp[0],(nums[i]xor k)+ dp[1])
nextDp[1]=maxOf(nums[i]+ dp[1],(nums[i]xor k)+ dp[0])
dp = nextDp
}return dp[0]}}
classSolution{funcmaximumValueSum(_ nums:[Int],_ k:Int,_ edges:[[Int]])->Int{let n = nums.count
var dp =[0,Int.min /2]for i instride(from: n -1, through:0, by:-1){var nextDp =[0,0]
nextDp[0]=max(nums[i]+ dp[0],(nums[i]^ k)+ dp[1])
nextDp[1]=max(nums[i]+ dp[1],(nums[i]^ k)+ dp[0])
dp = nextDp
}return dp[0]}}
Time & Space Complexity
Time complexity: O(n)
Space complexity: O(1) extra space.
5. Greedy
Intuition
For each node, compute the delta: (nums[i] ^ k) - nums[i]. A positive delta means XORing that node increases the sum. Since we must XOR an even number of nodes, we greedily pick pairs of nodes with the highest combined deltas. We sort deltas in descending order and take pairs as long as their sum is positive.
Algorithm
Compute delta[i] = (nums[i] ^ k) - nums[i] for each node.
Sort deltas in descending order.
Start with res = sum(nums).
Iterate through deltas in pairs (indices 0-1, 2-3, etc.):
If delta[i] + delta[i+1] > 0, add this sum to res.
Otherwise, stop (remaining pairs will also be non-positive).
classSolution:defmaximumValueSum(self, nums: List[int], k:int, edges: List[List[int]])->int:
delta =[(num ^ k)- num for num in nums]
delta.sort(reverse=True)
res =sum(nums)for i inrange(0,len(nums),2):if i ==len(nums)-1:break
path_delta = delta[i]+ delta[i +1]if path_delta <=0:break
res += path_delta
return res
publicclassSolution{publiclongmaximumValueSum(int[] nums,int k,int[][] edges){int n = nums.length;int[] delta =newint[n];long res =0;for(int i =0; i < n; i++){
res += nums[i];
delta[i]=(nums[i]^ k)- nums[i];}Arrays.sort(delta);for(int i = n -1; i >0; i -=2){int pathDelta = delta[i]+ delta[i -1];if(pathDelta <=0){break;}
res += pathDelta;}return res;}}
classSolution{public:longlongmaximumValueSum(vector<int>& nums,int k, vector<vector<int>>& edges){int n = nums.size();
vector<int>delta(n);longlong res =0;for(int i =0; i < n; i++){
res += nums[i];
delta[i]=(nums[i]^ k)- nums[i];}sort(delta.rbegin(), delta.rend());for(int i =0; i +1< n; i +=2){int pathDelta = delta[i]+ delta[i +1];if(pathDelta <=0){break;}
res += pathDelta;}return res;}};
classSolution{/**
* @param {number[]} nums
* @param {number} k
* @param {number[][]} edges
* @return {number}
*/maximumValueSum(nums, k, edges){const n = nums.length;let res =0;let delta =[];for(let i =0; i < n; i++){
res += nums[i];
delta.push((nums[i]^ k)- nums[i]);}
delta.sort((a, b)=> b - a);for(let i =0; i +1< n; i +=2){let pathDelta = delta[i]+ delta[i +1];if(pathDelta <=0){break;}
res += pathDelta;}return res;}}
publicclassSolution{publiclongMaximumValueSum(int[] nums,int k,int[][] edges){int n = nums.Length;int[] delta =newint[n];long res =0;for(int i =0; i < n; i++){
res += nums[i];
delta[i]=(nums[i]^ k)- nums[i];}
Array.Sort(delta);
Array.Reverse(delta);for(int i =0; i +1< n; i +=2){int pathDelta = delta[i]+ delta[i +1];if(pathDelta <=0)break;
res += pathDelta;}return res;}}
import"sort"funcmaximumValueSum(nums []int, k int, edges [][]int)int64{
n :=len(nums)
delta :=make([]int, n)
res :=int64(0)for i :=0; i < n; i++{
res +=int64(nums[i])
delta[i]=(nums[i]^ k)- nums[i]}
sort.Sort(sort.Reverse(sort.IntSlice(delta)))for i :=0; i+1< n; i +=2{
pathDelta := delta[i]+ delta[i+1]if pathDelta <=0{break}
res +=int64(pathDelta)}return res
}
class Solution {funmaximumValueSum(nums: IntArray, k: Int, edges: Array<IntArray>): Long {val n = nums.size
val delta =IntArray(n)var res =0Lfor(i in0 until n){
res += nums[i]
delta[i]=(nums[i]xor k)- nums[i]}
delta.sortDescending()var i =0while(i +1< n){val pathDelta = delta[i]+ delta[i +1]if(pathDelta <=0)break
res += pathDelta
i +=2}return res
}}
classSolution{funcmaximumValueSum(_ nums:[Int],_ k:Int,_ edges:[[Int]])->Int{let n = nums.count
var delta =[Int](repeating:0, count: n)var res =0for i in0..<n {
res += nums[i]
delta[i]=(nums[i]^ k)- nums[i]}
delta.sort(by:>)var i =0while i +1< n {let pathDelta = delta[i]+ delta[i +1]if pathDelta <=0{break}
res += pathDelta
i +=2}return res
}}
Time & Space Complexity
Time complexity: O(nlogn)
Space complexity: O(n)
6. Greedy (Optimal)
Intuition
We can optimize by avoiding sorting. For each node, greedily add whichever is larger: nums[i] or nums[i] ^ k. Track whether we have XORed an odd or even number of nodes. If odd at the end, we need to undo one operation. The minimum cost to fix parity is the smallest absolute difference |nums[i] ^ k - nums[i]| across all nodes.
Algorithm
Initialize res = 0, xorCnt = 0, and minDiff = infinity.
For each node:
If nums[i] ^ k > nums[i], add nums[i] ^ k to res and toggle xorCnt.
Otherwise, add nums[i] to res.
Update minDiff = min(minDiff, |nums[i] ^ k - nums[i]|).
If xorCnt is odd, subtract minDiff from res to fix parity.
classSolution:defmaximumValueSum(self, nums: List[int], k:int, edges: List[List[int]])->int:
xorCnt = res =0
minDiff =1<<30for num in nums:
xorNum = num ^ k
if xorNum > num:
res += xorNum
xorCnt ^=1else:
res += num
minDiff =min(minDiff,abs(xorNum - num))return res - xorCnt * minDiff
publicclassSolution{publiclongmaximumValueSum(int[] nums,int k,int[][] edges){int xorCnt =0, minDiff =1<<30;long res =0;for(int num : nums){int xorNum = num ^ k;if(xorNum > num){
res += xorNum;
xorCnt ^=1;}else{
res += num;}
minDiff =Math.min(minDiff,Math.abs(xorNum - num));}return res - xorCnt * minDiff;}}
classSolution{public:longlongmaximumValueSum(vector<int>& nums,int k, vector<vector<int>>& edges){int xorCnt =0, minDiff =1<<30;longlong res =0;for(int& num : nums){int xorNum = num ^ k;if(xorNum > num){
res += xorNum;
xorCnt ^=1;}else{
res += num;}
minDiff =min(minDiff,abs(xorNum - num));}return res -(xorCnt * minDiff);}};
classSolution{/**
* @param {number[]} nums
* @param {number} k
* @param {number[][]} edges
* @return {number}
*/maximumValueSum(nums, k, edges){let xorCnt =0,
res =0,
minDiff =1<<30;for(let num of nums){let xorNum = num ^ k;if(xorNum > num){
res += xorNum;
xorCnt ^=1;}else{
res += num;}
minDiff = Math.min(minDiff, Math.abs(xorNum - num));}return res - xorCnt * minDiff;}}
publicclassSolution{publiclongMaximumValueSum(int[] nums,int k,int[][] edges){int xorCnt =0, minDiff =1<<30;long res =0;foreach(int num in nums){int xorNum = num ^ k;if(xorNum > num){
res += xorNum;
xorCnt ^=1;}else{
res += num;}
minDiff = Math.Min(minDiff, Math.Abs(xorNum - num));}return res - xorCnt * minDiff;}}
funcmaximumValueSum(nums []int, k int, edges [][]int)int64{
xorCnt :=0
minDiff :=1<<30
res :=int64(0)for_, num :=range nums {
xorNum := num ^ k
if xorNum > num {
res +=int64(xorNum)
xorCnt ^=1}else{
res +=int64(num)}
diff := xorNum - num
if diff <0{
diff =-diff
}if diff < minDiff {
minDiff = diff
}}return res -int64(xorCnt*minDiff)}
class Solution {funmaximumValueSum(nums: IntArray, k: Int, edges: Array<IntArray>): Long {var xorCnt =0var minDiff =1shl30var res =0Lfor(num in nums){val xorNum = num xor k
if(xorNum > num){
res += xorNum
xorCnt = xorCnt xor1}else{
res += num
}
minDiff =minOf(minDiff, kotlin.math.abs(xorNum - num))}return res - xorCnt * minDiff
}}
classSolution{funcmaximumValueSum(_ nums:[Int],_ k:Int,_ edges:[[Int]])->Int{var xorCnt =0var minDiff =1<<30var res =0for num in nums {let xorNum = num ^ k
if xorNum > num {
res += xorNum
xorCnt ^=1}else{
res += num
}
minDiff =min(minDiff,abs(xorNum - num))}return res - xorCnt * minDiff
}}
Time & Space Complexity
Time complexity: O(n)
Space complexity: O(1) extra space.
Common Pitfalls
Forgetting the Even Parity Constraint
The XOR operation on an edge affects both endpoints simultaneously. This means you must XOR an even number of nodes in total. Forgetting this constraint and greedily XORing any node that benefits individually will produce incorrect results when an odd number of nodes would improve.
Ignoring That Tree Structure Allows Any Pair
A key insight is that applying XOR operations along a path allows you to effectively XOR any pair of nodes, not just adjacent ones. Many solutions incorrectly try to only consider adjacent node pairs, missing that the tree structure enables reaching any two nodes through a sequence of edge operations.
Integer Overflow in Sum Calculations
When summing node values (especially after XOR operations), the total can exceed 32-bit integer limits. Using int instead of long in languages like Java, C++, or C# will cause overflow errors on large inputs.
Incorrectly Computing the Minimum Difference for Parity Fix
In the optimal greedy approach, if an odd number of nodes are XORed, you need to undo one operation. The cost to fix parity is the minimum absolute difference |nums[i] ^ k - nums[i]| across all nodes. A common mistake is taking the minimum gain rather than the minimum absolute difference, or forgetting to track this value during iteration.
Misunderstanding XOR Self-Cancellation
Applying XOR with k twice on the same value returns the original value. Some solutions fail to recognize that repeated operations on the same edge cancel out, leading to unnecessarily complex state tracking or incorrect assumptions about which operations are possible.