module Data.RangeMin.LCA.Binary (Index, BinTree(..), quickLCABinary, lcaBinary) where
import Data.RangeMin
import Data.RangeMin.Common.Vector
import qualified Data.RangeMin.Mixed as Mix
import qualified Data.RangeMin.LCA as LCA()
import Data.RangeMin.LCA.IndexM
import qualified Data.Vector.Unboxed as UV
import qualified Data.Vector as V
import qualified Data.Vector.Generic as G
import qualified Data.Vector.Fusion.Stream as S
import Prelude hiding (foldr)
data BinTree a = Tip | BinTree a (BinTree a) (BinTree a)
unfoldBin :: BinTree a -> Maybe (a, BinTree a, BinTree a)
unfoldBin (BinTree x l r) = Just (x, l, r)
unfoldBin Tip = Nothing
type Depth = Int
data Trav a = Trav !Depth !Index a
inorderBin :: BinTree a -> (BinTree (Index, a), Int)
inorderBin = execIndexM . trav where
trav Tip = return Tip
trav (BinTree x l r) = do
l' <- trav l
i <- getIndex
r' <- trav r
return (BinTree (i, x) l' r')
inorderD :: (a -> Index) -> BinTree a -> [Trav a] -> [Trav a]
inorderD f = inorderD' 0 where
inorderD' !d t xs = case unfoldBin t of
Just (x, l, r) -> inorderD'' l (Trav d (f x) x:inorderD'' r xs)
Nothing -> xs
where inorderD'' = inorderD' (d+1)
quickLCABinary :: BinTree a -> (Int, BinTree (Index, a), Index -> Index -> (Index, a))
quickLCABinary tree = case inorderBin tree of
(iTree, n) -> (n, iTree, lcaBinary n fst iTree)
lcaBinary :: Int -> (a -> Index) -> BinTree a -> Index -> Index -> a
lcaBinary !n ix tree = lca
where !trav = G.unstream $ S.map (\ (Trav d i a) -> ((d, i), a)) $ S.fromListN n (inorderD ix tree [])
ixs :: UV.Vector Int
!ixs = vec n $ S.map (\ (a, b) -> (b, a)) $ S.indexed $ S.map (snd . fst) $ G.stream trav
!(dixs, !vals) = (Mix.unzip :: Mix.MixVector UV.Vector V.Vector (a, b) -> (UV.Vector a, V.Vector b))
trav
(!depths, _) = UV.unzip dixs
rM :: Int -> Int -> Int
!rM = vecRangeMin depths
lca !i !j = let
iIx = ixs ! i
jIx = ixs ! j
in vals ! case compare iIx jIx of
EQ -> iIx
LT -> rM iIx (jIx iIx + 1)
GT -> rM jIx (iIx jIx + 1)