{-# LANGUAGE LambdaCase #-}
module AtCoder.Extra.Bisect
(
lowerBound,
lowerBoundIn,
upperBound,
upperBoundIn,
maxRight,
maxRightM,
minLeft,
minLeftM,
)
where
import AtCoder.Internal.Assert qualified as ACIA
import Data.Functor.Identity
import Data.Vector.Generic qualified as VG
import GHC.Stack (HasCallStack)
{-# INLINE lowerBound #-}
lowerBound :: (HasCallStack, VG.Vector v a, Ord a) => v a -> a -> Int
lowerBound :: forall (v :: * -> *) a.
(HasCallStack, Vector v a, Ord a) =>
v a -> a -> Int
lowerBound v a
vec = Int -> Int -> v a -> a -> Int
forall (v :: * -> *) a.
(HasCallStack, Vector v a, Ord a) =>
Int -> Int -> v a -> a -> Int
lowerBoundIn Int
0 (v a -> Int
forall (v :: * -> *) a. Vector v a => v a -> Int
VG.length v a
vec) v a
vec
{-# INLINE lowerBoundIn #-}
lowerBoundIn :: (HasCallStack, VG.Vector v a, Ord a) => Int -> Int -> v a -> a -> Int
lowerBoundIn :: forall (v :: * -> *) a.
(HasCallStack, Vector v a, Ord a) =>
Int -> Int -> v a -> a -> Int
lowerBoundIn Int
l Int
r v a
vec a
target = HasCallStack => Int -> Int -> (Int -> Bool) -> Int
Int -> Int -> (Int -> Bool) -> Int
maxRight Int
l Int
r ((Int -> Bool) -> Int) -> (Int -> Bool) -> Int
forall a b. (a -> b) -> a -> b
$ \Int
i -> v a
vec v a -> Int -> a
forall (v :: * -> *) a.
(HasCallStack, Vector v a) =>
v a -> Int -> a
VG.! Int
i a -> a -> Bool
forall a. Ord a => a -> a -> Bool
< a
target
where
!Int -> ()
_ = HasCallStack => String -> Int -> Int -> Int -> Int -> ()
String -> Int -> Int -> Int -> Int -> ()
ACIA.checkIntervalBounded String
"AtCoder.Extra.Bisect.lowerBoundIn" Int
l Int
r (Int -> Int -> ()) -> Int -> Int -> ()
forall a b. (a -> b) -> a -> b
$ v a -> Int
forall (v :: * -> *) a. Vector v a => v a -> Int
VG.length v a
vec
{-# INLINE upperBound #-}
upperBound :: (HasCallStack, VG.Vector v a, Ord a) => v a -> a -> Int
upperBound :: forall (v :: * -> *) a.
(HasCallStack, Vector v a, Ord a) =>
v a -> a -> Int
upperBound v a
vec = Int -> Int -> v a -> a -> Int
forall (v :: * -> *) a.
(HasCallStack, Vector v a, Ord a) =>
Int -> Int -> v a -> a -> Int
upperBoundIn Int
0 (v a -> Int
forall (v :: * -> *) a. Vector v a => v a -> Int
VG.length v a
vec) v a
vec
{-# INLINE upperBoundIn #-}
upperBoundIn :: (HasCallStack, VG.Vector v a, Ord a) => Int -> Int -> v a -> a -> Int
upperBoundIn :: forall (v :: * -> *) a.
(HasCallStack, Vector v a, Ord a) =>
Int -> Int -> v a -> a -> Int
upperBoundIn Int
l Int
r v a
vec a
target = HasCallStack => Int -> Int -> (Int -> Bool) -> Int
Int -> Int -> (Int -> Bool) -> Int
maxRight Int
l Int
r ((Int -> Bool) -> Int) -> (Int -> Bool) -> Int
forall a b. (a -> b) -> a -> b
$ \Int
i -> v a
vec v a -> Int -> a
forall (v :: * -> *) a.
(HasCallStack, Vector v a) =>
v a -> Int -> a
VG.! Int
i a -> a -> Bool
forall a. Ord a => a -> a -> Bool
<= a
target
where
!Int -> ()
_ = HasCallStack => String -> Int -> Int -> Int -> Int -> ()
String -> Int -> Int -> Int -> Int -> ()
ACIA.checkIntervalBounded String
"AtCoder.Extra.Bisect.upperBoundIn" Int
l Int
r (Int -> Int -> ()) -> Int -> Int -> ()
forall a b. (a -> b) -> a -> b
$ v a -> Int
forall (v :: * -> *) a. Vector v a => v a -> Int
VG.length v a
vec
{-# INLINE maxRight #-}
maxRight ::
(HasCallStack) =>
Int ->
Int ->
(Int -> Bool) ->
Int
maxRight :: HasCallStack => Int -> Int -> (Int -> Bool) -> Int
maxRight Int
l Int
r Int -> Bool
p = Identity Int -> Int
forall a. Identity a -> a
runIdentity (Identity Int -> Int) -> Identity Int -> Int
forall a b. (a -> b) -> a -> b
$ Int -> Int -> (Int -> Identity Bool) -> Identity Int
forall (m :: * -> *).
(HasCallStack, Monad m) =>
Int -> Int -> (Int -> m Bool) -> m Int
maxRightM Int
l Int
r (Bool -> Identity Bool
forall a. a -> Identity a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Bool -> Identity Bool) -> (Int -> Bool) -> Int -> Identity Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> Bool
p)
{-# INLINE maxRightM #-}
maxRightM :: (HasCallStack, Monad m) => Int -> Int -> (Int -> m Bool) -> m Int
maxRightM :: forall (m :: * -> *).
(HasCallStack, Monad m) =>
Int -> Int -> (Int -> m Bool) -> m Int
maxRightM Int
l0 Int
r0 Int -> m Bool
p = Int -> Int -> (Int -> m Bool) -> m Int
forall (m :: * -> *).
(HasCallStack, Monad m) =>
Int -> Int -> (Int -> m Bool) -> m Int
bisectImpl (Int
l0 Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1) Int
r0 Int -> m Bool
p
where
!Int -> ()
_ = HasCallStack => String -> Int -> Int -> Int -> ()
String -> Int -> Int -> Int -> ()
ACIA.checkInterval String
"AtCoder.Extra.Bisect.maxRightM" Int
l0 Int
r0
{-# INLINE minLeft #-}
minLeft ::
(HasCallStack) =>
Int ->
Int ->
(Int -> Bool) ->
Int
minLeft :: HasCallStack => Int -> Int -> (Int -> Bool) -> Int
minLeft Int
l Int
r Int -> Bool
p = Identity Int -> Int
forall a. Identity a -> a
runIdentity (Identity Int -> Int) -> Identity Int -> Int
forall a b. (a -> b) -> a -> b
$ Int -> Int -> (Int -> Identity Bool) -> Identity Int
forall (m :: * -> *).
(HasCallStack, Monad m) =>
Int -> Int -> (Int -> m Bool) -> m Int
minLeftM Int
l Int
r (Bool -> Identity Bool
forall a. a -> Identity a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Bool -> Identity Bool) -> (Int -> Bool) -> Int -> Identity Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> Bool
p)
{-# INLINE minLeftM #-}
minLeftM :: (HasCallStack, Monad m) => Int -> Int -> (Int -> m Bool) -> m Int
minLeftM :: forall (m :: * -> *).
(HasCallStack, Monad m) =>
Int -> Int -> (Int -> m Bool) -> m Int
minLeftM Int
l Int
r Int -> m Bool
p = (Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1) (Int -> Int) -> m Int -> m Int
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Int -> Int -> (Int -> m Bool) -> m Int
forall (m :: * -> *).
(HasCallStack, Monad m) =>
Int -> Int -> (Int -> m Bool) -> m Int
bisectImpl Int
r (Int
l Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1) Int -> m Bool
p
where
!Int -> ()
_ = HasCallStack => String -> Int -> Int -> Int -> ()
String -> Int -> Int -> Int -> ()
ACIA.checkInterval String
"AtCoder.Extra.Bisect.minLeftM" Int
l Int
r
{-# INLINE bisectImpl #-}
bisectImpl :: (HasCallStack, Monad m) => Int -> Int -> (Int -> m Bool) -> m Int
bisectImpl :: forall (m :: * -> *).
(HasCallStack, Monad m) =>
Int -> Int -> (Int -> m Bool) -> m Int
bisectImpl Int
l0 Int
r0 Int -> m Bool
p = Int -> Int -> m Int
inner Int
l0 Int
r0
where
inner :: Int -> Int -> m Int
inner Int
l Int
r
| Int -> Int
forall a. Num a => a -> a
abs (Int
r Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
l) Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
1 = Int -> m Int
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Int
r
| Bool
otherwise =
Int -> m Bool
p Int
mid m Bool -> (Bool -> m Int) -> m Int
forall a b. m a -> (a -> m b) -> m b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \case
Bool
True -> Int -> Int -> m Int
inner Int
mid Int
r
Bool
False -> Int -> Int -> m Int
inner Int
l Int
mid
where
mid :: Int
mid = (Int
l Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
r) Int -> Int -> Int
forall a. Integral a => a -> a -> a
`div` Int
2