rangrange minimum query and lowest common ancestore minimum query and lowest common ancestor

Upload: carolina-narvaez

Post on 07-Aug-2018

224 views

Category:

Documents


0 download

TRANSCRIPT

  • 8/20/2019 RangRange Minimum Query and Lowest Common Ancestore Minimum Query and Lowest Common Ancestor

    1/17

    Range Minimum Query and Lowest

    Common AncestorBy danielp– TopCoder Member  

    Introduction

    The problem of finding the Lowest Common Ancestor (LCA) of a pair of nodes in a

    rooted tree has been studied more carefully in the second part of the 20th century

    and now is fairly basic in algorithmic graph theory. This problem is interesting not

    only for the tricy algorithms that can be used to sol!e it" but for its numerous

    applications in string processing and computational biology" for e#ample" whereLCA is used with suffi# trees or other tree$lie structures. %arel and Tar&an were the

    first to study this problem more attenti!ely and they showed that after linear

    preprocessing of the input tree LCA" 'ueries can be answered in constant time.

    Their wor has since been e#tended" and this tutorial will present many interesting

    approaches that can be used in other inds of problems as well.

    Lets consider a less abstract e#ample of LCA the tree of life. Its a well$nown fact

    that the current habitants of *arth e!ol!ed from other species. This e!ol!ing

    structure can be represented as a tree" in which nodes represent species" and thesons of some node represent the directly e!ol!ed species. +ow species with similar 

    characteristics are di!ided into groups. ,y finding the LCA of some nodes in this

    tree we can actually find the common parent of two species" and we can determine

    that the similar characteristics they share are inherited from that parent.

    -ange inimum /uery (-/) is used on arrays to find the position of an element

    with the minimum !alue between two specified indices. e will see later that the

    LCA problem can be reduced to a restricted !ersion of an -/ problem" in which

    consecuti!e array elements differ by e#actly 1.

    %owe!er" -/s are not only used with LCA. They ha!e an important role in string

    preprocessing" where they are used with suffi# arrays (a new data structure that

    supports string searches almost as fast as suffi# trees" but uses less memory and

    less coding effort).

    In this tutorial we will first tal about -/. e will present many approaches that

    sol!e the problem some slower but easier to code" and others faster. In thesecond part we will tal about the strong relation between LCA and -/. 3irst we

    https://www.topcoder.com/member-profile/danielphttp://www.topcoder.com/tc?module=LinkTracking&link=http://siamdl.aip.org/getabs/servlet/GetabsServlet?prog=normal%26id=SMJCAT000013000002000338000001%26idtype=cvips%26gifs=Yes&refer=http://www.topcoder.com/tc?module=LinkTracking&link=http://siamdl.aip.org/getabs/servlet/GetabsServlet?prog=normal%26id=SMJCAT000013000002000338000001%26idtype=cvips%26gifs=Yes&refer=http://www.topcoder.com/tc?module=LinkTracking&link=http://siamdl.aip.org/getabs/servlet/GetabsServlet?prog=normal%26id=SMJCAT000013000002000338000001%26idtype=cvips%26gifs=Yes&refer=https://www.topcoder.com/member-profile/danielp

  • 8/20/2019 RangRange Minimum Query and Lowest Common Ancestore Minimum Query and Lowest Common Ancestor

    2/17

    will re!iew two easy approaches for LCA that dont use -/4 then show that the

    -/ and LCA problems are e'ui!alent4 and" at the end" well loo at how the -/

    problem can be reduced to its restricted !ersion" as well as show a fast algorithm

    for this particular case.

    +otations

    5uppose that an algorithm has preprocessing time f(n) and 'uery time g(n). The

    notation for the o!erall comple#ity for the algorithm is .

    e will note the position of the element with the minimum !alue in some

    array A between indices i and j withRMQA(i, j).

    The furthest node from the root that is an ancestor of both u and v in some rooted

    tree T is LCAT(u, v).

    -ange inimum /uery(-/)6i!en an array A[0, N-1] find the position of the element with the minimum !alue

    between two gi!en indices.

    Tri!ial algorithms for -/3or e!ery pair of indices (i, j) store the !alue of RMQA(i, j) in a table M[0, N-1][0, N-

    1]. Tri!ial computation will lead us to an  comple#ity. %owe!er" by

    using an easy dynamic programming approach we can reduce the comple#ity

    to . The preprocessing function will loo something lie this

      void  process1(int M[MAXN][MAXN], int A[MAXN], int N)

      {

      int i, j;

      for (i =0; i < N; i++)

      M[i][i] = i;

      for (i = 0; i < N; i++)

      for (j = i + 1; j < N; j++)

      if (A[M[i][j - 1]] < A[j])

      M[i][j] = M[i][j - 1];

      else

      M[i][j] = j;

      }

  • 8/20/2019 RangRange Minimum Query and Lowest Common Ancestore Minimum Query and Lowest Common Ancestor

    3/17

    This tri!ial algorithm is 'uite slow and uses O(N2) memory" so it wont wor for largecases.

     An 78(+)" 8(s'rt(+))9 solution

     An interesting idea is to split the !ector in sq!(N) pieces. e will eep in a

    !ector M[0, sq!(N)-1] the position for the minimum !alue for each section. M canbe easily preprocessed in O(N). %ere is an e#ample

    +ow lets see how can we compute RMQA(i, j). The idea is to get the o!erallminimum from the sq!(N)sections that lie inside the inter!al" and from the end andthe beginning of the first and the last sections that intersect the bounds of theinter!al. To get RMQA(2,") in the abo!e e#ample we shouldcompare A[2]"A[M[1]]" A[#] and A["] and get the position of the minimum !alue.Its easy to see that this algorithm doesnt mae more than 3 $ sq!(N) operationsper 'uery.

    The main ad!antages of this approach are that is to 'uic to code (a plus for

    TopCoder$style competitions) and that you can adapt it to the dynamic !ersion of

    the problem (where you can change the elements of the array between 'ueries).

    5parse Table (5T) algorithm

     A better approach is to preprocess RMQ for sub arrays of length 2% using dynamic

    programming. e will eep an array M[0, N-1][0, &'gN] where M[i][j] is the inde# of 

    the minimum !alue in the sub array starting at iha!ing length 2 j. %ere is an

    e#ample

    3or computing M[i][j] we must search for the minimum !alue in the first and second

    half of the inter!al. Its ob!ious that the small pieces ha!e 2 j 1

     length" so therecurrence is

  • 8/20/2019 RangRange Minimum Query and Lowest Common Ancestore Minimum Query and Lowest Common Ancestor

    4/17

    The preprocessing function will loo something lie this

      void  process2(int M[MAXN][LOGMAXN], int A[MAXN], int N)

      {

      int i, j;

     

    i!i"i#$i%e M  &or "'e i!"er#$s i"' $e!*"' 1

      for (i = 0; i < N; i++)

      M[i][0] = i;

      cop"e #$es &ro s#$$er "o i**er i!"er#$s  for (j = 1; 1

  • 8/20/2019 RangRange Minimum Query and Lowest Common Ancestore Minimum Query and Lowest Common Ancestor

    5/17

    The segment tree has the same structure as a heap" so if we ha!e a node

    numbered . that is not a leaf the left son of . is 2$. and the right son 2$.+1.

    3or sol!ing the -/ problem using segment trees we should use an array M[1, 2 $

    2[&'gN] + 1] where M[i] holds the minimum !alue position in the inter!al assigned to

    node i. At the beginning all elements in M should be -1. The tree should be

    initiali;ed with the following function (/ and  are the bounds of the current

    inter!al)

      void  i!i"i#$i%e(int!o.e, int , int e, int M[MAX/N],int A[MAXN], int N)

      {

      if ( == e)

      M[!o.e] = ;

      else

      {

      cop"e "'e #$es i! "'e $e&" #!. ri*'" s"rees

      i!i"i#$i%e(2 !o.e, , ( + e) 2, M, A, N);

      i!i"i#$i%e(2 !o.e + 1, ( + e) 2 + 1, e, M,

    A, N);

      se#rc' &or "'e i!i #$e i! "'e &irs" #!.

    seco!. '#$& o& "'e i!"er#$

      if (A[M[2 !o.e]]

  • 8/20/2019 RangRange Minimum Query and Lowest Common Ancestore Minimum Query and Lowest Common Ancestor

    6/17

      }

    The function abo!e reflects the way the tree is constructed. hen calculating theminimum position for some inter!al we should loo at the !alues of the sons.

  • 8/20/2019 RangRange Minimum Query and Lowest Common Ancestore Minimum Query and Lowest Common Ancestor

    7/17

     algorithm. 5egment trees are !erypowerful" not only because they can be used for -/. They are a !ery fle#ible data

    structure" can sol!e e!en the dynamic !ersion of -/ problem" and ha!e

    numerous applications in range searching problems.

    Lowest Common Ancestor (LCA)

    6i!en a rooted tree T and two nodes u and v, find the furthest node from the root

    that is an ancestor for bothu and v. %ere is an e#ample (the root of the tree will be

    node 1 for all e#amples in this editorial)

     An 78(+)" 8(s'rt(+))9 solution

    >i!iding our input into e'ual$si;ed parts pro!es to be an interesting way to sol!e

    the -/ problem. This method can be adapted for the LCA problem as well. The

    idea is to split the tree in sq!() parts" were  is the height of the tree. Thus" the

    first section will contain the le!els numbered from 0 !' sq!() 1" the second will

    contain the le!els numbered from sq!() !' 2 $ sq!() 1" and so on. %ere ishow the tree in the e#ample should be di!ided

  • 8/20/2019 RangRange Minimum Query and Lowest Common Ancestore Minimum Query and Lowest Common Ancestor

    8/17

    +ow" for each node" we should now the ancestor that is situated on the last le!el

    of the upper ne#t section. e will preprocess this !alues in an array [1, MA4N].

    %ere is how  should loo lie for the tree in the e#ample (for simplity" for e!ery

    node i in the first section let [i] * 1)

    +otice that for the nodes situated on the le!els that are the first ones in some

    sections" [i] * T[i]. e can preprocess  using a depth first search (T[i] is the

    father of node i in the tree" n  is [sq!()] and L[i] is the le!el of the node i)

      void  .&s(int !o.e, int 8[MAXN], int N, int 9[MAXN], int 

    L[MAXN], int !r) {

      int :;

     

    i& !o.e is si"#"e. i! "'e &irs"

    sec"io! "'e! P[node] = 1

      i& !o.e is si"#"e. #" "'e e*i!!i!*

      o& soe sec"io! "'e! P[node] = T[node]

  • 8/20/2019 RangRange Minimum Query and Lowest Common Ancestore Minimum Query and Lowest Common Ancestor

    9/17

      i& !o!e o& "'ose "o c#ses occrs, "'e!

    P[node] = P[T[node]]

      if (L[!o.e] < !r)

      9[!o.e] = 1;

      else

      if((L[!o.e] !r))

      9[!o.e] = 8[!o.e];

      else

      9[!o.e] = 9[8[!o.e]];

     

    for e#c' so! : o& !o.e

      .&s(:, 8, N, 9, L, !r);  }

    +ow" we can easily mae 'ueries. 3or finding LCA(., 5) we we will first find in whatsection it lays" and then tri!ially compute it. %ere is the code

      i!" LA(int 8[MAXN], int 9[MAXN], int L[MAXN], int >,

    int 3)

      {

      #s $o!* #s "'e !o.e i! "'e !e>" sec"io! o&

    > #!. 3 is !o" o!e coo! #!ces"or

      e *e" "'e !o.e si"#"e. o! "'e s#$$er

    $eer c$oser

       while (9[>] = 9[3])

      if (L[>] 5 L[3])

      > = 9[>];

      else

      3 = 9[3];

     

    !o "'e3 #re i! "'e s#e sec"io!, so e "rii#$$3

    cop"e "'e LA

       while (> = 3)

      if (L[>] 5 L[3])

      > = 8[>];

      else

      3 = 8[3];

      return >;

  • 8/20/2019 RangRange Minimum Query and Lowest Common Ancestore Minimum Query and Lowest Common Ancestor

    10/17

      }

    This function maes at most 2 $ sq!() operations. =sing this approach we getan algorithm" where  is the height of the tree. In the worst

    case * N" so the o!erall comple#ity is . The main ad!antageof this algorithm is 'uic coding (an a!erage >i!ision 1 coder shouldnt need morethan 1? minutes to code it).

     Another easy solution in 78(+ log+" 8(log+)9

    If we need a faster solution for this problem we could use dynamic programming.

    3irst" lets compute a table @1"+B1"log+B where @iB&B is the 2 &$th ancestor of i. 3or

    computing this !alue we may use the following recursion

    The preprocessing function should loo lie this

      void  process?(int N, int 8[MAXN], int 9[MAXN][LOGMAXN])

      {

      int i, j;

     

    e i!i"i#$i%e eer3 e$ee!" i! 9 i"' -1

      for (i = 0; i < N; i++)

      for (j = 0; 1

  • 8/20/2019 RangRange Minimum Query and Lowest Common Ancestore Minimum Query and Lowest Common Ancestor

    11/17

    searching for LCA(6 * [6][j], q * [q][j]). At the end" both 6 and q will ha!e thesame father" so return T[6]. Lets see what happens if L[6] 7* L[q]. Assume"without loss of generality" that L[6] < L[q]. e can use the same meta$binarysearch for finding the ancestor of 6 situated on the same le!el with q" and then wecan compute the LCA  as described below. %ere is how the 'uery function should

    loo

      int er3(int N, int 9[MAXN][LOGMAXN], int 8[MAXN],

    int L[MAXN], int p, int )

      {

      int "p, $o*, i;

     

    i& p is si"#"e. o! # 'i*'er $ee$ "'#! "'e! e s#p

    "'e

      if (L[p] < L[])

      "p = p, p = , = "p;

     

    e cop"e "'e #$e o& [$o*(L[p)]

      for ($o* = 1; 1

  • 8/20/2019 RangRange Minimum Query and Lowest Common Ancestore Minimum Query and Lowest Common Ancestor

    12/17

    algorithm is . This solution is easy to code too" and its fasterthan the pre!ious one.

    -eduction from LCA to -/

    +ow" lets show how we can use -/ for computing LCA 'ueries. Actually" we will

    reduce the LCA problem to -/ in linear time" so e!ery algorithm that sol!es the-/ problem will sol!e the LCA problem too. Lets show how this reduction can be

    done using an e#ample

    clic to enlarge image

    +otice that LCAT(u, v) is the closest node from the root encountered between the

    !isits of u and v during a depth first search of T. 5o" we can consider all nodes

    between any two indices of u and v in the *uler Tour of the tree and then find the

    node situated on the smallest le!el between them. 3or this" we must build three

    arrays

  • 8/20/2019 RangRange Minimum Query and Lowest Common Ancestore Minimum Query and Lowest Common Ancestor

    13/17

    • 8[1, 2$N-1]  the nodes !isited in an *uler Tour of T4 8[i] is the label of i-

    !9 !isited node in the tour 

    • L[1, 2$N-1]  the le!els of the nodes !isited in the *uler Tour4 L[i] is the le!el

    of node 8[i]

    • [1, N] [i] is the inde# of the first occurrence of node i in 8 (any

    occurrence would be good" so its not bad if we consider the first one) Assume that [u] < [v] (otherwise you must swap u and v). Its easy to see thatthe nodes between the first occurrence of u and the first occurrence of v are 8[[u]:[v]]. +ow" we must find the node situated on the smallest le!el. 3or this" we canuse RMQ. 5o" LCAT(u, v) * 8[RMQL([u], [v])] (remember that -/ returns theinde#). %ere is how 8" L and  should loo for the e#ample

    clic to enlarge image+otice that consecuti!e elements in L differ by e#actly 1.

    3rom -/ to LCA

    e ha!e shown that the LCA problem can be reduced to -/ in linear time. %ere

    we will show how we can reduce the -/ problem to LCA. This means that we

    actually can reduce the general -/ to the restricted !ersion of the problem

    (where consecuti!e elements in the array differ by e#actly 1). 3or this we should

    use cartesian trees.

     A Cartesian Tree of an array A[0, N - 1] is a binary tree C(A) whose root is a

    minimum element of A" labeled with the position i of this minimum. The left child of

    the root is the Cartesian Tree of A[0, i - 1] if i > 0" otherwise theres no child. The

    right child is defined similary for A[i + 1, N - 1]. +ote that the Cartesian Tree is not

    necessarily uni'ue if A contains e'ual elements. In this tutorial the first appearance

    of the minimum !alue will be used" thus the Cartesian Tree will be uni'ue. Its easy

    to see now that RMQA(i, j) * LCAC(i, j).

    %ere is an e#ample

  • 8/20/2019 RangRange Minimum Query and Lowest Common Ancestore Minimum Query and Lowest Common Ancestor

    14/17

    +ow we only ha!e to compute C(A) in linear time. This can be done using a stac.

     At the beginning the stac is empty. e will then insert the elements of A in the

    stac. At the i-!9 step A[i] will be added ne#t to the last element in the stac that

    has a smaller or e'ual !alue to A[i]" and all the greater elements will be remo!ed.

    The element that was in the stac on the position of A[i] before the insertion was

    done will become the left son of i" and A[i] will become the right son of the smaller

    element behind him. At e!ery step the first element in the stac is the root of the

    cartesian tree. Its easier to build the tree if the stac will hold the inde#es of the

    elements" and not their !alue.

  • 8/20/2019 RangRange Minimum Query and Lowest Common Ancestore Minimum Query and Lowest Common Ancestor

    15/17

    %ere is how the stac will loo at each step for the e#ample abo!e

    Step Stack Modifications made in the tree

    0 0 0 is the only node in the tree.

    1 0 1

    1 is added at the end of the stack.

     Now, 1 is the right son of 0.

    2 0 2

    2 is added next to 0, and 1 is

    removed (!2" # !1"$. Now, 2 is the

    right son of 0 and the left son of 2 is

    1.

    % %

    !%" is the smallest element in the

    vector so far, so all elements in the

    stack will &e removed and % will

     &ecome the root of the tree. 'he left

    child of % is 0.

    %

    is added next to %, and the right son

    of % is .

    ) % )

    ) is added next to , and the right son

    of is ).

    * % ) *

    * is added next to ), and the right son

    of ) is *.

    +

    % ) *

    +

    + is added next to *, and the right son

    of * is +.

    %

    is added next to %, and all greater

    elements are removed. is now the

    right child of % and the left child of

    is .

    - % -

    - is added next to , and the right son

    of is -.

    +ote that e!ery element in A is only added once and remo!ed at most once" so thecomple#ity of this algorithm is O(N). %ere is how the tree$processing function willloo

      void cop"e8ree(int A[MAXN], int N, int 8[MAXN]) {

      int s"[MAXN], i, :, "op = -1;

     

  • 8/20/2019 RangRange Minimum Query and Lowest Common Ancestore Minimum Query and Lowest Common Ancestor

    16/17

      e s"#r" i"' #! ep"3 s"#c:

      #" s"ep i e i!ser" A[i] i! "'e s"#c:

      for (i = 0; i < N; i++)

      {

      cop"e "'e posi"io! o& "'e &irs" e$ee!" "'#" is

    e#$ or s#$$er "'#! A[i]

      : = "op;

       while (: 5= 0 77 A[s"[:]] 5 A[i])

      :--;

      e o.i&3 "'e "ree #s e>p$#i!e. #oe

      if (: = -1)

      8[i] = s"[:];  if (: < "op)

      8[s"[: + 1]] = i;

      e i!ser" A[i] i! "'e s"#c: #!. reoe

    #!3 i**er e$ee!"s

      s"[++:] = i;

      "op = :;

      }

      "'e &irs" e$ee!" i! "'e s"#c: is "'e roo" o&

    "'e "ree, so i" '#s !o "'er

      8[s"[0]] = -1;

      }

     

     An78(+)" 8(1)9 algorithm for the restricted -/+ow we now that the general -/ problem can be reduced to the restricted!ersion using LCA. %ere" consecuti!e elements in the array differ by e#actly 1. ecan use this and gi!e a fast  algorithm. 3rom now we will sol!e the-/ problem for an array A[0, N - 1] where ;A[i] A[i + 1]; * 1" i * [1, N - 1]. etransform A in a binary array with N-1 elements" where A[i] * A[i] A[i + 1]. Itsob!ious that elements in A can be &ust +1 or -1. +otice that the old !alue of A[i] isnow the sum of A[1]" A[2] .. A[i] plus the old A[0]. %owe!er" we wont need the old!alues from now on.

    To sol!e this restricted !ersion of the problem we need to partition A into blocs of

    si;e & * [(&'g N) 2]. LetA[i] be the minimum !alue for the i-!9 bloc

    in A and =[i] be the position of this minimum !alue in A. ,oth Aand = are N& long.

    +ow" we preprocess A using the 5T algorithm described in 5ection1. This will

    tae O(N& $ &'g(N&)) * O(N) time and space. After this preprocessing we can mae

    'ueries that span o!er se!eral blocs in O(1). It remains now to show how the in$

  • 8/20/2019 RangRange Minimum Query and Lowest Common Ancestore Minimum Query and Lowest Common Ancestor

    17/17

    bloc 'ueries can be made. +ote that the length of a bloc is & * [(&'g N) 2]" which

    is 'uite small. Also" note that A is a binary array. The total number of binary arrays

    of si;e &is 2&*sq!(N). 5o" for each binary bloc of si;e & we need to loc up in a

    table  the !alue for -/ between e!ery pair of indices. This can be tri!ially

    computed in O(sq!(N)$&2)*O(N) time and space. To inde# table " preprocess the

    type of each bloc in A and store it in array T[1, N&]. The bloc type is a binary

    number obtained by replacing $1 with 0 and D1 with 1.

    +ow" to answer RMQA(i, j) we ha!e two cases

    • i and j are in the same bloc" so we use the !alue computed in  and T

    • i and j are in different blocs" so we compute three !alues the minimum

    from i to the end of isbloc using  and T" the minimum of all blocs

    between is and &s bloc using precomputed 'ueries on A and the minimum from

    the begining of js bloc to j" again using T and 4 finally return the position where

    the o!erall minimum is using the three !alues you &ust computed.Conclusion-/ and LCA are strongly related problems that can be reduced one to another.any algorithms can be used to sol!e them" and they can be adapted to other indof problems as well.

    %ere are some training problems for segment trees" LCA and -/