Well, it is fairly simple to compute the LCA of two nodes in your notation, using this recursive method:
int lca(int a, int b) {
if(a == b) return a;
if(a < b) return lca(b, a);
return lca(a/2, b);
}
Now to find the union of the sets, we first need to be able to find what set a particular range represents. Lets introduce a factory method for this:
Set<Integer> rangeSet(int a, int b){
Set<Integer> result = new HashSet<Integer>(b-a);
for(int n = a; n <= b; n++) result.add(n);
return result;
}
This will return a Set<Integer>
containing all the integers contained in the range.
To find the union of these sets, just addAll
their elements to one set:
Set<Integer> unionSet(Set<Integer> ... sets){
Set<Integer> result = new HashSet<Integer>();
for(Set<Integer> s: sets)
result.addAll(s);
return result;
}
Now, we need to iterate over all possible pairs in the set:
pairLcaCount(int t, Set<Integer> nodes){
int result = 0;
for(int x: nodes)
for(int y: nodes)
if(x > y && lca(x,y) == t) result++;
return result;
}
Everything else is just glue logic, methods to convert from your input requirements to the ones taken here. For instance, something like:
Set<Integer> unionSetFromBoundsLists(int[] a, int[] b){
Set<Integer> [] ranges = new Set<Integer>[a.length];
for(int idx = 0; idx < ranges.length; idx++)
ranges[idx] = rangeSet(a[idx], b[idx]);
return unionSet(ranges);
}