Given a binary tree and an LCA, find the number of pairs of nodes that have this LCA?

Consider an infinite binary tree defined as follows.

For a node labeled with the letter v, let its left child be designated 2 * v and its right child 2 * v + 1. The root of the tree is marked as 1.

For given n ranges [a_1, b_1], [a_2, b_2], ... [a_n, b_n], for which (a_i <= b_i) for all i, each range [a_i, b_i] denotes the set of all integers not less than a_i and no more than b_i. For example, [5,9] will represent the set {5,6,7,8,9}.

For some integer T, let S represent the union [a_i, b_i] for all i to n. I need to find the number of unique pairs (regardless of order) of the elements x, y in S such that lca (x, y) = T

(Wikipedia has a pretty good explanation of what a two-node LCA is .)


For example, to enter:

A = {2, 12, 11}
B = {3, 13, 12}
T = 1

The output should be 6. (Ranges: [2,3], [12,13] and [11,12], and their union is the set {2,3,11,12,13}. Of all 20 possible pairs, there are exactly 6 of them ((2,3), (2,13), (3,11), (3,12), (11,13) and (12,13)) have LCA 1.)

And for input:

A = {1,7}
B = {2,15}
T = 3

The output should be 6. (The indicated ranges are [1,2] and [7,15], and their combination is the set {1,2,7,8,9,10,11,12,13, 14,15} Of the 110 possible pairs, exactly 6 of them ((7,12), (7,13), (12,14), (12,15), (13,14) and (13, 15)) have LCA 3. )

+4
source share
1 answer

Well, it's pretty simple to calculate 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);
}

, , , . factory :

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;
}

a Set<Integer>, , .

, addAll :

Set<Integer> unionSet(Set<Integer> ... sets){
    Set<Integer> result = new HashSet<Integer>();
    for(Set<Integer> s: sets)
        result.addAll(s);
    return result;
}

:

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;
}

- , , . , - :

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);
}
+1

Source: https://habr.com/ru/post/1529813/


All Articles