{-# LANGUAGE RecordWildCards #-}

-- | A static Wavelet Matrix.
--
-- ==== Notation
-- Let \(S\) be the set of values in your wavelet matrix. We use \(|S|\) to denote the number of
-- distinct values contained within this set \((|S| \lt n)\).
--
-- @since 1.1.0.0
module AtCoder.Extra.WaveletMatrix
  ( -- * Wavelet Matrix
    WaveletMatrix (..),

    -- * Constructors
    build,

    -- * Access (indexing)
    access,

    -- * Rank (count)
    rank,
    rankBetween,

    -- * Selection

    -- | ==== __Example__
    -- >>> import AtCoder.Extra.WaveletMatrix qualified as WM
    -- >>> import Data.Vector.Unboxed qualified as VU
    -- >>> let wm = WM.build $ VU.fromList [1,1,2,1,3]
    -- >>> WM.select wm 1
    -- Just 0
    -- >>> WM.selectKth wm 2 1
    -- Just 3
    -- >>> WM.selectIn wm {- [l, r) -} 1 4 {- x -} 1
    -- Just 1
    -- >>> WM.selectKthIn wm {- [l, r) -} 1 4 {- k -} 1 {- x -} 1
    -- Just 3
    select,
    selectKth,
    selectIn,
    selectKthIn,

    -- * Quantile (value-ordered access)
    kthLargestIn,
    ikthLargestIn,
    kthSmallestIn,
    ikthSmallestIn,
    -- unsafeKthLargestIn,
    -- unsafeIKthLargestIn,
    -- unsafeKthSmallestIn,
    -- unsafeIKthSmallestIn,

    -- * Lookup
    lookupLE,
    lookupLT,
    lookupGE,
    lookupGT,

    -- * Conversions
    assocsIn,
    descAssocsIn,
  )
where

import AtCoder.Extra.Bisect
import AtCoder.Extra.WaveletMatrix.Raw qualified as Rwm
import Control.Monad
import Data.Maybe (fromJust, fromMaybe)
import Data.Vector.Algorithms.Intro qualified as VAI
import Data.Vector.Generic qualified as VG
import Data.Vector.Unboxed qualified as VU

-- | A static Wavelet Matrix.
--
-- @since 1.1.0.0
data WaveletMatrix = WaveletMatrix
  { -- | The internal wavelet matrix, where index compression is not automatically performed.
    --
    -- @since 1.1.0.0
    WaveletMatrix -> RawWaveletMatrix
rawWM :: !Rwm.RawWaveletMatrix,
    -- | Index compression dictionary.
    --
    -- @since 1.1.0.0
    WaveletMatrix -> Vector Int
xDictWM :: !(VU.Vector Int)
  }

-- | \(O(n \log n)\) Creates a `WaveletMatrix` from an array \(a\).
--
-- @since 1.1.0.0
{-# INLINE build #-}
build :: VU.Vector Int -> WaveletMatrix
build :: Vector Int -> WaveletMatrix
build Vector Int
ys =
  let !xDictWM :: Vector Int
xDictWM = Vector Int -> Vector Int
forall a. (Unbox a, Eq a) => Vector a -> Vector a
VU.uniq (Vector Int -> Vector Int) -> Vector Int -> Vector Int
forall a b. (a -> b) -> a -> b
$ (forall s. MVector s Int -> ST s ()) -> Vector Int -> Vector Int
forall a.
Unbox a =>
(forall s. MVector s a -> ST s ()) -> Vector a -> Vector a
VU.modify (Comparison Int -> MVector (PrimState (ST s)) Int -> ST s ()
forall (m :: * -> *) (v :: * -> * -> *) e.
(PrimMonad m, MVector v e) =>
Comparison e -> v (PrimState m) e -> m ()
VAI.sortBy Comparison Int
forall a. Ord a => a -> a -> Ordering
compare) Vector Int
ys
      !ys' :: Vector Int
ys' = (Int -> Int) -> Vector Int -> Vector Int
forall a b. (Unbox a, Unbox b) => (a -> b) -> Vector a -> Vector b
VU.map (Maybe Int -> Int
forall a. HasCallStack => Maybe a -> a
fromJust (Maybe Int -> Int) -> (Int -> Maybe Int) -> Int -> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Vector Int -> Int -> Maybe Int
forall (v :: * -> *) a.
(HasCallStack, Vector v a, Ord a) =>
v a -> a -> Maybe Int
lowerBound Vector Int
xDictWM) Vector Int
ys
      !rawWM :: RawWaveletMatrix
rawWM = HasCallStack => Int -> Vector Int -> RawWaveletMatrix
Int -> Vector Int -> RawWaveletMatrix
Rwm.build (Vector Int -> Int
forall (v :: * -> *) a. Vector v a => v a -> Int
VG.length Vector Int
ys) Vector Int
ys'
   in WaveletMatrix {Vector Int
RawWaveletMatrix
rawWM :: RawWaveletMatrix
xDictWM :: Vector Int
xDictWM :: Vector Int
rawWM :: RawWaveletMatrix
..}

-- | \(O(\log |S|)\) Returns \(a[k]\) or `Nothing` if the index is out of the bounds. Try to use the
-- original array if you can.
--
-- @since 1.1.0.0
{-# INLINE access #-}
access :: WaveletMatrix -> Int -> Maybe Int
access :: WaveletMatrix -> Int -> Maybe Int
access WaveletMatrix {Vector Int
RawWaveletMatrix
rawWM :: WaveletMatrix -> RawWaveletMatrix
xDictWM :: WaveletMatrix -> Vector Int
rawWM :: RawWaveletMatrix
xDictWM :: Vector Int
..} Int
i = (Vector Int
xDictWM VG.!) (Int -> Int) -> Maybe Int -> Maybe Int
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> RawWaveletMatrix -> Int -> Maybe Int
Rwm.access RawWaveletMatrix
rawWM Int
i

-- | \(O(\log |S|)\) Returns the number of \(y\) in \([l, r)\).
--
-- @since 1.1.0.0
{-# INLINE rank #-}
rank ::
  -- | A wavelet matrix
  WaveletMatrix ->
  -- | \(l\)
  Int ->
  -- | \(r\)
  Int ->
  -- | \(y\)
  Int ->
  -- | The number of \(y\) in \([l, r)\).
  Int
rank :: WaveletMatrix -> Int -> Int -> Int -> Int
rank WaveletMatrix
wm Int
l Int
r Int
y = WaveletMatrix -> Int -> Int -> Int -> Int -> Int
rankBetween WaveletMatrix
wm Int
l Int
r Int
y (Int
y Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1)

-- | \(O(\log |S|)\) Returns the number of \(y\) in \([l, r) \times [y_1, y_2)\).
--
-- @since 1.1.0.0
{-# INLINE rankBetween #-}
rankBetween ::
  -- | A wavelet matrix
  WaveletMatrix ->
  -- | \(l\)
  Int ->
  -- | \(r\)
  Int ->
  -- | \(y_1\)
  Int ->
  -- | \(y_2\)
  Int ->
  -- | The number of \(y\) in \([l, r) \times [y_1, y_2)\).
  Int
rankBetween :: WaveletMatrix -> Int -> Int -> Int -> Int -> Int
rankBetween WaveletMatrix {Vector Int
RawWaveletMatrix
rawWM :: WaveletMatrix -> RawWaveletMatrix
xDictWM :: WaveletMatrix -> Vector Int
rawWM :: RawWaveletMatrix
xDictWM :: Vector Int
..} Int
l Int
r Int
y1 Int
y2
  | Bool -> Bool
not (Bool -> Bool) -> Bool -> Bool
forall a b. (a -> b) -> a -> b
$ Int
0 Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
l Bool -> Bool -> Bool
&& Int
l Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
r Bool -> Bool -> Bool
&& Int
r Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
n = Int
0
  | Int
y1' Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Int
y2' = Int
0
  | Bool
otherwise = RawWaveletMatrix -> Int -> Int -> Int -> Int -> Int
Rwm.rankBetween RawWaveletMatrix
rawWM Int
l Int
r Int
y1' Int
y2'
  where
    -- Handles the case @yl@ or  @yr@ is not in the dict
    n :: Int
n = RawWaveletMatrix -> Int
Rwm.lengthRwm RawWaveletMatrix
rawWM
    y1' :: Int
y1' = Int -> Maybe Int -> Int
forall a. a -> Maybe a -> a
fromMaybe Int
n (HasCallStack => Int -> Int -> (Int -> Bool) -> Maybe Int
Int -> Int -> (Int -> Bool) -> Maybe Int
bisectR Int
0 (Vector Int -> Int
forall (v :: * -> *) a. Vector v a => v a -> Int
VG.length Vector Int
xDictWM) ((Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
y1) (Int -> Bool) -> (Int -> Int) -> Int -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Vector Int -> Int -> Int
forall (v :: * -> *) a. Vector v a => v a -> Int -> a
VG.unsafeIndex Vector Int
xDictWM))
    y2' :: Int
y2' = Int -> (Int -> Int) -> Maybe Int -> Int
forall b a. b -> (a -> b) -> Maybe a -> b
maybe (-Int
1) (Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1) (HasCallStack => Int -> Int -> (Int -> Bool) -> Maybe Int
Int -> Int -> (Int -> Bool) -> Maybe Int
bisectL Int
0 (Vector Int -> Int
forall (v :: * -> *) a. Vector v a => v a -> Int
VG.length Vector Int
xDictWM) ((Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
y2) (Int -> Bool) -> (Int -> Int) -> Int -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Vector Int -> Int -> Int
forall (v :: * -> *) a. Vector v a => v a -> Int -> a
VG.unsafeIndex Vector Int
xDictWM))

-- | \(O(\log |S|)\) Returns the index of the first \(y\) in \(a\), or `Nothing` if \(y\) is
-- not found.
--
-- @since 1.1.0.0
{-# INLINE select #-}
select :: WaveletMatrix -> Int -> Maybe Int
select :: WaveletMatrix -> Int -> Maybe Int
select WaveletMatrix
wm = WaveletMatrix -> Int -> Int -> Maybe Int
selectKth WaveletMatrix
wm Int
0

-- | \(O(\log |S|)\) Returns the index of the \(k\)-th occurrence (0-based) of \(y\), or `Nothing`
-- if no such occurrence exists.
--
-- @since 1.1.0.0
{-# INLINE selectKth #-}
selectKth ::
  -- | A wavelet matrix
  WaveletMatrix ->
  -- | \(k\)
  Int ->
  -- | \(y\)
  Int ->
  -- | The index of \(k\)-th \(y\)
  Maybe Int
selectKth :: WaveletMatrix -> Int -> Int -> Maybe Int
selectKth WaveletMatrix {Vector Int
RawWaveletMatrix
rawWM :: WaveletMatrix -> RawWaveletMatrix
xDictWM :: WaveletMatrix -> Vector Int
rawWM :: RawWaveletMatrix
xDictWM :: Vector Int
..} Int
k Int
y = do
  Int
i <- Vector Int -> Int -> Maybe Int
forall (v :: * -> *) a.
(HasCallStack, Vector v a, Ord a) =>
v a -> a -> Maybe Int
lowerBound Vector Int
xDictWM Int
y
  -- TODO: we don't need such an explicit branch?
  let !y' :: Int
y' = Vector Int
xDictWM Vector Int -> Int -> Int
forall (v :: * -> *) a.
(HasCallStack, Vector v a) =>
v a -> Int -> a
VG.! Int
i
  Bool -> Maybe ()
forall (f :: * -> *). Alternative f => Bool -> f ()
guard (Bool -> Maybe ()) -> Bool -> Maybe ()
forall a b. (a -> b) -> a -> b
$ Int
y' Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
y
  RawWaveletMatrix -> Int -> Int -> Maybe Int
Rwm.selectKth RawWaveletMatrix
rawWM Int
k Int
i

-- | \(O(\log |S|)\) Given an interval \([l, r)\), it returns the index of the first occurrence
-- (0-based) of \(y\) in the sequence, or `Nothing` if no such occurrence exists.
--
-- @since 1.1.0.0
{-# INLINE selectIn #-}
selectIn ::
  -- | A wavelet matrix
  WaveletMatrix ->
  -- | \(l\)
  Int ->
  -- | \(r\)
  Int ->
  -- | \(y\)
  Int ->
  -- | The index of the first \(y\) in \([l, r)\).
  Maybe Int
selectIn :: WaveletMatrix -> Int -> Int -> Int -> Maybe Int
selectIn WaveletMatrix
wm Int
l Int
r = WaveletMatrix -> Int -> Int -> Int -> Int -> Maybe Int
selectKthIn WaveletMatrix
wm Int
l Int
r Int
0

-- | \(O(\log |S|)\) Given an interval \([l, r)\), it returns the index of the \(k\)-th occurrence
-- (0-based) of \(y\) in the sequence, or `Nothing` if no such occurrence exists.
--
-- @since 1.1.0.0
{-# INLINE selectKthIn #-}
selectKthIn ::
  -- | A wavelet matrix
  WaveletMatrix ->
  -- | \(l\)
  Int ->
  -- | \(r\)
  Int ->
  -- | \(k\)
  Int ->
  -- | \(y\)
  Int ->
  -- | The index of the \(k\)-th \(y\) in \([l, r)\).
  Maybe Int
selectKthIn :: WaveletMatrix -> Int -> Int -> Int -> Int -> Maybe Int
selectKthIn WaveletMatrix {Vector Int
RawWaveletMatrix
rawWM :: WaveletMatrix -> RawWaveletMatrix
xDictWM :: WaveletMatrix -> Vector Int
rawWM :: RawWaveletMatrix
xDictWM :: Vector Int
..} Int
l Int
r Int
k Int
y = do
  Int
i <- Vector Int -> Int -> Maybe Int
forall (v :: * -> *) a.
(HasCallStack, Vector v a, Ord a) =>
v a -> a -> Maybe Int
lowerBound Vector Int
xDictWM Int
y
  -- TODO: we don't need such an explicit branch?
  let !y' :: Int
y' = Vector Int
xDictWM Vector Int -> Int -> Int
forall (v :: * -> *) a.
(HasCallStack, Vector v a) =>
v a -> Int -> a
VG.! Int
i
  Bool -> Maybe ()
forall (f :: * -> *). Alternative f => Bool -> f ()
guard (Bool -> Maybe ()) -> Bool -> Maybe ()
forall a b. (a -> b) -> a -> b
$ Int
y' Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
y
  RawWaveletMatrix -> Int -> Int -> Int -> Int -> Maybe Int
Rwm.selectKthIn RawWaveletMatrix
rawWM Int
l Int
r Int
k Int
i

-- | \(O(\log |S|)\) Given the interval \([l, r)\), returns the index of the \(k\)-th (0-based)
-- largest value. Note that duplicated values are treated as distinct occurrences.
--
-- @since 1.1.0.0
{-# INLINE kthLargestIn #-}
kthLargestIn ::
  -- | A wavelet matrix
  WaveletMatrix ->
  -- | \(l\)
  Int ->
  -- | \(r\)
  Int ->
  -- | \(k\)
  Int ->
  -- | \(k\)-th largest \(y\) in \([l, r)\)
  Maybe Int
kthLargestIn :: WaveletMatrix -> Int -> Int -> Int -> Maybe Int
kthLargestIn WaveletMatrix {Vector Int
RawWaveletMatrix
rawWM :: WaveletMatrix -> RawWaveletMatrix
xDictWM :: WaveletMatrix -> Vector Int
rawWM :: RawWaveletMatrix
xDictWM :: Vector Int
..} Int
l Int
r Int
k
  | Just !Int
y <- RawWaveletMatrix -> Int -> Int -> Int -> Maybe Int
Rwm.kthLargestIn RawWaveletMatrix
rawWM Int
l Int
r Int
k = Int -> Maybe Int
forall a. a -> Maybe a
Just (Int -> Maybe Int) -> Int -> Maybe Int
forall a b. (a -> b) -> a -> b
$ Vector Int
xDictWM Vector Int -> Int -> Int
forall (v :: * -> *) a.
(HasCallStack, Vector v a) =>
v a -> Int -> a
VG.! Int
y
  | Bool
otherwise = Maybe Int
forall a. Maybe a
Nothing

-- | \(O(\log |S|)\) Given the interval \([l, r)\), returns both the index and the value of the
-- \(k\)-th (0-based) largest value. Note that duplicated values are treated as distinct occurrences.
--
-- @since 1.1.0.0
{-# INLINE ikthLargestIn #-}
ikthLargestIn ::
  -- | A wavelet matrix
  WaveletMatrix ->
  -- | \(l\)
  Int ->
  -- | \(r\)
  Int ->
  -- | \(k\)
  Int ->
  -- | \((i, y)\) for \(k\)-th largest \(y\) in \([l, r)\)
  Maybe (Int, Int)
ikthLargestIn :: WaveletMatrix -> Int -> Int -> Int -> Maybe (Int, Int)
ikthLargestIn WaveletMatrix {Vector Int
RawWaveletMatrix
rawWM :: WaveletMatrix -> RawWaveletMatrix
xDictWM :: WaveletMatrix -> Vector Int
rawWM :: RawWaveletMatrix
xDictWM :: Vector Int
..} Int
l Int
r Int
k
  | Just (!Int
i, !Int
y) <- RawWaveletMatrix -> Int -> Int -> Int -> Maybe (Int, Int)
Rwm.ikthLargestIn RawWaveletMatrix
rawWM Int
l Int
r Int
k = (Int, Int) -> Maybe (Int, Int)
forall a. a -> Maybe a
Just (Int
i, Vector Int
xDictWM Vector Int -> Int -> Int
forall (v :: * -> *) a.
(HasCallStack, Vector v a) =>
v a -> Int -> a
VG.! Int
y)
  | Bool
otherwise = Maybe (Int, Int)
forall a. Maybe a
Nothing

-- | \(O(\log |S|)\) Given the interval \([l, r)\), returns the index of the \(k\)-th (0-based)
-- smallest value. Note that duplicated values are treated as distinct occurrences.
--
-- @since 1.1.0.0
{-# INLINE kthSmallestIn #-}
kthSmallestIn ::
  -- | A wavelet matrix
  WaveletMatrix ->
  -- | \(l\)
  Int ->
  -- | \(r\)
  Int ->
  -- | \(k\)
  Int ->
  -- | \(k\)-th largest \(y\) in \([l, r)\)
  Maybe Int
kthSmallestIn :: WaveletMatrix -> Int -> Int -> Int -> Maybe Int
kthSmallestIn WaveletMatrix {Vector Int
RawWaveletMatrix
rawWM :: WaveletMatrix -> RawWaveletMatrix
xDictWM :: WaveletMatrix -> Vector Int
rawWM :: RawWaveletMatrix
xDictWM :: Vector Int
..} Int
l Int
r Int
k
  | Just !Int
y <- RawWaveletMatrix -> Int -> Int -> Int -> Maybe Int
Rwm.kthSmallestIn RawWaveletMatrix
rawWM Int
l Int
r Int
k = Int -> Maybe Int
forall a. a -> Maybe a
Just (Int -> Maybe Int) -> Int -> Maybe Int
forall a b. (a -> b) -> a -> b
$ Vector Int
xDictWM Vector Int -> Int -> Int
forall (v :: * -> *) a.
(HasCallStack, Vector v a) =>
v a -> Int -> a
VG.! Int
y
  | Bool
otherwise = Maybe Int
forall a. Maybe a
Nothing

-- | \(O(\log |S|)\) Given the interval \([l, r)\), returns both the index and the value of the
-- \(k\)-th (0-based) smallest value. Note that duplicated values are treated as distinct occurrences.
--
-- @since 1.1.0.0
{-# INLINE ikthSmallestIn #-}
ikthSmallestIn ::
  WaveletMatrix ->
  -- | \(l\)
  Int ->
  -- | \(r\)
  Int ->
  -- | \(k\)
  Int ->
  -- | \((i, y)\) for \(k\)-th largest \(y\) in \([l, r)\)
  Maybe (Int, Int)
ikthSmallestIn :: WaveletMatrix -> Int -> Int -> Int -> Maybe (Int, Int)
ikthSmallestIn WaveletMatrix {Vector Int
RawWaveletMatrix
rawWM :: WaveletMatrix -> RawWaveletMatrix
xDictWM :: WaveletMatrix -> Vector Int
rawWM :: RawWaveletMatrix
xDictWM :: Vector Int
..} Int
l Int
r Int
k
  | Just (!Int
i, !Int
y) <- RawWaveletMatrix -> Int -> Int -> Int -> Maybe (Int, Int)
Rwm.ikthSmallestIn RawWaveletMatrix
rawWM Int
l Int
r Int
k = (Int, Int) -> Maybe (Int, Int)
forall a. a -> Maybe a
Just (Int
i, Vector Int
xDictWM Vector Int -> Int -> Int
forall (v :: * -> *) a.
(HasCallStack, Vector v a) =>
v a -> Int -> a
VG.! Int
y)
  | Bool
otherwise = Maybe (Int, Int)
forall a. Maybe a
Nothing

-- | \(O(\log |S|)\)
--
-- @since 1.1.0.0
{-# INLINE unsafeKthSmallestIn #-}
unsafeKthSmallestIn :: WaveletMatrix -> Int -> Int -> Int -> Int
unsafeKthSmallestIn :: WaveletMatrix -> Int -> Int -> Int -> Int
unsafeKthSmallestIn WaveletMatrix {Vector Int
RawWaveletMatrix
rawWM :: WaveletMatrix -> RawWaveletMatrix
xDictWM :: WaveletMatrix -> Vector Int
rawWM :: RawWaveletMatrix
xDictWM :: Vector Int
..} Int
l Int
r Int
k =
  Vector Int
xDictWM Vector Int -> Int -> Int
forall (v :: * -> *) a.
(HasCallStack, Vector v a) =>
v a -> Int -> a
VG.! RawWaveletMatrix -> Int -> Int -> Int -> Int
Rwm.unsafeKthSmallestIn RawWaveletMatrix
rawWM Int
l Int
r Int
k

-- | \(O(\log |S|)\) Looks up the maximum \(y\) in \([l, r) \times (-\infty, y_0]\).
--
-- @since 1.1.0.0
{-# INLINE lookupLE #-}
lookupLE ::
  -- | A wavelet matrix
  WaveletMatrix ->
  -- | \(l\)
  Int ->
  -- | \(r\)
  Int ->
  -- | \(y_0\)
  Int ->
  -- | Maximum \(y\) in \([l, r) \times (-\infty, y_0]\)
  Maybe Int
lookupLE :: WaveletMatrix -> Int -> Int -> Int -> Maybe Int
lookupLE WaveletMatrix
wm Int
l Int
r Int
y0
  | Int
r' Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
l' = Maybe Int
forall a. Maybe a
Nothing
  | Int
rank_ Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
0 = Maybe Int
forall a. Maybe a
Nothing
  | Bool
otherwise = Int -> Maybe Int
forall a. a -> Maybe a
Just (Int -> Maybe Int) -> Int -> Maybe Int
forall a b. (a -> b) -> a -> b
$ WaveletMatrix -> Int -> Int -> Int -> Int
unsafeKthSmallestIn WaveletMatrix
wm Int
l' Int
r' (Int
rank_ Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1)
  where
    -- clamp
    l' :: Int
l' = Int -> Int -> Int
forall a. Ord a => a -> a -> a
max Int
0 Int
l
    r' :: Int
r' = Int -> Int -> Int
forall a. Ord a => a -> a -> a
min (RawWaveletMatrix -> Int
Rwm.lengthRwm (WaveletMatrix -> RawWaveletMatrix
rawWM WaveletMatrix
wm)) Int
r
    rank_ :: Int
rank_ = WaveletMatrix -> Int -> Int -> Int -> Int -> Int
rankBetween WaveletMatrix
wm Int
l' Int
r' Int
forall a. Bounded a => a
minBound (Int
y0 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1)

-- | \(O(\log |S|)\) Looks up the maximum \(y\) in \([l, r) \times (-\infty, y_0)\).
--
-- @since 1.1.0.0
{-# INLINE lookupLT #-}
lookupLT ::
  -- | A wavelet matrix
  WaveletMatrix ->
  -- | \(l\)
  Int ->
  -- | \(r\)
  Int ->
  -- | \(y_0\)
  Int ->
  -- | Maximum \(y\) in \([l, r) \times (-\infty, y_0)\)
  Maybe Int
lookupLT :: WaveletMatrix -> Int -> Int -> Int -> Maybe Int
lookupLT WaveletMatrix
wm Int
l Int
r Int
y0 = WaveletMatrix -> Int -> Int -> Int -> Maybe Int
lookupLE WaveletMatrix
wm Int
l Int
r (Int
y0 Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1)

-- | \(O(\log |S|)\) Looks up the minimum \(y\) in \([l, r) \times [y_0, \infty)\).
--
-- @since 1.1.0.0
{-# INLINE lookupGE #-}
lookupGE ::
  -- | A wavelet matrix
  WaveletMatrix ->
  -- | \(l\)
  Int ->
  -- | \(r\)
  Int ->
  -- | \(y_0\)
  Int ->
  -- | Minimum \(y\) in \([l, r) \times [y_0, \infty)\).
  Maybe Int
lookupGE :: WaveletMatrix -> Int -> Int -> Int -> Maybe Int
lookupGE WaveletMatrix
wm Int
l Int
r Int
y0
  | Int
r' Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
l' = Maybe Int
forall a. Maybe a
Nothing
  | Int
rank_ Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Int
r Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
l = Maybe Int
forall a. Maybe a
Nothing
  | Bool
otherwise = Int -> Maybe Int
forall a. a -> Maybe a
Just (Int -> Maybe Int) -> Int -> Maybe Int
forall a b. (a -> b) -> a -> b
$ WaveletMatrix -> Int -> Int -> Int -> Int
unsafeKthSmallestIn WaveletMatrix
wm Int
l Int
r Int
rank_
  where
    -- clamp
    l' :: Int
l' = Int -> Int -> Int
forall a. Ord a => a -> a -> a
max Int
0 Int
l
    r' :: Int
r' = Int -> Int -> Int
forall a. Ord a => a -> a -> a
min (RawWaveletMatrix -> Int
Rwm.lengthRwm (WaveletMatrix -> RawWaveletMatrix
rawWM WaveletMatrix
wm)) Int
r
    rank_ :: Int
rank_ = WaveletMatrix -> Int -> Int -> Int -> Int -> Int
rankBetween WaveletMatrix
wm Int
l' Int
r' Int
forall a. Bounded a => a
minBound Int
y0

-- | \(O(\log |S|)\) Looks up the minimum \(y\) in \([l, r) \times (y_0, \infty)\).
--
-- @since 1.1.0.0
{-# INLINE lookupGT #-}
lookupGT ::
  -- | A wavelet matrix
  WaveletMatrix ->
  -- | \(l\)
  Int ->
  -- | \(r\)
  Int ->
  -- | \(y_0\)
  Int ->
  -- | Minimum \(y\) in \([l, r) \times (y_0, \infty)\)
  Maybe Int
lookupGT :: WaveletMatrix -> Int -> Int -> Int -> Maybe Int
lookupGT WaveletMatrix
wm Int
l Int
r Int
y0 = WaveletMatrix -> Int -> Int -> Int -> Maybe Int
lookupGE WaveletMatrix
wm Int
l Int
r (Int
y0 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1)

-- | \(O(\min(|S|, L) \log |S|)\) Collects \((y, \mathrm{rank}(y))\) in range \([l, r)\) in
-- ascending order of \(y\). Note that it's only fast when the \(|S|\) is very small.
--
-- @since 1.1.0.0
{-# INLINE assocsIn #-}
assocsIn :: WaveletMatrix -> Int -> Int -> [(Int, Int)]
assocsIn :: WaveletMatrix -> Int -> Int -> [(Int, Int)]
assocsIn WaveletMatrix {Vector Int
RawWaveletMatrix
rawWM :: WaveletMatrix -> RawWaveletMatrix
xDictWM :: WaveletMatrix -> Vector Int
rawWM :: RawWaveletMatrix
xDictWM :: Vector Int
..} Int
l Int
r = RawWaveletMatrix -> Int -> Int -> (Int -> Int) -> [(Int, Int)]
Rwm.assocsWith RawWaveletMatrix
rawWM Int
l Int
r (Vector Int
xDictWM VG.!)

-- | \(O(\min(|S|, L) \log |S|)\) Collects \((y, \mathrm{rank}(y))\) in range \([l, r)\) in
-- descending order of \(y\). Note that it's only fast when the \(|S|\) is very small.
--
-- @since 1.1.0.0
{-# INLINE descAssocsIn #-}
descAssocsIn :: WaveletMatrix -> Int -> Int -> [(Int, Int)]
descAssocsIn :: WaveletMatrix -> Int -> Int -> [(Int, Int)]
descAssocsIn WaveletMatrix {Vector Int
RawWaveletMatrix
rawWM :: WaveletMatrix -> RawWaveletMatrix
xDictWM :: WaveletMatrix -> Vector Int
rawWM :: RawWaveletMatrix
xDictWM :: Vector Int
..} Int
l Int
r = RawWaveletMatrix -> Int -> Int -> (Int -> Int) -> [(Int, Int)]
Rwm.descAssocsInWith RawWaveletMatrix
rawWM Int
l Int
r (Vector Int
xDictWM VG.!)