packages feed

ac-library-hs 1.0.0.1 → 1.1.0.0

raw patch · 78 files changed

+9333/−709 lines, 78 filesdep +containersdep +unordered-containersPVP ok

version bump matches the API change (PVP)

Dependencies added: containers, unordered-containers

API changes (from Hackage documentation)

- AtCoder.Extra.Monoid: RangeAddId :: a -> RangeAddId a
- AtCoder.Extra.Monoid: RangeSetId :: RangeSetIdRepr a -> RangeSetId a
- AtCoder.Extra.Monoid: newtype RangeAddId a
- AtCoder.Extra.Monoid: newtype RangeSetId a
- AtCoder.Extra.Monoid.RangeAdd: instance GHC.Num.Num a => AtCoder.LazySegTree.SegAct (AtCoder.Extra.Monoid.RangeAdd.RangeAdd a) (Data.Semigroup.Internal.Sum a)
- AtCoder.Extra.Monoid.RangeAdd: instance GHC.Num.Num a => GHC.Base.Monoid (AtCoder.Extra.Monoid.RangeAdd.RangeAdd a)
- AtCoder.Extra.Monoid.RangeAdd: instance GHC.Num.Num a => GHC.Base.Semigroup (AtCoder.Extra.Monoid.RangeAdd.RangeAdd a)
- AtCoder.Extra.Monoid.RangeAddId: RangeAddId :: a -> RangeAddId a
- AtCoder.Extra.Monoid.RangeAddId: act :: Num a => RangeAddId a -> a -> a
- AtCoder.Extra.Monoid.RangeAddId: instance Data.Vector.Unboxed.Base.Unbox a => Data.Vector.Generic.Base.Vector Data.Vector.Unboxed.Base.Vector (AtCoder.Extra.Monoid.RangeAddId.RangeAddId a)
- AtCoder.Extra.Monoid.RangeAddId: instance Data.Vector.Unboxed.Base.Unbox a => Data.Vector.Generic.Mutable.Base.MVector Data.Vector.Unboxed.Base.MVector (AtCoder.Extra.Monoid.RangeAddId.RangeAddId a)
- AtCoder.Extra.Monoid.RangeAddId: instance Data.Vector.Unboxed.Base.Unbox a => Data.Vector.Unboxed.Base.Unbox (AtCoder.Extra.Monoid.RangeAddId.RangeAddId a)
- AtCoder.Extra.Monoid.RangeAddId: instance GHC.Classes.Eq a => GHC.Classes.Eq (AtCoder.Extra.Monoid.RangeAddId.RangeAddId a)
- AtCoder.Extra.Monoid.RangeAddId: instance GHC.Classes.Ord a => GHC.Classes.Ord (AtCoder.Extra.Monoid.RangeAddId.RangeAddId a)
- AtCoder.Extra.Monoid.RangeAddId: instance GHC.Num.Num a => AtCoder.LazySegTree.SegAct (AtCoder.Extra.Monoid.RangeAddId.RangeAddId a) (Data.Semigroup.Max a)
- AtCoder.Extra.Monoid.RangeAddId: instance GHC.Num.Num a => AtCoder.LazySegTree.SegAct (AtCoder.Extra.Monoid.RangeAddId.RangeAddId a) (Data.Semigroup.Min a)
- AtCoder.Extra.Monoid.RangeAddId: instance GHC.Num.Num a => GHC.Base.Monoid (AtCoder.Extra.Monoid.RangeAddId.RangeAddId a)
- AtCoder.Extra.Monoid.RangeAddId: instance GHC.Num.Num a => GHC.Base.Semigroup (AtCoder.Extra.Monoid.RangeAddId.RangeAddId a)
- AtCoder.Extra.Monoid.RangeAddId: instance GHC.Show.Show a => GHC.Show.Show (AtCoder.Extra.Monoid.RangeAddId.RangeAddId a)
- AtCoder.Extra.Monoid.RangeAddId: new :: a -> RangeAddId a
- AtCoder.Extra.Monoid.RangeAddId: newtype RangeAddId a
- AtCoder.Extra.Monoid.RangeSetId: RangeSetId :: RangeSetIdRepr a -> RangeSetId a
- AtCoder.Extra.Monoid.RangeSetId: act :: RangeSetId a -> a -> a
- AtCoder.Extra.Monoid.RangeSetId: instance (GHC.Classes.Ord a, GHC.Enum.Bounded a) => AtCoder.LazySegTree.SegAct (AtCoder.Extra.Monoid.RangeSetId.RangeSetId (Data.Semigroup.Max a)) (Data.Semigroup.Max a)
- AtCoder.Extra.Monoid.RangeSetId: instance (GHC.Classes.Ord a, GHC.Enum.Bounded a) => AtCoder.LazySegTree.SegAct (AtCoder.Extra.Monoid.RangeSetId.RangeSetId (Data.Semigroup.Min a)) (Data.Semigroup.Min a)
- AtCoder.Extra.Monoid.RangeSetId: instance Data.Vector.Unboxed.Base.Unbox a => Data.Vector.Generic.Base.Vector Data.Vector.Unboxed.Base.Vector (AtCoder.Extra.Monoid.RangeSetId.RangeSetId a)
- AtCoder.Extra.Monoid.RangeSetId: instance Data.Vector.Unboxed.Base.Unbox a => Data.Vector.Generic.Mutable.Base.MVector Data.Vector.Unboxed.Base.MVector (AtCoder.Extra.Monoid.RangeSetId.RangeSetId a)
- AtCoder.Extra.Monoid.RangeSetId: instance Data.Vector.Unboxed.Base.Unbox a => Data.Vector.Unboxed.Base.Unbox (AtCoder.Extra.Monoid.RangeSetId.RangeSetId a)
- AtCoder.Extra.Monoid.RangeSetId: instance GHC.Base.Monoid a => GHC.Base.Monoid (AtCoder.Extra.Monoid.RangeSetId.RangeSetId a)
- AtCoder.Extra.Monoid.RangeSetId: instance GHC.Base.Semigroup (AtCoder.Extra.Monoid.RangeSetId.RangeSetId a)
- AtCoder.Extra.Monoid.RangeSetId: instance GHC.Classes.Eq a => GHC.Classes.Eq (AtCoder.Extra.Monoid.RangeSetId.RangeSetId a)
- AtCoder.Extra.Monoid.RangeSetId: instance GHC.Classes.Ord a => GHC.Classes.Ord (AtCoder.Extra.Monoid.RangeSetId.RangeSetId a)
- AtCoder.Extra.Monoid.RangeSetId: instance GHC.Show.Show a => GHC.Show.Show (AtCoder.Extra.Monoid.RangeSetId.RangeSetId a)
- AtCoder.Extra.Monoid.RangeSetId: new :: a -> RangeSetId a
- AtCoder.Extra.Monoid.RangeSetId: newtype RangeSetId a
+ AtCoder.Extra.Bisect: bisectL :: HasCallStack => Int -> Int -> (Int -> Bool) -> Maybe Int
+ AtCoder.Extra.Bisect: bisectLM :: (HasCallStack, Monad m) => Int -> Int -> (Int -> m Bool) -> m (Maybe Int)
+ AtCoder.Extra.Bisect: bisectR :: HasCallStack => Int -> Int -> (Int -> Bool) -> Maybe Int
+ AtCoder.Extra.Bisect: bisectRM :: (HasCallStack, Monad m) => Int -> Int -> (Int -> m Bool) -> m (Maybe Int)
+ AtCoder.Extra.Bisect: lowerBound :: (HasCallStack, Vector v a, Ord a) => v a -> a -> Maybe Int
+ AtCoder.Extra.Bisect: lowerBoundIn :: (Vector v a, Ord a) => Int -> Int -> v a -> a -> Maybe Int
+ AtCoder.Extra.Bisect: upperBound :: (HasCallStack, Vector v a, Ord a) => v a -> a -> Maybe Int
+ AtCoder.Extra.Bisect: upperBoundIn :: (Vector v a, Ord a) => Int -> Int -> v a -> a -> Maybe Int
+ AtCoder.Extra.Graph: scc :: Csr w -> Vector (Vector Int)
+ AtCoder.Extra.Graph: swapDupe :: Unbox (Int, Int, w) => Vector (Int, Int, w) -> Vector (Int, Int, w)
+ AtCoder.Extra.Graph: swapDupe' :: Unbox (Int, Int) => Vector (Int, Int) -> Vector (Int, Int)
+ AtCoder.Extra.Graph: topSort :: Int -> (Int -> Vector Int) -> Vector Int
+ AtCoder.Extra.HashMap: assocs :: (PrimMonad m, Unbox a) => HashMap (PrimState m) a -> m (Vector (Int, a))
+ AtCoder.Extra.HashMap: build :: (PrimMonad m, Unbox a) => Int -> Vector (Int, a) -> m (HashMap (PrimState m) a)
+ AtCoder.Extra.HashMap: capacity :: HashMap s a -> Int
+ AtCoder.Extra.HashMap: clear :: PrimMonad m => HashMap (PrimState m) a -> m ()
+ AtCoder.Extra.HashMap: data HashMap s a
+ AtCoder.Extra.HashMap: elems :: (PrimMonad m, Unbox a) => HashMap (PrimState m) a -> m (Vector a)
+ AtCoder.Extra.HashMap: exchange :: (HasCallStack, PrimMonad m, Unbox a) => HashMap (PrimState m) a -> Int -> a -> m (Maybe a)
+ AtCoder.Extra.HashMap: insert :: (HasCallStack, PrimMonad m, Unbox a) => HashMap (PrimState m) a -> Int -> a -> m ()
+ AtCoder.Extra.HashMap: insertWith :: (HasCallStack, PrimMonad m, Unbox a) => HashMap (PrimState m) a -> (a -> a -> a) -> Int -> a -> m ()
+ AtCoder.Extra.HashMap: keys :: (PrimMonad m, Unbox a) => HashMap (PrimState m) a -> m (Vector Int)
+ AtCoder.Extra.HashMap: lookup :: (HasCallStack, Unbox a, PrimMonad m) => HashMap (PrimState m) a -> Int -> m (Maybe a)
+ AtCoder.Extra.HashMap: member :: (HasCallStack, PrimMonad m) => HashMap (PrimState m) a -> Int -> m Bool
+ AtCoder.Extra.HashMap: modify :: (HasCallStack, PrimMonad m, Unbox a) => HashMap (PrimState m) a -> (a -> a) -> Int -> m ()
+ AtCoder.Extra.HashMap: modifyM :: (HasCallStack, PrimMonad m, Unbox a) => HashMap (PrimState m) a -> (a -> m a) -> Int -> m ()
+ AtCoder.Extra.HashMap: new :: (PrimMonad m, Unbox a) => Int -> m (HashMap (PrimState m) a)
+ AtCoder.Extra.HashMap: notMember :: (HasCallStack, PrimMonad m) => HashMap (PrimState m) a -> Int -> m Bool
+ AtCoder.Extra.HashMap: size :: PrimMonad m => HashMap (PrimState m) a -> m Int
+ AtCoder.Extra.HashMap: unsafeAssocs :: (PrimMonad m, Unbox a) => HashMap (PrimState m) a -> m (Vector (Int, a))
+ AtCoder.Extra.HashMap: unsafeElems :: (PrimMonad m, Unbox a) => HashMap (PrimState m) a -> m (Vector a)
+ AtCoder.Extra.HashMap: unsafeKeys :: (PrimMonad m, Unbox a) => HashMap (PrimState m) a -> m (Vector Int)
+ AtCoder.Extra.IntMap: assocs :: (PrimMonad m, Unbox a) => IntMap (PrimState m) a -> m (Vector (Int, a))
+ AtCoder.Extra.IntMap: build :: (PrimMonad m, Unbox a) => Int -> Vector (Int, a) -> m (IntMap (PrimState m) a)
+ AtCoder.Extra.IntMap: capacity :: IntMap s a -> Int
+ AtCoder.Extra.IntMap: data IntMap s a
+ AtCoder.Extra.IntMap: delete :: PrimMonad m => IntMap (PrimState m) a -> Int -> m Bool
+ AtCoder.Extra.IntMap: deleteMax :: (HasCallStack, PrimMonad m, Unbox a) => IntMap (PrimState m) a -> m (Maybe (Int, a))
+ AtCoder.Extra.IntMap: deleteMin :: (HasCallStack, PrimMonad m, Unbox a) => IntMap (PrimState m) a -> m (Maybe (Int, a))
+ AtCoder.Extra.IntMap: delete_ :: PrimMonad m => IntMap (PrimState m) a -> Int -> m ()
+ AtCoder.Extra.IntMap: elems :: (PrimMonad m, Unbox a) => IntMap (PrimState m) a -> m (Vector a)
+ AtCoder.Extra.IntMap: insert :: (HasCallStack, PrimMonad m, Unbox a) => IntMap (PrimState m) a -> Int -> a -> m ()
+ AtCoder.Extra.IntMap: insertWith :: (HasCallStack, PrimMonad m, Unbox a) => IntMap (PrimState m) a -> (a -> a -> a) -> Int -> a -> m ()
+ AtCoder.Extra.IntMap: keys :: PrimMonad m => IntMap (PrimState m) a -> m (Vector Int)
+ AtCoder.Extra.IntMap: lookup :: (PrimMonad m, Unbox a) => IntMap (PrimState m) a -> Int -> m (Maybe a)
+ AtCoder.Extra.IntMap: lookupGE :: (PrimMonad m, Unbox a) => IntMap (PrimState m) a -> Int -> m (Maybe (Int, a))
+ AtCoder.Extra.IntMap: lookupGT :: (PrimMonad m, Unbox a) => IntMap (PrimState m) a -> Int -> m (Maybe (Int, a))
+ AtCoder.Extra.IntMap: lookupLE :: (HasCallStack, PrimMonad m, Unbox a) => IntMap (PrimState m) a -> Int -> m (Maybe (Int, a))
+ AtCoder.Extra.IntMap: lookupLT :: (PrimMonad m, Unbox a) => IntMap (PrimState m) a -> Int -> m (Maybe (Int, a))
+ AtCoder.Extra.IntMap: lookupMax :: (PrimMonad m, Unbox a) => IntMap (PrimState m) a -> m (Maybe (Int, a))
+ AtCoder.Extra.IntMap: lookupMin :: (PrimMonad m, Unbox a) => IntMap (PrimState m) a -> m (Maybe (Int, a))
+ AtCoder.Extra.IntMap: member :: PrimMonad m => IntMap (PrimState m) a -> Int -> m Bool
+ AtCoder.Extra.IntMap: modify :: (HasCallStack, PrimMonad m, Unbox a) => IntMap (PrimState m) a -> (a -> a) -> Int -> m ()
+ AtCoder.Extra.IntMap: modifyM :: (HasCallStack, PrimMonad m, Unbox a) => IntMap (PrimState m) a -> (a -> m a) -> Int -> m ()
+ AtCoder.Extra.IntMap: new :: (PrimMonad m, Unbox a) => Int -> m (IntMap (PrimState m) a)
+ AtCoder.Extra.IntMap: notMember :: PrimMonad m => IntMap (PrimState m) a -> Int -> m Bool
+ AtCoder.Extra.IntMap: null :: PrimMonad m => IntMap (PrimState m) a -> m Bool
+ AtCoder.Extra.IntMap: size :: PrimMonad m => IntMap (PrimState m) a -> m Int
+ AtCoder.Extra.IntSet: build :: PrimMonad m => Int -> Vector Int -> m (IntSet (PrimState m))
+ AtCoder.Extra.IntSet: capacity :: IntSet s -> Int
+ AtCoder.Extra.IntSet: data IntSet s
+ AtCoder.Extra.IntSet: delete :: PrimMonad m => IntSet (PrimState m) -> Int -> m Bool
+ AtCoder.Extra.IntSet: deleteMax :: PrimMonad m => IntSet (PrimState m) -> m (Maybe Int)
+ AtCoder.Extra.IntSet: deleteMin :: PrimMonad m => IntSet (PrimState m) -> m (Maybe Int)
+ AtCoder.Extra.IntSet: delete_ :: PrimMonad m => IntSet (PrimState m) -> Int -> m ()
+ AtCoder.Extra.IntSet: insert :: (HasCallStack, PrimMonad m) => IntSet (PrimState m) -> Int -> m ()
+ AtCoder.Extra.IntSet: keys :: PrimMonad m => IntSet (PrimState m) -> m (Vector Int)
+ AtCoder.Extra.IntSet: lookupGE :: PrimMonad m => IntSet (PrimState m) -> Int -> m (Maybe Int)
+ AtCoder.Extra.IntSet: lookupGT :: PrimMonad m => IntSet (PrimState m) -> Int -> m (Maybe Int)
+ AtCoder.Extra.IntSet: lookupLE :: PrimMonad m => IntSet (PrimState m) -> Int -> m (Maybe Int)
+ AtCoder.Extra.IntSet: lookupLT :: PrimMonad m => IntSet (PrimState m) -> Int -> m (Maybe Int)
+ AtCoder.Extra.IntSet: lookupMax :: PrimMonad m => IntSet (PrimState m) -> m (Maybe Int)
+ AtCoder.Extra.IntSet: lookupMin :: PrimMonad m => IntSet (PrimState m) -> m (Maybe Int)
+ AtCoder.Extra.IntSet: member :: PrimMonad m => IntSet (PrimState m) -> Int -> m Bool
+ AtCoder.Extra.IntSet: new :: PrimMonad m => Int -> m (IntSet (PrimState m))
+ AtCoder.Extra.IntSet: notMember :: PrimMonad m => IntSet (PrimState m) -> Int -> m Bool
+ AtCoder.Extra.IntSet: null :: PrimMonad m => IntSet (PrimState m) -> m Bool
+ AtCoder.Extra.IntSet: size :: PrimMonad m => IntSet (PrimState m) -> m Int
+ AtCoder.Extra.IntervalMap: build :: (PrimMonad m, Eq a, Unbox a) => Vector a -> m (IntervalMap (PrimState m) a)
+ AtCoder.Extra.IntervalMap: buildM :: (PrimMonad m, Eq a, Unbox a) => Vector a -> (Int -> Int -> a -> m ()) -> m (IntervalMap (PrimState m) a)
+ AtCoder.Extra.IntervalMap: capacity :: IntervalMap s a -> Int
+ AtCoder.Extra.IntervalMap: contains :: (PrimMonad m, Unbox a) => IntervalMap (PrimState m) a -> Int -> m Bool
+ AtCoder.Extra.IntervalMap: data IntervalMap s a
+ AtCoder.Extra.IntervalMap: delete :: (PrimMonad m, Unbox a) => IntervalMap (PrimState m) a -> Int -> Int -> m ()
+ AtCoder.Extra.IntervalMap: deleteM :: (PrimMonad m, Unbox a) => IntervalMap (PrimState m) a -> Int -> Int -> (Int -> Int -> a -> m ()) -> (Int -> Int -> a -> m ()) -> m ()
+ AtCoder.Extra.IntervalMap: freeze :: (PrimMonad m, Unbox a) => IntervalMap (PrimState m) a -> m (Vector (Int, (Int, a)))
+ AtCoder.Extra.IntervalMap: insert :: (PrimMonad m, Eq a, Unbox a) => IntervalMap (PrimState m) a -> Int -> Int -> a -> m ()
+ AtCoder.Extra.IntervalMap: insertM :: (PrimMonad m, Eq a, Unbox a) => IntervalMap (PrimState m) a -> Int -> Int -> a -> (Int -> Int -> a -> m ()) -> (Int -> Int -> a -> m ()) -> m ()
+ AtCoder.Extra.IntervalMap: intersects :: (PrimMonad m, Unbox a) => IntervalMap (PrimState m) a -> Int -> Int -> m Bool
+ AtCoder.Extra.IntervalMap: lookup :: (PrimMonad m, Unbox a) => IntervalMap (PrimState m) a -> Int -> Int -> m (Maybe (Int, Int, a))
+ AtCoder.Extra.IntervalMap: new :: (PrimMonad m, Unbox a) => Int -> m (IntervalMap (PrimState m) a)
+ AtCoder.Extra.IntervalMap: overwrite :: (PrimMonad m, Eq a, Unbox a) => IntervalMap (PrimState m) a -> Int -> Int -> a -> m ()
+ AtCoder.Extra.IntervalMap: overwriteM :: (PrimMonad m, Eq a, Unbox a) => IntervalMap (PrimState m) a -> Int -> Int -> a -> (Int -> Int -> a -> m ()) -> (Int -> Int -> a -> m ()) -> m ()
+ AtCoder.Extra.IntervalMap: read :: (HasCallStack, PrimMonad m, Unbox a) => IntervalMap (PrimState m) a -> Int -> Int -> m a
+ AtCoder.Extra.IntervalMap: readMaybe :: (PrimMonad m, Unbox a) => IntervalMap (PrimState m) a -> Int -> Int -> m (Maybe a)
+ AtCoder.Extra.Math: invGcd :: Int -> Int -> (Int, Int)
+ AtCoder.Extra.Math: isPrime32 :: Int -> Bool
+ AtCoder.Extra.Math: primitiveRoot :: Int -> Int
+ AtCoder.Extra.Monoid: Mat2x2 :: Mat2x2Repr a -> Mat2x2 a
+ AtCoder.Extra.Monoid: V2 :: V2Repr a -> V2 a
+ AtCoder.Extra.Monoid: data RollingHash b p
+ AtCoder.Extra.Monoid: newtype Mat2x2 a
+ AtCoder.Extra.Monoid: newtype V2 a
+ AtCoder.Extra.Monoid: type Mat2x2Repr a = (a, a, a, a)
+ AtCoder.Extra.Monoid: type RangeSetRepr a = (Bit, a)
+ AtCoder.Extra.Monoid: type V2Repr a = (a, a)
+ AtCoder.Extra.Monoid.Affine1: ident :: Num a => Affine1 a
+ AtCoder.Extra.Monoid.Affine1: unAffine1 :: Affine1 a -> Affine1Repr a
+ AtCoder.Extra.Monoid.Affine1: zero :: Num a => Affine1 a
+ AtCoder.Extra.Monoid.Mat2x2: Mat2x2 :: Mat2x2Repr a -> Mat2x2 a
+ AtCoder.Extra.Monoid.Mat2x2: act :: Num a => Mat2x2 a -> V2 a -> V2 a
+ AtCoder.Extra.Monoid.Mat2x2: det :: Fractional e => Mat2x2 e -> e
+ AtCoder.Extra.Monoid.Mat2x2: ident :: Num a => Mat2x2 a
+ AtCoder.Extra.Monoid.Mat2x2: instance Data.Vector.Unboxed.Base.Unbox a => Data.Vector.Generic.Base.Vector Data.Vector.Unboxed.Base.Vector (AtCoder.Extra.Monoid.Mat2x2.Mat2x2 a)
+ AtCoder.Extra.Monoid.Mat2x2: instance Data.Vector.Unboxed.Base.Unbox a => Data.Vector.Generic.Mutable.Base.MVector Data.Vector.Unboxed.Base.MVector (AtCoder.Extra.Monoid.Mat2x2.Mat2x2 a)
+ AtCoder.Extra.Monoid.Mat2x2: instance Data.Vector.Unboxed.Base.Unbox a => Data.Vector.Unboxed.Base.Unbox (AtCoder.Extra.Monoid.Mat2x2.Mat2x2 a)
+ AtCoder.Extra.Monoid.Mat2x2: instance GHC.Classes.Eq a => GHC.Classes.Eq (AtCoder.Extra.Monoid.Mat2x2.Mat2x2 a)
+ AtCoder.Extra.Monoid.Mat2x2: instance GHC.Classes.Ord a => GHC.Classes.Ord (AtCoder.Extra.Monoid.Mat2x2.Mat2x2 a)
+ AtCoder.Extra.Monoid.Mat2x2: instance GHC.Num.Num a => AtCoder.LazySegTree.SegAct (AtCoder.Extra.Monoid.Mat2x2.Mat2x2 a) (AtCoder.Extra.Monoid.V2.V2 a)
+ AtCoder.Extra.Monoid.Mat2x2: instance GHC.Num.Num a => AtCoder.LazySegTree.SegAct (Data.Semigroup.Internal.Dual (AtCoder.Extra.Monoid.Mat2x2.Mat2x2 a)) (AtCoder.Extra.Monoid.V2.V2 a)
+ AtCoder.Extra.Monoid.Mat2x2: instance GHC.Num.Num a => GHC.Base.Monoid (AtCoder.Extra.Monoid.Mat2x2.Mat2x2 a)
+ AtCoder.Extra.Monoid.Mat2x2: instance GHC.Num.Num a => GHC.Base.Semigroup (AtCoder.Extra.Monoid.Mat2x2.Mat2x2 a)
+ AtCoder.Extra.Monoid.Mat2x2: instance GHC.Show.Show a => GHC.Show.Show (AtCoder.Extra.Monoid.Mat2x2.Mat2x2 a)
+ AtCoder.Extra.Monoid.Mat2x2: inv :: (HasCallStack, Fractional e, Eq e) => Mat2x2 e -> Mat2x2 e
+ AtCoder.Extra.Monoid.Mat2x2: map :: (a -> b) -> Mat2x2 a -> Mat2x2 b
+ AtCoder.Extra.Monoid.Mat2x2: new :: Num a => a -> a -> Mat2x2 a
+ AtCoder.Extra.Monoid.Mat2x2: newtype Mat2x2 a
+ AtCoder.Extra.Monoid.Mat2x2: type Mat2x2Repr a = (a, a, a, a)
+ AtCoder.Extra.Monoid.Mat2x2: unMat2x2 :: Mat2x2 a -> Mat2x2Repr a
+ AtCoder.Extra.Monoid.Mat2x2: zero :: Num a => Mat2x2 a
+ AtCoder.Extra.Monoid.RangeAdd: instance GHC.Base.Monoid (Data.Semigroup.Internal.Sum a) => AtCoder.LazySegTree.SegAct (AtCoder.Extra.Monoid.RangeAdd.RangeAdd (Data.Semigroup.Internal.Sum a)) (Data.Semigroup.Internal.Sum a)
+ AtCoder.Extra.Monoid.RangeAdd: instance GHC.Base.Monoid (Data.Semigroup.Max a) => AtCoder.LazySegTree.SegAct (AtCoder.Extra.Monoid.RangeAdd.RangeAdd (Data.Semigroup.Max a)) (Data.Semigroup.Max a)
+ AtCoder.Extra.Monoid.RangeAdd: instance GHC.Base.Monoid (Data.Semigroup.Min a) => AtCoder.LazySegTree.SegAct (AtCoder.Extra.Monoid.RangeAdd.RangeAdd (Data.Semigroup.Min a)) (Data.Semigroup.Min a)
+ AtCoder.Extra.Monoid.RangeAdd: instance GHC.Base.Monoid a => GHC.Base.Monoid (AtCoder.Extra.Monoid.RangeAdd.RangeAdd a)
+ AtCoder.Extra.Monoid.RangeAdd: instance GHC.Base.Semigroup a => GHC.Base.Semigroup (AtCoder.Extra.Monoid.RangeAdd.RangeAdd a)
+ AtCoder.Extra.Monoid.RangeAdd: unRangeAdd :: RangeAdd a -> a
+ AtCoder.Extra.Monoid.RangeSet: type RangeSetRepr a = (Bit, a)
+ AtCoder.Extra.Monoid.RangeSet: unRangeSet :: RangeSet a -> RangeSetRepr a
+ AtCoder.Extra.Monoid.RollingHash: RollingHash :: {-# UNPACK #-} !Int -> {-# UNPACK #-} !Int -> RollingHash b p
+ AtCoder.Extra.Monoid.RollingHash: [hashRH] :: RollingHash b p -> {-# UNPACK #-} !Int
+ AtCoder.Extra.Monoid.RollingHash: [nextDigitRH] :: RollingHash b p -> {-# UNPACK #-} !Int
+ AtCoder.Extra.Monoid.RollingHash: data RollingHash b p
+ AtCoder.Extra.Monoid.RollingHash: instance (GHC.TypeNats.KnownNat b, GHC.TypeNats.KnownNat p) => GHC.Base.Monoid (AtCoder.Extra.Monoid.RollingHash.RollingHash b p)
+ AtCoder.Extra.Monoid.RollingHash: instance (GHC.TypeNats.KnownNat b, GHC.TypeNats.KnownNat p) => GHC.Base.Semigroup (AtCoder.Extra.Monoid.RollingHash.RollingHash b p)
+ AtCoder.Extra.Monoid.RollingHash: instance forall k1 (b :: k1) k2 (p :: k2). Data.Vector.Generic.Base.Vector Data.Vector.Unboxed.Base.Vector (AtCoder.Extra.Monoid.RollingHash.RollingHash b p)
+ AtCoder.Extra.Monoid.RollingHash: instance forall k1 (b :: k1) k2 (p :: k2). Data.Vector.Generic.Mutable.Base.MVector Data.Vector.Unboxed.Base.MVector (AtCoder.Extra.Monoid.RollingHash.RollingHash b p)
+ AtCoder.Extra.Monoid.RollingHash: instance forall k1 (b :: k1) k2 (p :: k2). GHC.Classes.Eq (AtCoder.Extra.Monoid.RollingHash.RollingHash b p)
+ AtCoder.Extra.Monoid.RollingHash: instance forall k1 (b :: k1) k2 (p :: k2). GHC.Show.Show (AtCoder.Extra.Monoid.RollingHash.RollingHash b p)
+ AtCoder.Extra.Monoid.RollingHash: instance forall k1 k2 (b :: k1) (p :: k2). Data.Vector.Unboxed.Base.IsoUnbox (AtCoder.Extra.Monoid.RollingHash.RollingHash b p) AtCoder.Extra.Monoid.RollingHash.RHRepr
+ AtCoder.Extra.Monoid.RollingHash: instance forall k1 k2 (b :: k1) (p :: k2). Data.Vector.Unboxed.Base.Unbox (AtCoder.Extra.Monoid.RollingHash.RollingHash b p)
+ AtCoder.Extra.Monoid.RollingHash: new :: forall b p. (KnownNat b, KnownNat p) => Int -> RollingHash b p
+ AtCoder.Extra.Monoid.RollingHash: unsafeNew :: forall b p. (KnownNat b, KnownNat p) => Int -> RollingHash b p
+ AtCoder.Extra.Monoid.V2: V2 :: V2Repr a -> V2 a
+ AtCoder.Extra.Monoid.V2: instance Data.Vector.Unboxed.Base.Unbox a => Data.Vector.Generic.Base.Vector Data.Vector.Unboxed.Base.Vector (AtCoder.Extra.Monoid.V2.V2 a)
+ AtCoder.Extra.Monoid.V2: instance Data.Vector.Unboxed.Base.Unbox a => Data.Vector.Generic.Mutable.Base.MVector Data.Vector.Unboxed.Base.MVector (AtCoder.Extra.Monoid.V2.V2 a)
+ AtCoder.Extra.Monoid.V2: instance Data.Vector.Unboxed.Base.Unbox a => Data.Vector.Unboxed.Base.Unbox (AtCoder.Extra.Monoid.V2.V2 a)
+ AtCoder.Extra.Monoid.V2: instance GHC.Classes.Eq a => GHC.Classes.Eq (AtCoder.Extra.Monoid.V2.V2 a)
+ AtCoder.Extra.Monoid.V2: instance GHC.Classes.Ord a => GHC.Classes.Ord (AtCoder.Extra.Monoid.V2.V2 a)
+ AtCoder.Extra.Monoid.V2: instance GHC.Num.Num a => GHC.Base.Monoid (AtCoder.Extra.Monoid.V2.V2 a)
+ AtCoder.Extra.Monoid.V2: instance GHC.Num.Num a => GHC.Base.Semigroup (AtCoder.Extra.Monoid.V2.V2 a)
+ AtCoder.Extra.Monoid.V2: instance GHC.Show.Show a => GHC.Show.Show (AtCoder.Extra.Monoid.V2.V2 a)
+ AtCoder.Extra.Monoid.V2: new :: Num a => a -> V2 a
+ AtCoder.Extra.Monoid.V2: newtype V2 a
+ AtCoder.Extra.Monoid.V2: type V2Repr a = (a, a)
+ AtCoder.Extra.Monoid.V2: unV2 :: V2 a -> a
+ AtCoder.Extra.MultiSet: add :: (HasCallStack, PrimMonad m) => MultiSet (PrimState m) -> Int -> Int -> m ()
+ AtCoder.Extra.MultiSet: assocs :: PrimMonad m => MultiSet (PrimState m) -> m (Vector (Int, Int))
+ AtCoder.Extra.MultiSet: capacity :: MultiSet s -> Int
+ AtCoder.Extra.MultiSet: data MultiSet s
+ AtCoder.Extra.MultiSet: dec :: (HasCallStack, PrimMonad m) => MultiSet (PrimState m) -> Int -> m ()
+ AtCoder.Extra.MultiSet: delete :: (HasCallStack, PrimMonad m) => MultiSet (PrimState m) -> Int -> m ()
+ AtCoder.Extra.MultiSet: elems :: PrimMonad m => MultiSet (PrimState m) -> m (Vector Int)
+ AtCoder.Extra.MultiSet: inc :: (HasCallStack, PrimMonad m) => MultiSet (PrimState m) -> Int -> m ()
+ AtCoder.Extra.MultiSet: insert :: (HasCallStack, PrimMonad m) => MultiSet (PrimState m) -> Int -> Int -> m ()
+ AtCoder.Extra.MultiSet: keys :: PrimMonad m => MultiSet (PrimState m) -> m (Vector Int)
+ AtCoder.Extra.MultiSet: lookup :: PrimMonad m => MultiSet (PrimState m) -> Int -> m (Maybe Int)
+ AtCoder.Extra.MultiSet: member :: PrimMonad m => MultiSet (PrimState m) -> Int -> m Bool
+ AtCoder.Extra.MultiSet: new :: PrimMonad m => Int -> m (MultiSet (PrimState m))
+ AtCoder.Extra.MultiSet: notMember :: PrimMonad m => MultiSet (PrimState m) -> Int -> m Bool
+ AtCoder.Extra.MultiSet: size :: PrimMonad m => MultiSet (PrimState m) -> m Int
+ AtCoder.Extra.MultiSet: sub :: (HasCallStack, PrimMonad m) => MultiSet (PrimState m) -> Int -> Int -> m ()
+ AtCoder.Extra.MultiSet: unsafeAssocs :: PrimMonad m => MultiSet (PrimState m) -> m (Vector (Int, Int))
+ AtCoder.Extra.MultiSet: unsafeElems :: PrimMonad m => MultiSet (PrimState m) -> m (Vector Int)
+ AtCoder.Extra.MultiSet: unsafeKeys :: PrimMonad m => MultiSet (PrimState m) -> m (Vector Int)
+ AtCoder.Extra.Pdsu: canMerge :: (HasCallStack, PrimMonad m, Semigroup a, Eq a, Unbox a) => Pdsu (PrimState m) a -> Int -> Int -> a -> m Bool
+ AtCoder.Extra.Pdsu: clear :: forall m a. (PrimMonad m, Monoid a, Unbox a) => Pdsu (PrimState m) a -> m ()
+ AtCoder.Extra.Pdsu: data Pdsu s a
+ AtCoder.Extra.Pdsu: diff :: (HasCallStack, PrimMonad m, Monoid a, Unbox a) => Pdsu (PrimState m) a -> Int -> Int -> m (Maybe a)
+ AtCoder.Extra.Pdsu: groups :: (PrimMonad m, Semigroup a, Unbox a) => Pdsu (PrimState m) a -> m (Vector (Vector Int))
+ AtCoder.Extra.Pdsu: leader :: (HasCallStack, PrimMonad m, Semigroup a, Unbox a) => Pdsu (PrimState m) a -> Int -> m Int
+ AtCoder.Extra.Pdsu: merge :: (HasCallStack, PrimMonad m, Monoid a, Ord a, Unbox a) => Pdsu (PrimState m) a -> Int -> Int -> a -> m Bool
+ AtCoder.Extra.Pdsu: merge_ :: (HasCallStack, PrimMonad m, Monoid a, Ord a, Unbox a) => Pdsu (PrimState m) a -> Int -> Int -> a -> m ()
+ AtCoder.Extra.Pdsu: new :: forall m a. (PrimMonad m, Monoid a, Unbox a) => Int -> (a -> a) -> m (Pdsu (PrimState m) a)
+ AtCoder.Extra.Pdsu: pot :: (HasCallStack, PrimMonad m, Semigroup a, Unbox a) => Pdsu (PrimState m) a -> Int -> m a
+ AtCoder.Extra.Pdsu: same :: (HasCallStack, PrimMonad m, Semigroup a, Unbox a) => Pdsu (PrimState m) a -> Int -> Int -> m Bool
+ AtCoder.Extra.Pdsu: size :: (HasCallStack, PrimMonad m, Semigroup a, Unbox a) => Pdsu (PrimState m) a -> Int -> m Int
+ AtCoder.Extra.Pdsu: unsafeDiff :: (HasCallStack, PrimMonad m, Monoid a, Unbox a) => Pdsu (PrimState m) a -> Int -> Int -> m a
+ AtCoder.Extra.Semigroup.Matrix: Matrix :: {-# UNPACK #-} !Int -> {-# UNPACK #-} !Int -> !Vector a -> Matrix a
+ AtCoder.Extra.Semigroup.Matrix: [hM] :: Matrix a -> {-# UNPACK #-} !Int
+ AtCoder.Extra.Semigroup.Matrix: [vecM] :: Matrix a -> !Vector a
+ AtCoder.Extra.Semigroup.Matrix: [wM] :: Matrix a -> {-# UNPACK #-} !Int
+ AtCoder.Extra.Semigroup.Matrix: data Matrix a
+ AtCoder.Extra.Semigroup.Matrix: diag :: (Unbox a, Num a) => Int -> Vector a -> Matrix a
+ AtCoder.Extra.Semigroup.Matrix: ident :: (Unbox a, Num a) => Int -> Matrix a
+ AtCoder.Extra.Semigroup.Matrix: instance (Data.Vector.Unboxed.Base.Unbox a, GHC.Classes.Eq a) => GHC.Classes.Eq (AtCoder.Extra.Semigroup.Matrix.Matrix a)
+ AtCoder.Extra.Semigroup.Matrix: instance (GHC.Num.Num a, Data.Vector.Unboxed.Base.Unbox a) => GHC.Base.Semigroup (AtCoder.Extra.Semigroup.Matrix.Matrix a)
+ AtCoder.Extra.Semigroup.Matrix: instance (GHC.Show.Show a, Data.Vector.Unboxed.Base.Unbox a) => GHC.Show.Show (AtCoder.Extra.Semigroup.Matrix.Matrix a)
+ AtCoder.Extra.Semigroup.Matrix: map :: (Unbox a, Unbox b) => (a -> b) -> Matrix a -> Matrix b
+ AtCoder.Extra.Semigroup.Matrix: mul :: (Num e, Unbox e) => Matrix e -> Matrix e -> Matrix e
+ AtCoder.Extra.Semigroup.Matrix: mulMint :: forall a. KnownNat a => Matrix (ModInt a) -> Matrix (ModInt a) -> Matrix (ModInt a)
+ AtCoder.Extra.Semigroup.Matrix: mulMod :: Int -> Matrix Int -> Matrix Int -> Matrix Int
+ AtCoder.Extra.Semigroup.Matrix: mulToCol :: (Num a, Unbox a) => Matrix a -> Col a -> Col a
+ AtCoder.Extra.Semigroup.Matrix: new :: (HasCallStack, Unbox a) => Int -> Int -> Vector a -> Matrix a
+ AtCoder.Extra.Semigroup.Matrix: pow :: Int -> Matrix Int -> Matrix Int
+ AtCoder.Extra.Semigroup.Matrix: powMint :: forall m. KnownNat m => Int -> Matrix (ModInt m) -> Matrix (ModInt m)
+ AtCoder.Extra.Semigroup.Matrix: powMod :: Int -> Int -> Matrix Int -> Matrix Int
+ AtCoder.Extra.Semigroup.Matrix: zero :: (Unbox a, Num a) => Int -> Matrix a
+ AtCoder.Extra.Semigroup.Permutation: Permutation :: Vector Int -> Permutation
+ AtCoder.Extra.Semigroup.Permutation: [unPermutation] :: Permutation -> Vector Int
+ AtCoder.Extra.Semigroup.Permutation: act :: HasCallStack => Permutation -> Int -> Int
+ AtCoder.Extra.Semigroup.Permutation: ident :: Int -> Permutation
+ AtCoder.Extra.Semigroup.Permutation: instance GHC.Base.Semigroup AtCoder.Extra.Semigroup.Permutation.Permutation
+ AtCoder.Extra.Semigroup.Permutation: instance GHC.Classes.Eq AtCoder.Extra.Semigroup.Permutation.Permutation
+ AtCoder.Extra.Semigroup.Permutation: instance GHC.Show.Show AtCoder.Extra.Semigroup.Permutation.Permutation
+ AtCoder.Extra.Semigroup.Permutation: length :: HasCallStack => Permutation -> Int
+ AtCoder.Extra.Semigroup.Permutation: new :: HasCallStack => Vector Int -> Permutation
+ AtCoder.Extra.Semigroup.Permutation: newtype Permutation
+ AtCoder.Extra.Semigroup.Permutation: unsafeNew :: HasCallStack => Vector Int -> Permutation
+ AtCoder.Extra.Semigroup.Permutation: zero :: Int -> Permutation
+ AtCoder.Extra.Tree: fold :: (HasCallStack, Unbox w) => (Int -> Vector (Int, w)) -> (Int -> a) -> (a -> (Int, w) -> f) -> (f -> a -> a) -> Int -> a
+ AtCoder.Extra.Tree: foldReroot :: forall w f a. (HasCallStack, Unbox w, Unbox a, Unbox f, Monoid f) => Int -> (Int -> Vector (Int, w)) -> (Int -> a) -> (a -> (Int, w) -> f) -> (f -> a -> a) -> Vector a
+ AtCoder.Extra.Tree: scan :: (Unbox w, Vector v a) => Int -> (Int -> Vector (Int, w)) -> (Int -> a) -> (a -> (Int, w) -> f) -> (f -> a -> a) -> Int -> v a
+ AtCoder.Extra.Tree.Hld: Hld :: {-# UNPACK #-} !Vertex -> !Vector Vertex -> !Vector VertexHld -> !Vector Vertex -> !Vector Vertex -> !Vector Int -> !Vector Int -> Hld
+ AtCoder.Extra.Tree.Hld: WeightsAreOnEdges :: WeightPolicy
+ AtCoder.Extra.Tree.Hld: WeightsAreOnVertices :: WeightPolicy
+ AtCoder.Extra.Tree.Hld: [depthHld] :: Hld -> !Vector Int
+ AtCoder.Extra.Tree.Hld: [headHld] :: Hld -> !Vector Vertex
+ AtCoder.Extra.Tree.Hld: [indexHld] :: Hld -> !Vector VertexHld
+ AtCoder.Extra.Tree.Hld: [parentHld] :: Hld -> !Vector Vertex
+ AtCoder.Extra.Tree.Hld: [revIndexHld] :: Hld -> !Vector Vertex
+ AtCoder.Extra.Tree.Hld: [rootHld] :: Hld -> {-# UNPACK #-} !Vertex
+ AtCoder.Extra.Tree.Hld: [subtreeSizeHld] :: Hld -> !Vector Int
+ AtCoder.Extra.Tree.Hld: ancestor :: HasCallStack => Hld -> Vertex -> Int -> Vertex
+ AtCoder.Extra.Tree.Hld: data Hld
+ AtCoder.Extra.Tree.Hld: data WeightPolicy
+ AtCoder.Extra.Tree.Hld: instance GHC.Classes.Eq AtCoder.Extra.Tree.Hld.Hld
+ AtCoder.Extra.Tree.Hld: instance GHC.Classes.Eq AtCoder.Extra.Tree.Hld.WeightPolicy
+ AtCoder.Extra.Tree.Hld: instance GHC.Show.Show AtCoder.Extra.Tree.Hld.Hld
+ AtCoder.Extra.Tree.Hld: instance GHC.Show.Show AtCoder.Extra.Tree.Hld.WeightPolicy
+ AtCoder.Extra.Tree.Hld: isInSubtree :: HasCallStack => Hld -> Vertex -> Vertex -> Bool
+ AtCoder.Extra.Tree.Hld: jump :: HasCallStack => Hld -> Vertex -> Vertex -> Int -> Maybe Vertex
+ AtCoder.Extra.Tree.Hld: lca :: HasCallStack => Hld -> Vertex -> Vertex -> Vertex
+ AtCoder.Extra.Tree.Hld: lengthBetween :: HasCallStack => Hld -> Vertex -> Vertex -> Int
+ AtCoder.Extra.Tree.Hld: new :: forall w. HasCallStack => Csr w -> Hld
+ AtCoder.Extra.Tree.Hld: newAt :: forall w. HasCallStack => Csr w -> Vertex -> Hld
+ AtCoder.Extra.Tree.Hld: path :: HasCallStack => Hld -> Vertex -> Vertex -> [Vertex]
+ AtCoder.Extra.Tree.Hld: pathSegmentsInclusive :: HasCallStack => WeightPolicy -> Hld -> Vertex -> Vertex -> [(VertexHld, VertexHld)]
+ AtCoder.Extra.Tree.Hld: prod :: (HasCallStack, Monoid mono, Monad m) => WeightPolicy -> Hld -> (VertexHld -> VertexHld -> m mono) -> (VertexHld -> VertexHld -> m mono) -> Vertex -> Vertex -> m mono
+ AtCoder.Extra.Tree.Hld: subtreeSegmentInclusive :: HasCallStack => Hld -> Vertex -> (VertexHld, VertexHld)
+ AtCoder.Extra.Tree.Hld: type Vertex = Int
+ AtCoder.Extra.Tree.Hld: type VertexHld = Vertex
+ AtCoder.Extra.Tree.TreeMonoid: Commute :: Commutativity
+ AtCoder.Extra.Tree.TreeMonoid: NonCommute :: Commutativity
+ AtCoder.Extra.Tree.TreeMonoid: data Commutativity
+ AtCoder.Extra.Tree.TreeMonoid: data TreeMonoid a s
+ AtCoder.Extra.Tree.TreeMonoid: exchange :: (HasCallStack, PrimMonad m, Monoid a, Unbox a) => TreeMonoid a (PrimState m) -> Vertex -> a -> m a
+ AtCoder.Extra.Tree.TreeMonoid: fromEdges :: (HasCallStack, PrimMonad m, Monoid a, Unbox a) => Hld -> Commutativity -> Vector (Vertex, Vertex, a) -> m (TreeMonoid a (PrimState m))
+ AtCoder.Extra.Tree.TreeMonoid: fromVerts :: (HasCallStack, PrimMonad m, Monoid a, Unbox a) => Hld -> Commutativity -> Vector a -> m (TreeMonoid a (PrimState m))
+ AtCoder.Extra.Tree.TreeMonoid: instance GHC.Classes.Eq AtCoder.Extra.Tree.TreeMonoid.Commutativity
+ AtCoder.Extra.Tree.TreeMonoid: instance GHC.Show.Show AtCoder.Extra.Tree.TreeMonoid.Commutativity
+ AtCoder.Extra.Tree.TreeMonoid: modify :: (HasCallStack, PrimMonad m, Monoid a, Unbox a) => TreeMonoid a (PrimState m) -> (a -> a) -> Int -> m ()
+ AtCoder.Extra.Tree.TreeMonoid: modifyM :: (HasCallStack, PrimMonad m, Monoid a, Unbox a) => TreeMonoid a (PrimState m) -> (a -> m a) -> Int -> m ()
+ AtCoder.Extra.Tree.TreeMonoid: prod :: (HasCallStack, PrimMonad m, Monoid a, Unbox a) => TreeMonoid a (PrimState m) -> Vertex -> Vertex -> m a
+ AtCoder.Extra.Tree.TreeMonoid: prodSubtree :: (HasCallStack, PrimMonad m, Monoid a, Unbox a) => TreeMonoid a (PrimState m) -> Vertex -> m a
+ AtCoder.Extra.Tree.TreeMonoid: read :: (HasCallStack, PrimMonad m, Monoid a, Unbox a) => TreeMonoid a (PrimState m) -> Vertex -> m a
+ AtCoder.Extra.Tree.TreeMonoid: type Vertex = Int
+ AtCoder.Extra.Tree.TreeMonoid: type VertexHld = Vertex
+ AtCoder.Extra.Tree.TreeMonoid: write :: (HasCallStack, PrimMonad m, Monoid a, Unbox a) => TreeMonoid a (PrimState m) -> Vertex -> a -> m ()
+ AtCoder.Extra.WaveletMatrix: WaveletMatrix :: !RawWaveletMatrix -> !Vector Int -> WaveletMatrix
+ AtCoder.Extra.WaveletMatrix: [rawWM] :: WaveletMatrix -> !RawWaveletMatrix
+ AtCoder.Extra.WaveletMatrix: [xDictWM] :: WaveletMatrix -> !Vector Int
+ AtCoder.Extra.WaveletMatrix: access :: WaveletMatrix -> Int -> Maybe Int
+ AtCoder.Extra.WaveletMatrix: assocsIn :: WaveletMatrix -> Int -> Int -> [(Int, Int)]
+ AtCoder.Extra.WaveletMatrix: build :: Vector Int -> WaveletMatrix
+ AtCoder.Extra.WaveletMatrix: data WaveletMatrix
+ AtCoder.Extra.WaveletMatrix: descAssocsIn :: WaveletMatrix -> Int -> Int -> [(Int, Int)]
+ AtCoder.Extra.WaveletMatrix: ikthLargestIn :: WaveletMatrix -> Int -> Int -> Int -> Maybe (Int, Int)
+ AtCoder.Extra.WaveletMatrix: ikthSmallestIn :: WaveletMatrix -> Int -> Int -> Int -> Maybe (Int, Int)
+ AtCoder.Extra.WaveletMatrix: kthLargestIn :: WaveletMatrix -> Int -> Int -> Int -> Maybe Int
+ AtCoder.Extra.WaveletMatrix: kthSmallestIn :: WaveletMatrix -> Int -> Int -> Int -> Maybe Int
+ AtCoder.Extra.WaveletMatrix: lookupGE :: WaveletMatrix -> Int -> Int -> Int -> Maybe Int
+ AtCoder.Extra.WaveletMatrix: lookupGT :: WaveletMatrix -> Int -> Int -> Int -> Maybe Int
+ AtCoder.Extra.WaveletMatrix: lookupLE :: WaveletMatrix -> Int -> Int -> Int -> Maybe Int
+ AtCoder.Extra.WaveletMatrix: lookupLT :: WaveletMatrix -> Int -> Int -> Int -> Maybe Int
+ AtCoder.Extra.WaveletMatrix: rank :: WaveletMatrix -> Int -> Int -> Int -> Int
+ AtCoder.Extra.WaveletMatrix: rankBetween :: WaveletMatrix -> Int -> Int -> Int -> Int -> Int
+ AtCoder.Extra.WaveletMatrix: select :: WaveletMatrix -> Int -> Maybe Int
+ AtCoder.Extra.WaveletMatrix: selectIn :: WaveletMatrix -> Int -> Int -> Int -> Maybe Int
+ AtCoder.Extra.WaveletMatrix: selectKth :: WaveletMatrix -> Int -> Int -> Maybe Int
+ AtCoder.Extra.WaveletMatrix: selectKthIn :: WaveletMatrix -> Int -> Int -> Int -> Int -> Maybe Int
+ AtCoder.Extra.WaveletMatrix.BitVector: BitVector :: !Vector Bit -> !Vector Int -> BitVector
+ AtCoder.Extra.WaveletMatrix.BitVector: [bitsBv] :: BitVector -> !Vector Bit
+ AtCoder.Extra.WaveletMatrix.BitVector: [csumBv] :: BitVector -> !Vector Int
+ AtCoder.Extra.WaveletMatrix.BitVector: build :: Vector Bit -> BitVector
+ AtCoder.Extra.WaveletMatrix.BitVector: csumInPlace :: PrimMonad m => MVector (PrimState m) Int -> Vector Bit -> m Int
+ AtCoder.Extra.WaveletMatrix.BitVector: data BitVector
+ AtCoder.Extra.WaveletMatrix.BitVector: instance GHC.Classes.Eq AtCoder.Extra.WaveletMatrix.BitVector.BitVector
+ AtCoder.Extra.WaveletMatrix.BitVector: instance GHC.Show.Show AtCoder.Extra.WaveletMatrix.BitVector.BitVector
+ AtCoder.Extra.WaveletMatrix.BitVector: rank0 :: BitVector -> Int -> Int
+ AtCoder.Extra.WaveletMatrix.BitVector: rank1 :: BitVector -> Int -> Int
+ AtCoder.Extra.WaveletMatrix.BitVector: select0 :: BitVector -> Int -> Maybe Int
+ AtCoder.Extra.WaveletMatrix.BitVector: select1 :: BitVector -> Int -> Maybe Int
+ AtCoder.Extra.WaveletMatrix.BitVector: selectKthIn0 :: BitVector -> Int -> Int -> Int -> Maybe Int
+ AtCoder.Extra.WaveletMatrix.BitVector: selectKthIn1 :: BitVector -> Int -> Int -> Int -> Maybe Int
+ AtCoder.Extra.WaveletMatrix.BitVector: wordSize :: Int
+ AtCoder.Extra.WaveletMatrix.Raw: RawWaveletMatrix :: {-# UNPACK #-} !Int -> {-# UNPACK #-} !Int -> !Vector BitVector -> !Vector Int -> RawWaveletMatrix
+ AtCoder.Extra.WaveletMatrix.Raw: [bitsRwm] :: RawWaveletMatrix -> !Vector BitVector
+ AtCoder.Extra.WaveletMatrix.Raw: [heightRwm] :: RawWaveletMatrix -> {-# UNPACK #-} !Int
+ AtCoder.Extra.WaveletMatrix.Raw: [lengthRwm] :: RawWaveletMatrix -> {-# UNPACK #-} !Int
+ AtCoder.Extra.WaveletMatrix.Raw: [nZerosRwm] :: RawWaveletMatrix -> !Vector Int
+ AtCoder.Extra.WaveletMatrix.Raw: access :: RawWaveletMatrix -> Int -> Maybe Int
+ AtCoder.Extra.WaveletMatrix.Raw: assocsIn :: RawWaveletMatrix -> Int -> Int -> [(Int, Int)]
+ AtCoder.Extra.WaveletMatrix.Raw: assocsWith :: RawWaveletMatrix -> Int -> Int -> (Int -> Int) -> [(Int, Int)]
+ AtCoder.Extra.WaveletMatrix.Raw: build :: HasCallStack => Int -> Vector Int -> RawWaveletMatrix
+ AtCoder.Extra.WaveletMatrix.Raw: data RawWaveletMatrix
+ AtCoder.Extra.WaveletMatrix.Raw: descAssocsIn :: RawWaveletMatrix -> Int -> Int -> [(Int, Int)]
+ AtCoder.Extra.WaveletMatrix.Raw: descAssocsInWith :: RawWaveletMatrix -> Int -> Int -> (Int -> Int) -> [(Int, Int)]
+ AtCoder.Extra.WaveletMatrix.Raw: ikthLargestIn :: RawWaveletMatrix -> Int -> Int -> Int -> Maybe (Int, Int)
+ AtCoder.Extra.WaveletMatrix.Raw: ikthSmallestIn :: RawWaveletMatrix -> Int -> Int -> Int -> Maybe (Int, Int)
+ AtCoder.Extra.WaveletMatrix.Raw: instance GHC.Classes.Eq AtCoder.Extra.WaveletMatrix.Raw.RawWaveletMatrix
+ AtCoder.Extra.WaveletMatrix.Raw: instance GHC.Show.Show AtCoder.Extra.WaveletMatrix.Raw.RawWaveletMatrix
+ AtCoder.Extra.WaveletMatrix.Raw: kthLargestIn :: RawWaveletMatrix -> Int -> Int -> Int -> Maybe Int
+ AtCoder.Extra.WaveletMatrix.Raw: kthSmallestIn :: RawWaveletMatrix -> Int -> Int -> Int -> Maybe Int
+ AtCoder.Extra.WaveletMatrix.Raw: lookupGE :: RawWaveletMatrix -> Int -> Int -> Int -> Maybe Int
+ AtCoder.Extra.WaveletMatrix.Raw: lookupGT :: RawWaveletMatrix -> Int -> Int -> Int -> Maybe Int
+ AtCoder.Extra.WaveletMatrix.Raw: lookupLE :: RawWaveletMatrix -> Int -> Int -> Int -> Maybe Int
+ AtCoder.Extra.WaveletMatrix.Raw: lookupLT :: RawWaveletMatrix -> Int -> Int -> Int -> Maybe Int
+ AtCoder.Extra.WaveletMatrix.Raw: rank :: RawWaveletMatrix -> Int -> Int -> Int -> Int
+ AtCoder.Extra.WaveletMatrix.Raw: rankBetween :: RawWaveletMatrix -> Int -> Int -> Int -> Int -> Int
+ AtCoder.Extra.WaveletMatrix.Raw: rankLT :: RawWaveletMatrix -> Int -> Int -> Int -> Int
+ AtCoder.Extra.WaveletMatrix.Raw: select :: RawWaveletMatrix -> Int -> Maybe Int
+ AtCoder.Extra.WaveletMatrix.Raw: selectIn :: RawWaveletMatrix -> Int -> Int -> Int -> Maybe Int
+ AtCoder.Extra.WaveletMatrix.Raw: selectKth :: RawWaveletMatrix -> Int -> Int -> Maybe Int
+ AtCoder.Extra.WaveletMatrix.Raw: selectKthIn :: RawWaveletMatrix -> Int -> Int -> Int -> Int -> Maybe Int
+ AtCoder.Extra.WaveletMatrix.Raw: unsafeIKthLargestIn :: RawWaveletMatrix -> Int -> Int -> Int -> (Int, Int)
+ AtCoder.Extra.WaveletMatrix.Raw: unsafeIKthSmallestIn :: RawWaveletMatrix -> Int -> Int -> Int -> (Int, Int)
+ AtCoder.Extra.WaveletMatrix.Raw: unsafeKthLargestIn :: RawWaveletMatrix -> Int -> Int -> Int -> Int
+ AtCoder.Extra.WaveletMatrix.Raw: unsafeKthSmallestIn :: RawWaveletMatrix -> Int -> Int -> Int -> Int
+ AtCoder.Extra.WaveletMatrix2d: WaveletMatrix2d :: !RawWaveletMatrix -> !Vector (Int, Int) -> !Vector Int -> !Vector (SegTree s a) -> !a -> a -> WaveletMatrix2d s a
+ AtCoder.Extra.WaveletMatrix2d: [invWm2d] :: WaveletMatrix2d s a -> !a -> a
+ AtCoder.Extra.WaveletMatrix2d: [rawWmWm2d] :: WaveletMatrix2d s a -> !RawWaveletMatrix
+ AtCoder.Extra.WaveletMatrix2d: [segTreesWm2d] :: WaveletMatrix2d s a -> !Vector (SegTree s a)
+ AtCoder.Extra.WaveletMatrix2d: [xyDictWm2d] :: WaveletMatrix2d s a -> !Vector (Int, Int)
+ AtCoder.Extra.WaveletMatrix2d: [yDictWm2d] :: WaveletMatrix2d s a -> !Vector Int
+ AtCoder.Extra.WaveletMatrix2d: allProd :: (HasCallStack, Unbox a, Monoid a, PrimMonad m) => WaveletMatrix2d (PrimState m) a -> m a
+ AtCoder.Extra.WaveletMatrix2d: build :: (PrimMonad m, Monoid a, Unbox a) => (a -> a) -> Vector (Int, Int, a) -> m (WaveletMatrix2d (PrimState m) a)
+ AtCoder.Extra.WaveletMatrix2d: data WaveletMatrix2d s a
+ AtCoder.Extra.WaveletMatrix2d: modify :: (HasCallStack, Monoid a, Unbox a, PrimMonad m) => WaveletMatrix2d (PrimState m) a -> (a -> a) -> (Int, Int) -> m ()
+ AtCoder.Extra.WaveletMatrix2d: new :: (PrimMonad m, Monoid a, Unbox a) => (a -> a) -> Vector (Int, Int) -> m (WaveletMatrix2d (PrimState m) a)
+ AtCoder.Extra.WaveletMatrix2d: prod :: (HasCallStack, Unbox a, Monoid a, PrimMonad m) => WaveletMatrix2d (PrimState m) a -> Int -> Int -> Int -> Int -> m a
+ AtCoder.Extra.WaveletMatrix2d: prodMaybe :: (Unbox a, Monoid a, PrimMonad m) => WaveletMatrix2d (PrimState m) a -> Int -> Int -> Int -> Int -> m (Maybe a)
+ AtCoder.Extra.WaveletMatrix2d: read :: (HasCallStack, Unbox a, Monoid a, PrimMonad m) => WaveletMatrix2d (PrimState m) a -> (Int, Int) -> m a
+ AtCoder.Extra.WaveletMatrix2d: write :: (HasCallStack, Monoid a, Unbox a, PrimMonad m) => WaveletMatrix2d (PrimState m) a -> (Int, Int) -> a -> m ()
+ AtCoder.Internal.Csr: Csr :: {-# UNPACK #-} !Int -> {-# UNPACK #-} !Int -> !Vector Int -> !Vector Int -> !Vector w -> Csr w
+ AtCoder.Internal.Csr: [adjCsr] :: Csr w -> !Vector Int
+ AtCoder.Internal.Csr: [mCsr] :: Csr w -> {-# UNPACK #-} !Int
+ AtCoder.Internal.Csr: [nCsr] :: Csr w -> {-# UNPACK #-} !Int
+ AtCoder.Internal.Csr: [startCsr] :: Csr w -> !Vector Int
+ AtCoder.Internal.Csr: [wCsr] :: Csr w -> !Vector w
+ AtCoder.Internal.Csr: build1 :: HasCallStack => Int -> Vector (Int, Int) -> Csr Int
+ AtCoder.LazySegTree: exchange :: (HasCallStack, PrimMonad m, SegAct f a, Unbox f, Monoid a, Unbox a) => LazySegTree (PrimState m) f a -> Int -> a -> m a
+ AtCoder.SegTree: exchange :: (HasCallStack, PrimMonad m, Monoid a, Unbox a) => SegTree (PrimState m) a -> Int -> a -> m a
- AtCoder.Extra.Monoid.RangeAdd: act :: Num a => RangeAdd a -> a -> a
+ AtCoder.Extra.Monoid.RangeAdd: act :: Semigroup a => RangeAdd a -> a -> a
- AtCoder.Internal.Csr: adj :: (HasCallStack, Unbox w) => Csr w -> Int -> Vector Int
+ AtCoder.Internal.Csr: adj :: HasCallStack => Csr w -> Int -> Vector Int
- AtCoder.Internal.Csr: eAdj :: (HasCallStack, Unbox w) => Csr w -> Int -> Vector (Int, Int)
+ AtCoder.Internal.Csr: eAdj :: HasCallStack => Csr w -> Int -> Vector (Int, Int)

Files

CHANGELOG.md view
@@ -1,8 +1,16 @@ # Revision history for acl-hs +## 1.1.0.0 -- Jan 2025++- Removed `RangeSetId` and `RangeAddId` from `AtCoder.Extra.Monoid`.+- Implemented `SegAct` for `RangeSet`, `RangeAdd` and `Max`, `Min`.+- Added `segActWithLength` to `SegAct`.+- Added `build1` to `AtCoder.Internal.Csr`.+- Added a bunch of extra modules.+ ## 1.0.0.0 -- Dec 2024 -* First version.-* ACL-compatible modules.-* Extra module of `Math` (binary exponentiation) and `Monoid` (`SegAct` instances).+- First version.+- Added ACL-compatible modules.+- Added Extra module of `Math` (binary exponentiation) and `Monoid` (`SegAct` instances). 
README.md view
@@ -5,8 +5,8 @@ ## Notes  - The library is mainly for AtCoder and only GHC 9.8.4 is guaranteed to be supported.-- The `Internal` module is unstable and does not follow PVP.-- The `Extra` module provides with extra contents not in the original `ac-library`. Note that they're less tested.+- Functions primarily use half-open interval \([l, r)\).+- The extra module contains additional utilities beyond the original C++ library.  ## Usage 
ac-library-hs.cabal view
@@ -4,12 +4,15 @@ -- PVP summary:  +-+------- breaking API changes --               | | +----- non-breaking API additions --               | | | +--- code changes with no API change-version:         1.0.0.1+version:         1.1.0.0 synopsis:        Data structures and algorithms description:   Haskell port of [ac-library](https://github.com/atcoder/ac-library), a library for competitive   programming on [AtCoder](https://atcoder.jp/). +  - Functions primarily use half-open interval \([l, r)\).+  - The extra module contains additional utilities beyond the original C++ library.+ category:        Algorithms, Data Structures license:         CC0-1.0 license-file:    LICENSE@@ -70,13 +73,31 @@   exposed-modules:     AtCoder.Convolution     AtCoder.Dsu+    AtCoder.Extra.Bisect+    AtCoder.Extra.HashMap+    AtCoder.Extra.IntervalMap+    AtCoder.Extra.IntMap+    AtCoder.Extra.IntSet+    AtCoder.Extra.Graph+    AtCoder.Extra.Tree+    AtCoder.Extra.Tree.Hld+    AtCoder.Extra.Tree.TreeMonoid     AtCoder.Extra.Math     AtCoder.Extra.Monoid     AtCoder.Extra.Monoid.Affine1+    AtCoder.Extra.Monoid.Mat2x2     AtCoder.Extra.Monoid.RangeAdd-    AtCoder.Extra.Monoid.RangeAddId     AtCoder.Extra.Monoid.RangeSet-    AtCoder.Extra.Monoid.RangeSetId+    AtCoder.Extra.Monoid.RollingHash+    AtCoder.Extra.Monoid.V2+    AtCoder.Extra.MultiSet+    AtCoder.Extra.Semigroup.Matrix+    AtCoder.Extra.Semigroup.Permutation+    AtCoder.Extra.Pdsu+    AtCoder.Extra.WaveletMatrix+    AtCoder.Extra.WaveletMatrix.BitVector+    AtCoder.Extra.WaveletMatrix.Raw+    AtCoder.Extra.WaveletMatrix2d     AtCoder.FenwickTree     AtCoder.Internal.Assert     AtCoder.Internal.Barrett@@ -118,8 +139,21 @@   other-modules:     Tests.Convolution     Tests.Dsu+    Tests.Extra.Bisect+    Tests.Extra.Graph+    Tests.Extra.HashMap+    Tests.Extra.IntervalMap+    Tests.Extra.IntMap+    Tests.Extra.IntSet     Tests.Extra.Math     Tests.Extra.Monoid+    Tests.Extra.MultiSet+    Tests.Extra.Semigroup.Matrix+    Tests.Extra.Semigroup.Permutation+    Tests.Extra.WaveletMatrix+    Tests.Extra.WaveletMatrix.BitVector+    Tests.Extra.WaveletMatrix.Raw+    Tests.Extra.WaveletMatrix2d     Tests.FenwickTree     Tests.Internal.Bit     Tests.Internal.Buffer@@ -146,6 +180,7 @@   main-is:        Main.hs   build-depends:     , ac-library-hs+    , containers     , hspec     , mtl     , QuickCheck@@ -157,6 +192,7 @@     , tasty-quickcheck     , tasty-rerun     , transformers+    , unordered-containers  benchmark ac-library-hs-benchmark   import:         warnings@@ -167,8 +203,11 @@   hs-source-dirs: benchmarks   other-modules:     Bench.AddMod+    Bench.Matrix+    Bench.ModInt     Bench.PowMod     BenchLib.AddMod+    BenchLib.Matrix     BenchLib.ModInt.ModIntNats     BenchLib.ModInt.Modulus     BenchLib.MulMod.Barrett64@@ -180,8 +219,10 @@     , ac-library-hs     , base     , criterion+    , mtl     , random     , tagged+    , transformers  test-suite benchlib-test   import:         warnings@@ -204,6 +245,7 @@     , hspec     , mtl     , QuickCheck+    -- , quickcheck-instances     , random     , tagged     , tasty
benchmarks/Bench/AddMod.hs view
@@ -6,7 +6,7 @@ import BenchLib.AddMod import Criterion import Data.Vector.Unboxed qualified as VU-import Data.Word (Word32, Word64)+import Data.Word (Word32) import System.Random  n :: Int
+ benchmarks/Bench/Matrix.hs view
@@ -0,0 +1,87 @@+module Bench.Matrix (benches) where++import AtCoder.ModInt qualified as M+import AtCoder.Extra.Semigroup.Matrix qualified as ACMAT+import AtCoder.Extra.Math qualified as ACEM+import BenchLib.Matrix qualified as Mat+import Control.Monad.State.Class (MonadState, state)+import Control.Monad.Trans.State.Strict (evalState, runState)+import Criterion+import Data.Semigroup (Semigroup (..))+import Data.Vector qualified as V+import Data.Vector.Unboxed qualified as VU+import System.Random++testSize :: Int+testSize = 10000++m :: Int+m = 998244353++randomMatrix :: (MonadState StdGen m) => m (Mat.Matrix Int, Int)+randomMatrix = do+  h <- state $ uniformR (1, 16)+  nextMatrix h++nextMatrix :: (MonadState StdGen m) => Int -> m (Mat.Matrix Int, Int)+nextMatrix h = do+  w <- state $ uniformR (1, 16)+  vec <- VU.replicateM (h * w) $ state (uniformR (0, m - 1))+  pure (Mat.new h w vec, w)++randomSquareACLMatrix :: (MonadState StdGen m) => Int -> m (ACMAT.Matrix Int)+randomSquareACLMatrix n = do+  vec <- VU.replicateM (n * n) $ state (uniformR (0, m - 1))+  pure $ ACMAT.new n n vec++benches :: Benchmark+benches =+  bgroup+    "Matrix"+    [ bench "mul1" $ whnf (V.foldl1' Mat.mul1) randomMatrixInput,+      bench "mul2" $ whnf (V.foldl1' Mat.mul2) randomMatrixInput,+      bench "mul3_1" $ whnf (V.foldl1' Mat.mul3_1) randomMatrixInput,+      bench "mul3_2" $ whnf (V.foldl1' Mat.mul3_2) randomMatrixInput,+      bench "mul3_3" $ whnf (V.foldl1' Mat.mul3_3) randomMatrixInput,+      bench "mulMod1" $ whnf (V.foldl1' (Mat.mulMod1 m)) randomMatrixInput,+      bench "mulMod2" $ whnf (V.foldl1' (Mat.mulMod2 m)) randomMatrixInput,+      bench "mulMod3" $ whnf (V.foldl1' (Mat.mulMod3 m)) randomMatrixInput,+      bench "mulMod4" $ whnf (V.foldl1' (Mat.mulMod4 m)) randomMatrixInput,+      bench "mulMod5" $ whnf (V.foldl1' (Mat.mulMod5 m)) randomMatrixInput,+      bench "mulMint1" $ whnf (V.foldl1' Mat.mulMint1) randomMintMatrixInput,+      bench "mulMint2" $ whnf (V.foldl1' Mat.mulMint2) randomMintMatrixInput,+      bench "mulMint3" $ whnf (V.foldl1' Mat.mulMint3) randomMintMatrixInput,+      -- mul (ACL)+      bench "mul_ACL" $ whnf (V.foldl1' ACMAT.mul) randomMatrixInputACL,+      bench "mulMod_ACL" $ whnf (V.foldl1' (ACMAT.mulMod m)) randomMatrixInputACL,+      -- pow mod (ACL only)+      bench "powMod_ACL" $ whnf (VU.foldl' (flip (ACMAT.powMod m)) squareMat) randomVec,+      bench "powMintACL_stimes" $ whnf (VU.foldl' (flip stimes) squareMatMint) randomVec,+      bench "powMintACL_stimes'" $ whnf (VU.foldl' (flip ACEM.stimes') squareMatMint) randomVec,+      bench "powMintACL_powMint" $ whnf (VU.foldl' (flip ACMAT.powMint) squareMatMint) randomVec+    ]+  where+    -- Bench matrix+    randomMatrixInput :: V.Vector (Mat.Matrix Int)+    !randomMatrixInput = evalState (V.unfoldrExactNM testSize nextMatrix (Mat.wM mat0)) gen0+      where+        ((!mat0, !_), !gen0) = runState randomMatrix $ mkStdGen 123456789++    randomMintMatrixInput :: V.Vector (Mat.Matrix (M.ModInt 998244353))+    !randomMintMatrixInput = V.map (Mat.map M.new) randomMatrixInput++    -- ACL matrix+    randomMatrixInputACL :: V.Vector (ACMAT.Matrix Int)+    !randomMatrixInputACL = V.map (\mat -> ACMAT.new (Mat.hM mat) (Mat.wM mat) (Mat.vecM mat)) randomMatrixInput++    squareMat :: ACMAT.Matrix Int+    !squareMat = evalState (randomSquareACLMatrix 17) $ mkStdGen 123456789++    squareMatMint ::ACMAT.Matrix (M.ModInt 998244353)+    !squareMatMint = ACMAT.map M.new squareMat++    -- non-zero random vector+    randomVec :: VU.Vector Int+    !randomVec =+      VU.map ((+ 1) . fromIntegral) $+        VU.unfoldrExactN 100 (genWord64R (m - 2)) (mkStdGen 123456789)
+ benchmarks/Bench/ModInt.hs view
@@ -0,0 +1,23 @@+module Bench.ModInt (benches) where++import AtCoder.ModInt qualified as M+import BenchLib.PowMod qualified as PowMod+import BenchLib.ModInt.ModIntNats qualified as MN+import Criterion+import Data.Vector.Unboxed qualified as VU+import System.Random++benches :: Benchmark+benches =+  bgroup+    "modInt"+    [++    ]+  where+    n = 10000+    randomVec :: VU.Vector Int+    randomVec =+      VU.map fromIntegral $+        VU.unfoldrExactN n (genWord64R (998244383 - 2)) (mkStdGen 123456789)+
+ benchmarks/BenchLib/Matrix.hs view
@@ -0,0 +1,394 @@+{-# LANGUAGE MagicHash #-}+{-# LANGUAGE RecordWildCards #-}++module BenchLib.Matrix+  ( Matrix (..),+    new,+    map,+    mulToCol,+    mulToColModInt,+    mul1,+    mul2,+    mul3_1,+    mul3_2,+    mul3_3,+    mulMod1,+    mulMod2,+    mulMod3,+    mulMod4,+    mulMod5,+    mulMint1,+    mulMint2,+    mulMint3,+  )+where++import AtCoder.Internal.Assert qualified as ACIA+import AtCoder.Internal.Barrett qualified as BT+import AtCoder.ModInt qualified as M+import Data.Vector qualified as V+import Data.Vector.Generic qualified as VG+import Data.Vector.Unboxed qualified as VU+import Data.Word (Word64)+import GHC.Exts (Proxy#, proxy#)+import GHC.Stack (HasCallStack)+import GHC.TypeNats (KnownNat, natVal, natVal')+import Prelude hiding (map)++data Matrix a = Matrix+  { hM :: {-# UNPACK #-} !Int,+    wM :: {-# UNPACK #-} !Int,+    vecM :: !(VU.Vector a)+  }+  deriving (Show, Eq)++type Col a = VU.Vector a++{-# INLINE new #-}+new :: (HasCallStack, VU.Unbox a) => Int -> Int -> VU.Vector a -> Matrix a+new h w vec+  | VU.length vec /= h * w = error "AtCoder.Extra.Matrix: size mismatch"+  | otherwise = Matrix h w vec++{-# INLINE map #-}+map :: (VU.Unbox a, VU.Unbox b) => (a -> b) -> Matrix a -> Matrix b+map f Matrix {..} = Matrix hM wM $ VU.map f vecM++{-# INLINE mulToCol #-}+mulToCol :: (Num a, VU.Unbox a) => Matrix a -> Col a -> Col a+mulToCol Matrix {..} !col = VU.convert $ V.map (VU.sum . VU.zipWith (*) col) rows+  where+    !n = VU.length col+    !_ = ACIA.runtimeAssert (n == wM) "AtCoder.Extra.Matrix.mulToCol: size mismatch"+    rows = V.unfoldrExactN hM (VU.splitAt wM) vecM++{-# INLINE mulToColModInt #-}+mulToColModInt :: forall m. (KnownNat m) => Matrix (M.ModInt m) -> Col (M.ModInt m) -> Col (M.ModInt m)+mulToColModInt Matrix {..} !col = VU.convert $ V.map (VU.foldl' (+) (M.unsafeNew 0) . VU.zipWith mulMod col) rows+  where+    !_ = ACIA.runtimeAssert (VU.length col == wM) "AtCoder.Extra.Matrix.mulToColModInt: size mismatch"+    !bt = BT.new32 $ fromIntegral (natVal' (proxy# @m))+    rows = V.unfoldrExactN hM (VU.splitAt wM) vecM+    mulMod (M.ModInt x) (M.ModInt y) = M.unsafeNew . fromIntegral $ BT.mulMod bt (fromIntegral x) (fromIntegral y)++{-# INLINE mul1 #-}+mul1 :: (Num e, VU.Unbox e) => Matrix e -> Matrix e -> Matrix e+mul1 !a !b =+  Matrix h w' $+    VU.unfoldrExactN+      (h * w')+      ( \(!row, !col) ->+          let !x = f row col+           in if col + 1 >= w'+                then (x, (row + 1, 0))+                else (x, (row, col + 1))+      )+      (0, 0)+  where+    f row col = VU.sum $ VU.zipWith (*) (rows1 VG.! row) (cols2 VG.! col)+    h = hM a+    w = wM a+    vecA = vecM a+    h' = hM b+    w' = wM b+    vecB = vecM b+    !_ = ACIA.runtimeAssert (w == h') "AtCoder.Extra.Matrix.mul: matrix size mismatch"+    rows1 = V.unfoldrExactN h (VU.splitAt w) vecA+    cols2 = V.generate w' $ \col -> VU.unfoldrExactN h' (\i -> (VG.unsafeIndex vecB i, i + w')) col++{-# INLINE mul2 #-}+mul2 :: (Num e, VU.Unbox e) => Matrix e -> Matrix e -> Matrix e+mul2 !a !b =+  Matrix h w' $+    VU.unfoldrExactN+      (h * w')+      ( \(!row, !col) ->+          let !x = f row col+           in if col + 1 >= w'+                then (x, (row + 1, 0))+                else (x, (row, col + 1))+      )+      (0, 0)+  where+    f row col = VU.sum $ VU.imap (\iRow x -> x * VG.unsafeIndex vecB (col + iRow * w')) (rows1 VG.! row)+    h = hM a+    w = wM a+    vecA = vecM a+    h' = hM b+    w' = wM b+    vecB = vecM b+    !_ = ACIA.runtimeAssert (w == h') "AtCoder.Extra.Matrix.mul: matrix size mismatch"+    rows1 = V.unfoldrExactN h (VU.splitAt w) vecA++{-# INLINE mul3_1 #-}+mul3_1 :: (Num e, VU.Unbox e) => Matrix e -> Matrix e -> Matrix e+mul3_1 !a !b =+  Matrix h w' $+    VU.unfoldrExactN+      (h * w')+      ( \(!row, !col) ->+          let !x = f row col+           in if col + 1 >= w'+                then (x, (row + 1, 0))+                else (x, (row, col + 1))+      )+      (0, 0)+  where+    f row col = VU.sum $ VU.imap (\iRow x -> x * VG.unsafeIndex vecB (col + iRow * w')) (VU.unsafeSlice (w * row) w vecA)+    h = hM a+    w = wM a+    h' = hM b+    vecA = vecM a+    w' = wM b+    vecB = vecM b+    !_ = ACIA.runtimeAssert (w == h') "AtCoder.Extra.Matrix.mul: matrix size mismatch"++{-# INLINE mul3_2 #-}+mul3_2 :: (Num e, VU.Unbox e) => Matrix e -> Matrix e -> Matrix e+mul3_2 !a !b =+  Matrix h w' $+    VU.unfoldrExactN+      (h * w')+      ( \(!row, !col) ->+          let !y = VU.sum $ VU.imap (\iRow x -> x * VG.unsafeIndex vecB (col + iRow * w')) (VU.unsafeSlice (w * row) w vecA)+           in if col + 1 >= w'+                then (y, (row + 1, 0))+                else (y, (row, col + 1))+      )+      (0, 0)+  where+    h = hM a+    w = wM a+    h' = hM b+    vecA = vecM a+    w' = wM b+    vecB = vecM b+    !_ = ACIA.runtimeAssert (w == h') "AtCoder.Extra.Matrix.mul: matrix size mismatch"++{-# INLINE mul3_3 #-}+mul3_3 :: (Num e, VU.Unbox e) => Matrix e -> Matrix e -> Matrix e+mul3_3 !a !b = Matrix h w' $ VU.generate (h * w') $ \i ->+  let (!row, !col) = i `quotRem` w'+   in VU.sum $ VU.imap (\iRow x -> x * VG.unsafeIndex vecB (col + iRow * w')) (VU.unsafeSlice (w * row) w vecA)+  where+    h = hM a+    w = wM a+    h' = hM b+    vecA = vecM a+    w' = wM b+    vecB = vecM b+    !_ = ACIA.runtimeAssert (w == h') "AtCoder.Extra.Matrix.mul: matrix size mismatch"++{-# INLINE mulMod1 #-}+mulMod1 :: Int -> Matrix Int -> Matrix Int -> Matrix Int+mulMod1 !m !a !b =+  Matrix h w' $+    VU.unfoldrExactN+      (h * w')+      ( \(!row, !col) ->+          let !x = f row col+           in if col + 1 >= w'+                then (x, (row + 1, 0))+                else (x, (row, col + 1))+      )+      (0, 0)+  where+    f row col = VU.foldl1' addMod $ VU.imap (\iRow x -> mulMod x (VG.unsafeIndex vecB (col + (iRow * w')))) (VU.unsafeSlice (w * row) w vecA)+    addMod x y = (x + y) `mod` m+    mulMod x y = (x * y) `mod` m+    h = hM a+    w = wM a+    h' = hM b+    vecA = vecM a+    w' = wM b+    vecB = vecM b+    !_ = ACIA.runtimeAssert (w == h') "AtCoder.Extra.Matrix.mul: matrix size mismatch"++{-# INLINE mulMod2 #-}+mulMod2 :: Int -> Matrix Int -> Matrix Int -> Matrix Int+mulMod2 !m !a !b =+  Matrix h w' $+    VU.unfoldrExactN+      (h * w')+      ( \(!row, !col) ->+          let !x = f row col+           in if col + 1 >= w'+                then (x, (row + 1, 0))+                else (x, (row, col + 1))+      )+      (0, 0)+  where+    f row col = VU.foldl1' addMod $ VU.imap (\iRow x -> mulMod x (VG.unsafeIndex vecB (col + (iRow * w')))) (VU.unsafeSlice (w * row) w vecA)+    -- very slow+    addMod x y+      | x + y >= m = x + y - m+      | otherwise = x + y+    mulMod x y = (x * y) `mod` m+    h = hM a+    w = wM a+    h' = hM b+    vecA = vecM a+    w' = wM b+    vecB = vecM b+    !_ = ACIA.runtimeAssert (w == h') "AtCoder.Extra.Matrix.mul: matrix size mismatch"++{-# INLINE mulMod3 #-}+mulMod3 :: Int -> Matrix Int -> Matrix Int -> Matrix Int+mulMod3 !m !a !b =+  Matrix h w' $+    VU.unfoldrExactN+      (h * w')+      ( \(!row, !col) ->+          let !x = f row col+           in if col + 1 >= w'+                then (x, (row + 1, 0))+                else (x, (row, col + 1))+      )+      (0, 0)+  where+    !bt = BT.new32 $ fromIntegral m+    f row col = VU.foldl1' addMod $ VU.imap (\iRow x -> mulMod x (VG.unsafeIndex vecB (col + (iRow * w')))) (VU.unsafeSlice (w * row) w vecA)+    addMod x y = (x + y) `mod` m+    mulMod x y = fromIntegral $ BT.mulMod bt (fromIntegral x) (fromIntegral y)+    h = hM a+    w = wM a+    h' = hM b+    vecA = vecM a+    w' = wM b+    vecB = vecM b+    !_ = ACIA.runtimeAssert (w == h') "AtCoder.Extra.Matrix.mul: matrix size mismatch"++{-# INLINE mulMod4 #-}+mulMod4 :: Int -> Matrix Int -> Matrix Int -> Matrix Int+mulMod4 !m !a !b =+  Matrix h w' $+    VU.unfoldrExactN+      (h * w')+      ( \(!row, !col) ->+          let !x = f row col+           in if col + 1 >= w'+                then (x, (row + 1, 0))+                else (x, (row, col + 1))+      )+      (0, 0)+  where+    !bt = BT.new32 $ fromIntegral m+    f row col = VU.foldl1' addMod $ VU.imap (\iRow x -> mulMod x (VG.unsafeIndex vecB (col + (iRow * w')))) (VU.unsafeSlice (w * row) w vecA)+    addMod x y = (x + y) `rem` m+    mulMod x y = fromIntegral $ BT.mulMod bt (fromIntegral x) (fromIntegral y)+    h = hM a+    w = wM a+    h' = hM b+    vecA = vecM a+    w' = wM b+    vecB = vecM b+    !_ = ACIA.runtimeAssert (w == h') "AtCoder.Extra.Matrix.mul: matrix size mismatch"++{-# INLINE mulMod5 #-}+mulMod5 :: Int -> Matrix Int -> Matrix Int -> Matrix Int+mulMod5 !m !a !b =+  Matrix h w' $+    VU.unfoldrExactN+      (h * w')+      ( \(!row, !col) ->+          let !x = f row col+           in if col + 1 >= w'+                then (x, (row + 1, 0))+                else (x, (row, col + 1))+      )+      (0, 0)+  where+    !bt = BT.new32 $ fromIntegral m+    f row col = VU.foldl1' addMod $ VU.imap (\iRow x -> mulMod x (VG.unsafeIndex vecB (col + (iRow * w')))) (VU.unsafeSlice (w * row) w vecA)+    addMod x y+      | x + y >= m = x + y - m+      | otherwise = x + y+    mulMod x y = fromIntegral $ BT.mulMod bt (fromIntegral x) (fromIntegral y)+    h = hM a+    w = wM a+    h' = hM b+    vecA = vecM a+    w' = wM b+    vecB = vecM b+    !_ = ACIA.runtimeAssert (w == h') "AtCoder.Extra.Matrix.mul: matrix size mismatch"++{-# INLINE mulMint1 #-}+mulMint1 :: forall a. (KnownNat a) => Matrix (M.ModInt a) -> Matrix (M.ModInt a) -> Matrix (M.ModInt a)+mulMint1 !a !b =+  Matrix h w' $+    VU.unfoldrExactN+      (h * w')+      ( \(!row, !col) ->+          let !x = f row col+           in if col + 1 >= w'+                then (x, (row + 1, 0))+                else (x, (row, col + 1))+      )+      (0, 0)+  where+    f :: Int -> Int -> M.ModInt a+    f row col = VU.sum $ VU.imap (\iRow x -> mulMod x (VG.unsafeIndex vecB (col + (iRow * w')))) (VU.unsafeSlice (w * row) w vecA)+    mulMod :: M.ModInt a -> M.ModInt a -> M.ModInt a+    mulMod = (*)+    h = hM a+    w = wM a+    h' = hM b+    vecA = vecM a+    w' = wM b+    vecB = vecM b+    !_ = ACIA.runtimeAssert (w == h') "AtCoder.Extra.Matrix.mul: matrix size mismatch"++{-# INLINE mulMint2 #-}+mulMint2 :: forall a. (KnownNat a) => Matrix (M.ModInt a) -> Matrix (M.ModInt a) -> Matrix (M.ModInt a)+mulMint2 !a !b =+  Matrix h w' $+    VU.unfoldrExactN+      (h * w')+      ( \(!row, !col) ->+          let !x = f row col+           in if col + 1 >= w'+                then (x, (row + 1, 0))+                else (x, (row, col + 1))+      )+      (0, 0)+  where+    !bt = BT.new32 $ fromIntegral (natVal' (proxy# @a))+    f :: Int -> Int -> M.ModInt a+    f row col = VU.sum $ VU.imap (\iRow x -> mulMod x (VG.unsafeIndex vecB (col + (iRow * w')))) (VU.unsafeSlice (w * row) w vecA)+    mulMod :: M.ModInt a -> M.ModInt a -> M.ModInt a+    mulMod (M.ModInt x) (M.ModInt y) = M.unsafeNew . fromIntegral $ BT.mulMod bt (fromIntegral x) (fromIntegral y)+    h = hM a+    w = wM a+    h' = hM b+    vecA = vecM a+    w' = wM b+    vecB = vecM b+    !_ = ACIA.runtimeAssert (w == h') "AtCoder.Extra.Matrix.mul: matrix size mismatch"++-- REMARK: This is very unsafe in that it can overflow (mod^2 * n)+{-# INLINE mulMint3 #-}+mulMint3 :: forall a. (KnownNat a) => Matrix (M.ModInt a) -> Matrix (M.ModInt a) -> Matrix (M.ModInt a)+mulMint3 !a !b =+  Matrix h w' $+    VU.unfoldrExactN+      (h * w')+      ( \(!row, !col) ->+          let !x = f row col+           in if col + 1 >= w'+                then (x, (row + 1, 0))+                else (x, (row, col + 1))+      )+      (0, 0)+  where+    !bt = BT.new32 $ fromIntegral (natVal' (proxy# @a))+    f :: Int -> Int -> M.ModInt a+    f row col = M.new64 . VU.sum $ VU.imap (\iRow x -> mulMod x (VG.unsafeIndex vecB (col + (iRow * w')))) (VU.unsafeSlice (w * row) w vecA)+    mulMod :: M.ModInt a -> M.ModInt a -> Word64+    mulMod (M.ModInt x) (M.ModInt y) = BT.mulMod bt (fromIntegral x) (fromIntegral y)+    h = hM a+    w = wM a+    h' = hM b+    vecA = vecM a+    w' = wM b+    vecB = vecM b+    !_ = ACIA.runtimeAssert (w == h') "AtCoder.Extra.Matrix.mul: matrix size mismatch"
benchmarks/BenchLib/MulMod/BarrettWideWord.hs view
@@ -24,10 +24,11 @@     imBarrett :: {-# UNPACK #-} !Word64   } --- | Creates barret reduction for modulus \(m\).+-- | Creates a `Barrett` for modulus value \(m\) of type `Word32`. new32 :: Word32 -> Barrett new32 m = Barrett m $ maxBound @Word64 `div` (fromIntegral m :: Word64) + 1 +-- | Creates a `Barrett` for modulus value \(m\) of type `Word64`. new64 :: Word64 -> Barrett new64 m = Barrett (fromIntegral m) $ maxBound @Word64 `div` m + 1 
benchmarks/BenchLib/MulMod/Montgomery.hs view
@@ -17,8 +17,8 @@ import Data.Bits (bit, (!>>.)) import Data.Word (Word32, Word64) --- | Fast modular multiplication by Montgomery multiplication. The modulus value has to be odd--- to be fast.+-- | Fast modular multiplication by Montgomery multiplication. The modulus value must be odd for+-- the speed. data Montgomery = Montgomery   { mMontgomery :: {-# UNPACK #-} !Word64,     -- | R2 == (2^64) % MOD;@@ -27,7 +27,7 @@     negInvMontgomery :: {-# UNPACK #-} !Word32   } --- | Creates `Montgomery` for modulus @m@.+-- | Creates a `Montgomery` for modulus @m@. new :: Word64 -> Montgomery new m =   let !negInv = inner 0 0 1 0
benchmarks/Main.hs view
@@ -3,7 +3,9 @@ module Main where  import Bench.AddMod qualified+import Bench.Matrix qualified import Bench.MulMod qualified+import Bench.ModInt qualified import Bench.PowMod qualified import Criterion.Main @@ -13,9 +15,10 @@ main :: IO () main =   defaultMain-  -- TODO: generate graph by benchmark group?-    [ -- Bench.MulMod.benches32,-      -- Bench.MulMod.benches64,-      -- Bench.AddMod.benches-      Bench.PowMod.benches+    -- TODO: generate criterion graph by benchmark group?+    [ Bench.MulMod.benches,+      Bench.ModInt.benches,+      Bench.AddMod.benches,+      Bench.PowMod.benches,+      Bench.Matrix.benches     ]
src/AtCoder/Convolution.hs view
@@ -14,7 +14,7 @@ -- >>> import Data.Proxy (Proxy) -- >>> import Data.Vector.Unboxed qualified as VU ----- It's handy to define specific items for interested modulus values:+-- Define specific modulus items: -- -- >>> type Mint = M.ModInt998244353 -- >>> let modInt :: Int -> Mint; modInt = M.new@@ -26,7 +26,7 @@ -- >>> C.convolution a b -- [5,16,34,60,61,52,32] ----- You can also target any @'Integral' a@ (with some runtime overhead for conversion to modint):+-- You can also target any @'Integral' a@ with `convolutionRaw`: -- -- >>> let a = VU.fromList @Int [1, 2, 3, 4] -- >>> let b = VU.fromList @Int [5, 6, 7, 8]
src/AtCoder/Dsu.hs view
@@ -1,17 +1,17 @@ {-# LANGUAGE RecordWildCards #-} --- | Disjoint set union, also known as Union-Find tree. It processes the following queries in+-- | A disjoint set union, also known as a Union-Find tree. It processes the following queries in -- amortized \(O(\alpha(n))\) time. ----- - Edge addition--- - Deciding whether given two vertices are in the same connected component+-- - Edge addition (`merge`)+-- - Deciding whether given two vertices are in the same connected component (`same`) ----- Each connected component internally has a representative vertex. When two connected components--- are merged by edge addition, one of the two representatives of these connected components--- becomes the representative of the new connected component.+-- Each connected component internally has a representative vertex (`leader`). When two connected+-- components are merged by edge addition (`merge`), one of the two representatives of these+-- connected components becomes the representative (`leader`) of the new connected component. -- -- ==== __Example__--- Create DSU:+-- Create a `Dsu` with four vertices: -- -- >>> import AtCoder.Dsu qualified as Dsu -- >>> dsu <- Dsu.new 4   -- 0 1 2 3@@ -49,15 +49,15 @@     -- * Constructor     new, -    -- * Merge+    -- * Merging     merge,     merge_,      -- * Leader     leader,-    same,      -- * Component information+    same,     size,     groups,   )@@ -73,13 +73,13 @@ import Data.Vector.Unboxed.Mutable qualified as VUM import GHC.Stack (HasCallStack) --- | Disjoint set union. Akso known as Union-Find tree.+-- | A disjoint set union. Akso known as Union-Find tree. -- -- @since 1.0.0.0 data Dsu s = Dsu-  { -- | 1.0.0 The number of nodes.+  { -- | The number of nodes.     ---    -- @since+    -- @since 1.0.0.0     nDsu :: {-# UNPACK #-} !Int,     -- | For root (leader) nodes it stores their size as a negative number. For child nodes it     -- stores their parent node index.@@ -103,8 +103,8 @@       pure Dsu {..}   | otherwise = error $ "new: given negative size (`" ++ show nDsu ++ "`)" --- | Adds an edge @(a, b)@. the vertices @a@ and @b@ were in the same connected component, it--- returns the representative of this connected component. Otherwise, it returns the+-- | Adds an edge \((a, b)\). If the vertices \(a\) and \(b\) are in the same connected component, it+-- returns the representative (`leader`) of this connected component. Otherwise, it returns the -- representative of the new connected component. -- -- ==== Constraints@@ -134,7 +134,7 @@       VGM.modify parentOrSizeDsu (+ sizeY) x       pure x --- | `merge` with return value discarded.+-- | `merge` with the return value discarded. -- -- ==== Constraints -- - \(0 \leq a < n\)@@ -207,7 +207,7 @@   sizeLa <- VGM.read parentOrSizeDsu la   pure (-sizeLa) --- | Divides the graph into connected components and returns the list of them.+-- | Divides the graph into connected components and returns the vector of them. -- -- More precisely, it returns a vector of the "vector of the vertices in a connected component". -- Both of the orders of the connected components and the vertices are undefined.
+ src/AtCoder/Extra/Bisect.hs view
@@ -0,0 +1,297 @@+-- | Bisection methods and binary search functions. They partition a half-open interval \([l, r)\)+-- into two and return either the left or the right point of the boundary.+--+-- @+-- Y Y Y Y Y N N N N N      Y: user predicate holds+-- --------* *---------> X  N: user predicate does not hold+--         L R              L, R: left, right point of the boundary+-- @+--+-- ==== __Example__+-- Perform index compression:+--+-- >>> import AtCoder.Extra.Bisect+-- >>> import Data.Maybe (fromJust)+-- >>> import Data.Vector.Algorithms.Intro qualified as VAI+-- >>> import Data.Vector.Unboxed qualified as VU+-- >>> let xs = VU.fromList ([0, 20, 10, 40, 30] :: [Int])+-- >>> let dict = VU.uniq $ VU.modify VAI.sort xs+-- >>> VU.map (fromJust . lowerBound dict) xs+-- [0,2,1,4,3]+--+-- @since 1.1.0.0+module AtCoder.Extra.Bisect+  ( -- * C++-like binary search+    lowerBound,+    lowerBoundIn,+    upperBound,+    upperBoundIn,++    -- * Generic bisection method+    bisectL,+    bisectLM,+    bisectR,+    bisectRM,+  )+where++import AtCoder.Internal.Assert qualified as ACIA+import Data.Functor ((<&>))+import Data.Functor.Identity+import Data.Vector.Generic qualified as VG+import GHC.Stack (HasCallStack)++-- | \(O(\log n)\) Bisection method implementation. Works on a half-open interfal \([l, r)\) .+--+-- @since 1.1.0.0+{-# INLINE bisectLImpl #-}+bisectLImpl :: (HasCallStack, Monad m) => (Int -> m Bool) -> Int -> Int -> m Int+bisectLImpl p l0 = inner (l0 - 1)+  where+    inner l r+      | l + 1 == r = pure l+      | otherwise =+          p mid >>= \case+            True -> inner mid r+            False -> inner l mid+      where+        mid = (l + r) `div` 2++-- | \(O(\log n)\) Bisection method implementation. Works on a half-open interfal \([l, r)\) .+--+-- @since 1.1.0.0+{-# INLINE bisectRImpl #-}+bisectRImpl :: (HasCallStack, Monad m) => (Int -> m Bool) -> Int -> Int -> m Int+bisectRImpl p l = ((+ 1) <$>) . bisectLImpl p l++-- | \(O(\log n)\) Returns the index of the first element \(x\) in the vector such that+-- \(x \ge x_0\), or `Nothing` if no such element exists.+--+-- @+-- Y Y Y Y Y N N N N N      Y: (< x0)+-- --------- *---------> X  N: (>= x0)+--           R              R: returning point+-- @+--+-- ==== __Example__+-- >>> import Data.Vector.Unboxed qualified as VU+-- >>> let xs = VU.fromList [1, 1, 2, 2, 4, 4]+-- >>> lowerBound xs 1+-- Just 0+--+-- >>> lowerBound xs 2+-- Just 2+--+-- >>> lowerBound xs 3+-- Just 4+--+-- >>> lowerBound xs 4+-- Just 4+--+-- Out of range values:+--+-- >>> lowerBound xs 0+-- Just 0+--+-- >>> lowerBound xs 5+-- Nothing+--+-- @since 1.1.0.0+{-# INLINE lowerBound #-}+lowerBound :: (HasCallStack, VG.Vector v a, Ord a) => v a -> a -> Maybe Int+lowerBound vec = lowerBoundIn 0 (VG.length vec) vec++-- | \(O(\log n)\) Computes the `lowerBound` for a slice of a vector within the interval \([l, r)\).+--+-- - The user predicate evaluates indices in \([l, r)\).+-- - The interval \([l, r)\) is silently clamped to ensure it remains within the bounds \([0, n)\).+--+-- ==== __Example__+-- >>> import Data.Vector.Unboxed qualified as VU+-- >>> let xs = VU.fromList [10, 10, 20, 20, 40, 40]+-- >>> --                            *---*---*+-- >>> lowerBoundIn 2 5 xs 10+-- Just 2+--+-- >>> lowerBoundIn 2 5 xs 20+-- Just 2+--+-- >>> lowerBoundIn 2 5 xs 30+-- Just 4+--+-- >>> lowerBoundIn 2 5 xs 40+-- Just 4+--+-- >>> lowerBoundIn 2 5 xs 50+-- Nothing+--+-- @since 1.1.0.0+{-# INLINE lowerBoundIn #-}+lowerBoundIn :: (VG.Vector v a, Ord a) => Int -> Int -> v a -> a -> Maybe Int+lowerBoundIn l_ r_ vec target+  | ACIA.testInterval l r (VG.length vec) = bisectR l r $ \i -> VG.unsafeIndex vec i < target+  | otherwise = Nothing+  where+    -- clamp+    l = max 0 l_+    r = min (VG.length vec) r_++-- | \(O(\log n)\) Returns the index of the first element \(x\) in the vector such that+-- \(x \gt x_0\), or `Nothing` if no such element exists.+--+-- @+-- Y Y Y Y Y N N N N N      Y: (<= x0)+-- --------- *---------> X  N: (> x0)+--           R              R: returning point+-- @+--+-- ==== __Example__+-- >>> import Data.Vector.Unboxed qualified as VU+-- >>> let xs = VU.fromList [10, 10, 20, 20, 40, 40]+-- >>> upperBound xs 10+-- Just 2+--+-- >>> upperBound xs 20+-- Just 4+--+-- >>> upperBound xs 30+-- Just 4+--+-- >>> upperBound xs 40+-- Nothing+--+-- Out of range values:+--+-- >>> upperBound xs 0+-- Just 0+--+-- >>> upperBound xs 50+-- Nothing+--+-- @since 1.1.0.0+{-# INLINE upperBound #-}+upperBound :: (HasCallStack, VG.Vector v a, Ord a) => v a -> a -> Maybe Int+upperBound vec = upperBoundIn 0 (VG.length vec) vec++-- | \(O(\log n)\) Computes the `upperBound` for a slice of a vector within the interval \([l, r)\).+--+-- - The user predicate evaluates indices in \([l, r)\).+-- - The interval \([l, r)\) is silently clamped to ensure it remains within the bounds \([0, n)\).+--+-- ==== __Example__+-- >>> import Data.Vector.Unboxed qualified as VU+-- >>> let xs = VU.fromList [10, 10, 20, 20, 40, 40]+-- >>> --                            *---*---*+-- >>> upperBoundIn 2 5 xs 0+-- Just 2+--+-- >>> upperBoundIn 2 5 xs 10+-- Just 2+--+-- >>> upperBoundIn 2 5 xs 20+-- Just 4+--+-- >>> upperBoundIn 2 5 xs 30+-- Just 4+--+-- >>> upperBoundIn 2 5 xs 40+-- Nothing+--+-- >>> upperBoundIn 2 5 xs 50+-- Nothing+--+-- @since 1.1.0.0+{-# INLINE upperBoundIn #-}+upperBoundIn :: (VG.Vector v a, Ord a) => Int -> Int -> v a -> a -> Maybe Int+upperBoundIn l_ r_ vec target+  | ACIA.testInterval l r (VG.length vec) = bisectR l r $ \i -> VG.unsafeIndex vec i <= target+  | otherwise = Nothing+  where+    -- clamp+    l = max 0 l_+    r = min (VG.length vec) r_++-- | \(O(\log n)\) Applies the bisection method on a half-open interval \([l, r)\) and returns the+-- left boundary point, or `Nothing` if no such point exists.+--+-- @+-- Y Y Y Y Y N N N N N      Y: user predicate holds+-- --------* ----------> X  N: user predicate does not hold+--         L                L: the left boundary point returned+-- @+--+-- ==== __Example__+-- >>> import Data.Vector.Unboxed qualified as VU+-- >>> let xs = VU.fromList [10, 10, 20, 20, 30, 30]+-- >>> let n = VU.length xs+-- >>> bisectL 0 n ((<= 20) . (xs VU.!))+-- Just 3+--+-- >>> bisectL 0 n ((<= 0) . (xs VU.!))+-- Nothing+--+-- >>> bisectL 0 n ((<= 100) . (xs VU.!))+-- Just 5+--+-- >>> bisectL 0 3 ((<= 20) . (xs VU.!))+-- Just 2+--+-- @since 1.1.0.0+{-# INLINE bisectL #-}+bisectL :: (HasCallStack) => Int -> Int -> (Int -> Bool) -> Maybe Int+bisectL l r p = runIdentity $ bisectLM l r (pure . p)++-- | \(O(\log n)\) Monadic variant of `bisectL`.+--+-- @since 1.1.0.0+{-# INLINE bisectLM #-}+bisectLM :: (HasCallStack, Monad m) => Int -> Int -> (Int -> m Bool) -> m (Maybe Int)+bisectLM l r p+  | l >= r = pure Nothing+  | otherwise =+      bisectLImpl p l r <&> \case+        i | i == (l - 1) -> Nothing+        i -> Just i++-- | \(O(\log n)\) Applies the bisection method on a half-open interval \([l, r)\) and returns the+-- right boundary point, or `Nothing` if no such point exists.+--+--+-- @+-- Y Y Y Y Y N N N N N      Y: user predicate holds+-- --------- *---------> X  N: user predicate does not hold+--           R              R: the right boundary point returned+-- @+--+-- ==== __Example__+-- >>> import Data.Vector.Unboxed qualified as VU+-- >>> let xs = VU.fromList [10, 10, 20, 20, 30, 30]+-- >>> let n = VU.length xs+-- >>> bisectR 0 n ((<= 20) . (xs VU.!))+-- Just 4+--+-- >>> bisectR 0 n ((<= 0) . (xs VU.!))+-- Just 0+--+-- >>> bisectR 0 n ((<= 100) . (xs VU.!))+-- Nothing+--+-- >>> bisectR 0 4 ((<= 20) . (xs VU.!))+-- Nothing+--+-- @since 1.1.0.0+{-# INLINE bisectR #-}+bisectR :: (HasCallStack) => Int -> Int -> (Int -> Bool) -> Maybe Int+bisectR l r p = runIdentity $ bisectRM l r (pure . p)++-- | \(O(\log n)\) Monadic variant of `bisectR`.+--+-- @since 1.1.0.0+{-# INLINE bisectRM #-}+bisectRM :: (HasCallStack, Monad m) => Int -> Int -> (Int -> m Bool) -> m (Maybe Int)+bisectRM l r p+  | l >= r = pure Nothing+  | otherwise =+      bisectRImpl p l r <&> \case+        i | i == r -> Nothing+        i -> Just i
+ src/AtCoder/Extra/Graph.hs view
@@ -0,0 +1,147 @@+-- | Re-export of the @Csr@ module and generic graph search functions.+--+-- @since 1.1.0.0+module AtCoder.Extra.Graph+  ( -- * Re-export of CSR++    -- | The `Csr.Csr` data type and all the functions such as `build` or `adj` are re-exported.+    module Csr,++    -- * CSR helpers+    swapDupe,+    swapDupe',+    scc,++    -- * Graph search+    topSort,+  )+where++import AtCoder.Extra.IntSet qualified as IS+import AtCoder.Internal.Buffer qualified as B+import AtCoder.Internal.Csr as Csr+import AtCoder.Internal.Scc qualified as ACISCC+import Control.Monad (when)+import Control.Monad.ST (runST)+import Data.Foldable (for_)+import Data.Vector qualified as V+import Data.Vector.Generic.Mutable qualified as VGM+import Data.Vector.Unboxed qualified as VU+import Data.Vector.Unboxed.Mutable qualified as VUM++-- | \(O(n)\) Converts non-directed edges into directional edges. This is a convenient function for+-- making an input to `build`.+--+-- ==== __Example__+-- `swapDupe` duplicates each edge reversing the direction:+--+-- >>> import AtCoder.Extra.Graph qualified as Gr+-- >>> import Data.Vector.Unboxed qualified as VU+-- >>> Gr.swapDupe $ VU.fromList [(0, 1, ()), (1, 2, ())]+-- [(0,1,()),(1,0,()),(1,2,()),(2,1,())]+--+-- Create a non-directed graph:+--+-- >>> let gr = Gr.build 3 . Gr.swapDupe $ VU.fromList [(0, 1, ()), (1, 2, ())]+-- >>> gr `Gr.adj` 0+-- [1]+--+-- >>> gr `Gr.adj` 1+-- [0,2]+--+-- >>> gr `Gr.adj` 2+-- [1]+--+-- @since 1.1.0.0+{-# INLINE swapDupe #-}+swapDupe :: (VU.Unbox (Int, Int, w)) => VU.Vector (Int, Int, w) -> VU.Vector (Int, Int, w)+swapDupe = VU.concatMap (\(!u, !v, !w) -> VU.fromListN 2 [(u, v, w), (v, u, w)])++-- | \(O(n)\) Converts non-directed edges into directional edges. This is a convenient function for+-- making an input to `build'`.+--+-- ==== __Example__+-- `swapDupe'` duplicates each edge reversing the direction:+--+-- >>> import AtCoder.Extra.Graph qualified as Gr+-- >>> import Data.Vector.Unboxed qualified as VU+-- >>> Gr.swapDupe' $ VU.fromList [(0, 1), (1, 2)]+-- [(0,1),(1,0),(1,2),(2,1)]+--+-- Create a non-directed graph:+--+-- >>> let gr = Gr.build' 3 . Gr.swapDupe' $ VU.fromList [(0, 1), (1, 2)]+-- >>> gr `Gr.adj` 0+-- [1]+--+-- >>> gr `Gr.adj` 1+-- [0,2]+--+-- >>> gr `Gr.adj` 2+-- [1]+--+-- @since 1.1.0.0+{-# INLINE swapDupe' #-}+swapDupe' :: (VU.Unbox (Int, Int)) => VU.Vector (Int, Int) -> VU.Vector (Int, Int)+swapDupe' = VU.concatMap (\(!u, !v) -> VU.fromListN 2 [(u, v), (v, u)])++-- | \(O(n + m)\) Returns the strongly connected components.+--+-- ==== __Example__+-- >>> import AtCoder.Extra.Graph qualified as Gr+-- >>> import Data.Vector.Unboxed qualified as VU+-- >>> -- 0 == 1 -> 2    3+-- >>> let gr = Gr.build' 4 $ VU.fromList [(0, 1), (1, 0), (1, 2)]+-- >>> Gr.scc gr+-- [[3],[0,1],[2]]+--+-- @since 1.1.0.0+{-# INLINE scc #-}+scc :: Csr w -> V.Vector (VU.Vector Int)+scc = ACISCC.sccCsr++-- | \(O(n \log n + m)\) Returns the lexicographically smallest topological ordering of the given+-- graph.+--+-- ==== Constraints+-- - The graph must be a DAG.+--+-- ==== __Example__+-- >>> import AtCoder.Extra.Graph qualified as Gr+-- >>> import Data.Vector.Unboxed qualified as VU+-- >>> let n = 5+-- >>> let gr = Gr.build' n $ VU.fromList [(1, 2), (4, 0), (0, 3)]+-- >>> Gr.topSort n (gr `Gr.adj`)+-- [1,2,4,0,3]+--+-- @since 1.1.0.0+{-# INLINE topSort #-}+topSort :: Int -> (Int -> VU.Vector Int) -> VU.Vector Int+topSort n gr = runST $ do+  inDeg <- VUM.replicate n (0 :: Int)+  for_ [0 .. n - 1] $ \u -> do+    VU.forM_ (gr u) $ \v -> do+      VGM.modify inDeg (+ 1) v++  -- start from the vertices with zero in-degrees:+  que <- IS.new n+  inDeg' <- VU.unsafeFreeze inDeg+  VU.iforM_ inDeg' $ \v d -> do+    when (d == 0) $ do+      IS.insert que v++  buf <- B.new n+  let run = do+        IS.deleteMin que >>= \case+          Nothing -> pure ()+          Just u -> do+            B.pushBack buf u+            VU.forM_ (gr u) $ \v -> do+              nv <- subtract 1 <$> VGM.read inDeg v+              VGM.write inDeg v nv+              when (nv == 0) $ do+                IS.insert que v+            run++  run+  B.unsafeFreeze buf
+ src/AtCoder/Extra/HashMap.hs view
@@ -0,0 +1,346 @@+{-# LANGUAGE RecordWildCards #-}++-- original implementaion:+-- <https://github.com/maspypy/library/blob/main/ds/hashmap.hpp>++-- | A dense, fast `Int` hash map with a fixed-sized `capacity` of \(n\). Most operations are+-- performed in \(O(1)\) time, but in average.+--+-- NOTE: The entries (key - value pairs) cannot be invalidated due to the internal implementation+-- (called /open addressing/).+--+-- ==== __Example__+-- Create a `HashMap` with `capacity` \(10\):+--+-- >>> import AtCoder.Extra.HashMap qualified as HM+-- >>> hm <- HM.new @_ @Int 10+--+-- `insert`, `lookup` and other functions are available in \(O(1)\) averaged time:+--+-- >>> HM.insert hm 0 100+-- >>> HM.insert hm 10 101+-- >>> HM.size hm+-- 2+--+-- >>> HM.lookup hm 0+-- Just 100+--+-- >>> HM.lookup hm 10+-- Just 101+--+-- @since 1.1.0.0+module AtCoder.Extra.HashMap+  ( -- * HashMap+    HashMap,++    -- * Constructors+    new,+    build,++    -- * Metadata+    capacity,+    size,++    -- * Lookups+    lookup,+    member,+    notMember,++    -- * Modifications++    -- ** Insertions+    insert,+    insertWith,+    exchange,++    -- ** Updates+    modify,+    modifyM,++    -- ** Reset+    clear,++    -- * Conversions++    -- ** Safe conversions+    keys,+    elems,+    assocs,++    -- ** Unsafe conversions+    unsafeKeys,+    unsafeElems,+    unsafeAssocs,+  )+where++import AtCoder.Internal.Assert qualified as ACIA+import Control.Monad (void, when)+import Control.Monad.Primitive (PrimMonad, PrimState)+import Data.Bit (Bit (..))+import Data.Bits (Bits (xor, (.&.)), (.>>.))+import Data.Vector.Generic qualified as VG+import Data.Vector.Generic.Mutable qualified as VGM+import Data.Vector.Unboxed qualified as VU+import Data.Vector.Unboxed.Mutable qualified as VUM+import Data.Word (Word64)+import GHC.Stack (HasCallStack)+import Prelude hiding (lookup)++-- | A dense, fast `Int` hash map with a fixed-sized capacity of \(n\).+--+-- @since 1.1.0.0+data HashMap s a = HashMap+  { -- | Maximum number of elements.+    maxCapHM :: {-# UNPACK #-} !Int,+    -- | The number of elements that can be added.+    restCapHM :: !(VUM.MVector s Int),+    -- | Bit mask for powerset iteration on indexing.+    maskHM :: {-# UNPACK #-} !Int,+    -- | Original key to the hash index.+    keyHM :: !(VUM.MVector s Int),+    -- | Values to the hash index.+    valHM :: !(VUM.MVector s a),+    -- | Whether the slot is used or not.+    usedHM :: !(VUM.MVector s Bit)+  }++{-# INLINE decrementRestCapacity #-}+decrementRestCapacity :: (HasCallStack, PrimMonad m) => VUM.MVector (PrimState m) Int -> String -> m ()+decrementRestCapacity restCap funcName = do+  rest <- VGM.unsafeRead restCap 0+  let !_ = ACIA.runtimeAssert (rest > 0) $ "AtCoder.Extra.HashMap." ++ funcName ++ ": out of capacity"+  VGM.unsafeWrite restCap 0 (rest - 1)+  pure ()++-- | \(O(n)\) Creates a `HashMap` of capacity \(n\).+--+-- @since 1.1.0.0+{-# INLINE new #-}+new :: (PrimMonad m, VU.Unbox a) => Int -> m (HashMap (PrimState m) a)+new n = do+  let !k0 = 1+  let !k = until (>= 2 * n) (* 2) k0+  let !maxCapHM = k `div` 2+  restCapHM <- VUM.replicate 1 maxCapHM+  let !maskHM = k - 1+  keyHM <- VUM.unsafeNew k+  valHM <- VUM.unsafeNew k+  usedHM <- VUM.replicate k $ Bit False+  pure HashMap {..}++-- | \(O(n)\) Creates a `HashMap` of capacity \(n\) with initial entries.+--+-- @since 1.1.0.0+{-# INLINE build #-}+build :: (PrimMonad m, VU.Unbox a) => Int -> VU.Vector (Int, a) -> m (HashMap (PrimState m) a)+build n xs = do+  hm <- new n+  VU.forM_ xs $ \(!i, !x) -> do+    insert hm i x+  pure hm++-- | \(O(1)\) Returns the maximum number of elements the hash map can store.+--+-- @since 1.1.0.0+{-# INLINE capacity #-}+capacity :: HashMap s a -> Int+capacity = maxCapHM++-- | \(O(1)\) Returns the number of elements in the hash map.+--+-- @since 1.1.0.0+{-# INLINE size #-}+size :: (PrimMonad m) => HashMap (PrimState m) a -> m Int+size HashMap {..} = do+  !rest <- VUM.unsafeRead restCapHM 0+  pure $ maxCapHM - rest++-- | \(O(1)\) (Internal) Hash value calculation.+--+-- @since 1.1.0.0+{-# INLINE hash #-}+hash :: HashMap a s -> Int -> Int+hash hm x = fromIntegral $ (x3 `xor` (x3 .>>. 31)) .&. fromIntegral (maskHM hm)+  where+    fixedRandom, x1, x2, x3 :: Word64+    fixedRandom = 321896566547+    x1 = fromIntegral x + fixedRandom+    x2 = (x1 `xor` (x1 .>>. 30)) * 0xbf58476d1ce4e5b9+    x3 = (x2 `xor` (x2 .>>. 27)) * 0x94d049bb133111eb++-- | \(O(1)\) (Internal) Hashed slot search.+--+-- @since 1.1.0.0+{-# INLINE index #-}+index :: (PrimMonad m) => HashMap (PrimState m) a -> Int -> m Int+index hm@HashMap {..} k = inner (hash hm k)+  where+    inner !h = do+      Bit b <- VGM.read usedHM h+      -- already there?+      k' <- VGM.read keyHM h+      if b && k' /= k+        then inner $ (h + 1) .&. maskHM+        else pure h++-- | \(O(1)\) Return the value to which the specified key is mapped, or `Nothing` if this map+-- contains no mapping for the key.+--+-- @since 1.1.0.0+{-# INLINE lookup #-}+lookup :: (HasCallStack, VU.Unbox a, PrimMonad m) => HashMap (PrimState m) a -> Int -> m (Maybe a)+lookup hm@HashMap {..} k = do+  i <- index hm k+  Bit b <- VGM.read usedHM i+  if b+    then Just <$> VGM.read valHM i+    else pure Nothing++-- | \(O(1)\) Checks whether the hash map contains the element.+--+-- @since 1.1.0.0+{-# INLINE member #-}+member :: (HasCallStack, PrimMonad m) => HashMap (PrimState m) a -> Int -> m Bool+member hm@HashMap {..} k = do+  i <- index hm k+  Bit b <- VGM.read usedHM i+  -- TODO: is this key check necessary+  k' <- VGM.read keyHM i+  pure $ b && k' == k++-- | \(O(1)\) Checks whether the hash map does not contain the element.+--+-- @since 1.1.0.0+{-# INLINE notMember #-}+notMember :: (HasCallStack, PrimMonad m) => HashMap (PrimState m) a -> Int -> m Bool+notMember hm k = not <$> member hm k++-- | \(O(1)\) Inserts a \((k, v)\) pair.+--+-- @since 1.1.0.0+{-# INLINE insert #-}+insert :: (HasCallStack, PrimMonad m, VU.Unbox a) => HashMap (PrimState m) a -> Int -> a -> m ()+insert hm k v = void $ exchange hm k v++-- | \(O(1)\) Inserts a \((k, v)\) pair. If the key exists, the function will insert the pair+-- \((k, f(v_{\mathrm{new}}, v_{\mathrm{old}}))\).+--+-- @since 1.1.0.0+{-# INLINE insertWith #-}+insertWith :: (HasCallStack, PrimMonad m, VU.Unbox a) => HashMap (PrimState m) a -> (a -> a -> a) -> Int -> a -> m ()+insertWith hm@HashMap {..} f k v = do+  i <- index hm k+  Bit b <- VGM.exchange usedHM i $ Bit True+  if b+    then do+      -- modify the existing entry+      VGM.modify valHM (f v) i+    else do+      -- insert the new \((k, v)\) pair+      decrementRestCapacity restCapHM "insertWith"+      VGM.write keyHM i k+      VGM.write valHM i v++-- | \(O(1)\) Inserts a \((k, v)\) pair and returns the old value, or `Nothing` if no such entry+-- exists.+--+-- @since 1.1.0.0+{-# INLINE exchange #-}+exchange :: (HasCallStack, PrimMonad m, VU.Unbox a) => HashMap (PrimState m) a -> Int -> a -> m (Maybe a)+exchange hm@HashMap {..} k v = do+  i <- index hm k+  Bit b <- VGM.exchange usedHM i $ Bit True+  if b+    then do+      -- overwrite the existing entry+      Just <$> VGM.exchange valHM i v+    else do+      -- insert the new (key, value) pair+      decrementRestCapacity restCapHM "exchange"+      VGM.write keyHM i k+      VGM.write valHM i v+      pure Nothing++-- | \(O(1)\) Modifies the element at the given key. Does nothing if no such entry exists.+--+-- @since 1.1.0.0+{-# INLINE modify #-}+modify :: (HasCallStack, PrimMonad m, VU.Unbox a) => HashMap (PrimState m) a -> (a -> a) -> Int -> m ()+modify hm@HashMap {..} f k = do+  i <- index hm k+  Bit b <- VGM.read usedHM i+  when b $ do+    VGM.modify valHM f i++-- | \(O(1)\) Modifies the element at the given key. Does nothing if no such entry exists.+--+-- @since 1.1.0.0+{-# INLINE modifyM #-}+modifyM :: (HasCallStack, PrimMonad m, VU.Unbox a) => HashMap (PrimState m) a -> (a -> m a) -> Int -> m ()+modifyM hm@HashMap {..} f k = do+  i <- index hm k+  Bit b <- VGM.read usedHM i+  when b $ do+    VGM.modifyM valHM f i++-- | \(O(n)\) Clears all the elements.+--+-- @since 1.1.0.0+{-# INLINE clear #-}+clear :: (PrimMonad m) => HashMap (PrimState m) a -> m ()+clear HashMap {..} = do+  VGM.set usedHM $ Bit False+  VUM.unsafeWrite restCapHM 0 maxCapHM++-- | \(O(n)\) Enumerates the keys in the hash map.+--+-- @since 1.1.0.0+{-# INLINE keys #-}+keys :: (PrimMonad m, VU.Unbox a) => HashMap (PrimState m) a -> m (VU.Vector Int)+keys hm = VU.force <$> unsafeKeys hm++-- | \(O(n)\) Enumerates the elements (values) in the hash map.+--+-- @since 1.1.0.0+{-# INLINE elems #-}+elems :: (PrimMonad m, VU.Unbox a) => HashMap (PrimState m) a -> m (VU.Vector a)+elems hm = VU.force <$> unsafeElems hm++-- | \(O(n)\) Enumerates the key-value pairs in the hash map.+--+-- @since 1.1.0.0+{-# INLINE assocs #-}+assocs :: (PrimMonad m, VU.Unbox a) => HashMap (PrimState m) a -> m (VU.Vector (Int, a))+assocs hm = VU.force <$> unsafeAssocs hm++-- | \(O(n)\) Enumerates the keys in the hash map.+--+-- @since 1.1.0.0+{-# INLINE unsafeKeys #-}+unsafeKeys :: (PrimMonad m, VU.Unbox a) => HashMap (PrimState m) a -> m (VU.Vector Int)+unsafeKeys HashMap {..} = do+  used <- VU.unsafeFreeze usedHM+  keys_ <- VU.unsafeFreeze keyHM+  pure $ VU.ifilter (const . unBit . (used VG.!)) keys_++-- | \(O(n)\) Enumerates the elements (values) in the hash map.+--+-- @since 1.1.0.0+{-# INLINE unsafeElems #-}+unsafeElems :: (PrimMonad m, VU.Unbox a) => HashMap (PrimState m) a -> m (VU.Vector a)+unsafeElems HashMap {..} = do+  used <- VU.unsafeFreeze usedHM+  vals <- VU.unsafeFreeze valHM+  pure $ VU.ifilter (const . unBit . (used VG.!)) vals++-- | \(O(n)\) Enumerates the key-value pairs in the hash map.+--+-- @since 1.1.0.0+{-# INLINE unsafeAssocs #-}+unsafeAssocs :: (PrimMonad m, VU.Unbox a) => HashMap (PrimState m) a -> m (VU.Vector (Int, a))+unsafeAssocs HashMap {..} = do+  used <- VU.unsafeFreeze usedHM+  keys_ <- VU.unsafeFreeze keyHM+  vals <- VU.unsafeFreeze valHM+  pure $ VU.ifilter (const . unBit . (used VG.!)) $ VU.zip keys_ vals
+ src/AtCoder/Extra/IntMap.hs view
@@ -0,0 +1,338 @@+{-# LANGUAGE RecordWildCards #-}++-- | A dense, fast `Int` map implemented as a 64-ary tree that covers an interval \([0, n)\).+--+-- ==== __Example__+-- Create an `IntMap` with capacity \(10\):+--+-- >>> import AtCoder.Extra.IntMap qualified as IM+-- >>> im <- IM.new @_ @Int 10+--+-- `insert`, `delete`, `lookup` and other functions are available:+--+-- >>> IM.insert im 0 100+-- >>> IM.insert im 9 101+-- >>> IM.delete im 0+-- True+--+-- >>> IM.size im+-- 1+--+-- >>> IM.lookup im 9+-- Just 101+--+-- >>> IM.lookup im 1+-- Nothing+--+-- >>> IM.lookupGT im 5+-- Just (9,101)+--+-- @since 1.1.0.0+module AtCoder.Extra.IntMap+  ( -- * IntMap+    IntMap,++    -- * Constructors+    new,+    build,++    -- * Metadata+    capacity,+    size,+    null,++    -- * Lookups+    lookup,+    member,+    notMember,++    -- ** Compartive lookups+    lookupGE,+    lookupGT,+    lookupLE,+    lookupLT,++    -- ** Max/Min lookups+    lookupMin,+    lookupMax,++    -- * Modifications++    -- ** Insertions+    insert,+    insertWith,++    -- ** Updates+    modify,+    modifyM,++    -- ** Deletions+    delete,+    delete_,+    deleteMin,+    deleteMax,++    -- * Conversions+    keys,+    elems,+    assocs,+  )+where++import AtCoder.Extra.IntSet qualified as IS+import Control.Monad (when)+import Control.Monad.Primitive (PrimMonad, PrimState)+import Data.Maybe (fromJust)+import Data.Vector.Generic.Mutable qualified as VGM+import Data.Vector.Unboxed qualified as VU+import Data.Vector.Unboxed.Mutable qualified as VUM+import GHC.Stack (HasCallStack)+import Prelude hiding (lookup, null)++-- | A dense, fast `Int` map implemented as a 64-ary tree that covers an interval \([0, n)\).+--+-- @since 1.1.0.0+data IntMap s a = IntMap+  { setIM :: !(IS.IntSet s),+    valIM :: !(VUM.MVector s a)+  }++-- | \(O(n)\) Creates an `IntMap` for an interval \([0, n)\).+--+-- @since 1.1.0.0+{-# INLINE new #-}+new :: (PrimMonad m, VU.Unbox a) => Int -> m (IntMap (PrimState m) a)+new cap = do+  setIM <- IS.new cap+  valIM <- VUM.unsafeNew cap+  pure IntMap {..}++-- | \(O(n + m \log n)\) Creates an `IntMap` for an interval \([0, n)\) with initial values.+--+-- @since 1.1.0.0+{-# INLINE build #-}+build :: (PrimMonad m, VU.Unbox a) => Int -> VU.Vector (Int, a) -> m (IntMap (PrimState m) a)+build cap xs = do+  im <- new cap+  VU.forM_ xs $ \(!k, !v) -> do+    insert im k v+  pure im++-- | \(O(1)\) Returns the capacity \(n\), where the interval \([0, n)\) is covered by the map.+--+-- @since 1.1.0.0+{-# INLINE capacity #-}+capacity :: IntMap s a -> Int+capacity = IS.capacity . setIM++-- | \(O(1)\) Returns the number of elements in the map.+--+-- @since 1.1.0.0+{-# INLINE size #-}+size :: (PrimMonad m) => IntMap (PrimState m) a -> m Int+size = IS.size . setIM++-- | \(O(1)\) Returns whether the map is empty.+--+-- @since 1.1.0.0+{-# INLINE null #-}+null :: (PrimMonad m) => IntMap (PrimState m) a -> m Bool+null = IS.null . setIM++-- | \(O(\log n)\) Looks up the value for a key.+--+-- @since 1.1.0.0+{-# INLINE lookup #-}+lookup :: (PrimMonad m, VU.Unbox a) => IntMap (PrimState m) a -> Int -> m (Maybe a)+lookup im@IntMap {..} k = do+  member im k >>= \case+    True -> Just <$> VGM.read valIM k+    False -> pure Nothing++-- | \(O(\log n)\) Tests whether a key \(k\) is in the map.+--+-- @since 1.1.0.0+{-# INLINE member #-}+member :: (PrimMonad m) => IntMap (PrimState m) a -> Int -> m Bool+member = IS.member . setIM++-- | \(O(\log n)\) Tests whether a key \(k\) is not in the map.+--+-- @since 1.1.0.0+{-# INLINE notMember #-}+notMember :: (PrimMonad m) => IntMap (PrimState m) a -> Int -> m Bool+notMember = IS.notMember . setIM++-- | \(O(\log n)\) Looks up the \((k, v)\) pair with the smallest key \(k\) such that \(k \ge k_0\).+--+-- @since 1.1.0.0+{-# INLINE lookupGE #-}+lookupGE :: (PrimMonad m, VU.Unbox a) => IntMap (PrimState m) a -> Int -> m (Maybe (Int, a))+lookupGE IntMap {..} k = do+  IS.lookupGE setIM k >>= \case+    Just i -> Just . (i,) <$> VGM.read valIM i+    Nothing -> pure Nothing++-- | \(O(\log n)\) Looks up the \((k, v)\) pair with the smallest \(k\) such that \(k \gt k_0\).+--+-- @since 1.1.0.0+{-# INLINE lookupGT #-}+lookupGT :: (PrimMonad m, VU.Unbox a) => IntMap (PrimState m) a -> Int -> m (Maybe (Int, a))+lookupGT is k = lookupGE is (k + 1)++-- | \(O(\log n)\) Looks up the \((k, v)\) pair with the largest key \(k\) such that \(k \le k_0\).+--+-- @since 1.1.0.0+{-# INLINE lookupLE #-}+lookupLE :: (HasCallStack, PrimMonad m, VU.Unbox a) => IntMap (PrimState m) a -> Int -> m (Maybe (Int, a))+lookupLE IntMap {..} k = do+  IS.lookupLE setIM k >>= \case+    Just i -> Just . (i,) <$> VGM.read valIM i+    Nothing -> pure Nothing++-- | \(O(\log n)\) Looks up the \((k, v)\) pair with the largest key \(k\) such that \(k \lt k_0\).+--+-- @since 1.1.0.0+{-# INLINE lookupLT #-}+lookupLT :: (PrimMonad m, VU.Unbox a) => IntMap (PrimState m) a -> Int -> m (Maybe (Int, a))+lookupLT is k = lookupLE is (k - 1)++-- | \(O(\log n)\) Looks up the \((k, v)\) pair with the minimum key \(k\).+--+-- @since 1.1.0.0+{-# INLINE lookupMin #-}+lookupMin :: (PrimMonad m, VU.Unbox a) => IntMap (PrimState m) a -> m (Maybe (Int, a))+lookupMin is = lookupGE is 0++-- | \(O(\log n)\) Looks up the \((k, v)\) pair with the maximum key \(k\).+--+-- @since 1.1.0.0+{-# INLINE lookupMax #-}+lookupMax :: (PrimMonad m, VU.Unbox a) => IntMap (PrimState m) a -> m (Maybe (Int, a))+lookupMax im = lookupLE im (IS.capacity (setIM im) - 1)++-- | \(O(\log n)\) Inserts a \((k, v)\) pair into the map. If an entry with the same key already+-- exists, it is overwritten.+--+-- @since 1.1.0.0+{-# INLINE insert #-}+insert :: (HasCallStack, PrimMonad m, VU.Unbox a) => IntMap (PrimState m) a -> Int -> a -> m ()+insert IntMap {..} k v = do+  IS.insert setIM k+  VGM.write valIM k v++-- | \(O(\log n)\) Inserts a \((k, v)\) pair into the map. If an entry with the same key already+-- exists, it overwritten with \(f(v_{\mathrm{new}}, v_{\mathrm{old}})\).+--+-- @since 1.1.0.0+{-# INLINE insertWith #-}+insertWith :: (HasCallStack, PrimMonad m, VU.Unbox a) => IntMap (PrimState m) a -> (a -> a -> a) -> Int -> a -> m ()+insertWith IntMap {..} f k v = do+  b <- IS.member setIM k+  if b+    then do+      VGM.modify valIM (f v) k+    else do+      IS.insert setIM k+      VGM.write valIM k v++-- | \(O(\log n)\) Modifies the value associated with a key. If an entry with the same key already+-- does not exist, nothing is performed.+--+-- @since 1.1.0.0+{-# INLINE modify #-}+modify :: (HasCallStack, PrimMonad m, VU.Unbox a) => IntMap (PrimState m) a -> (a -> a) -> Int -> m ()+modify IntMap {..} f k = do+  b <- IS.member setIM k+  when b $ do+    VGM.modify valIM f k++-- | \(O(\log n)\) Modifies the value associated with a key. If an entry with the same key already+-- does not exist, nothing is performed.+--+-- @since 1.1.0.0+{-# INLINE modifyM #-}+modifyM :: (HasCallStack, PrimMonad m, VU.Unbox a) => IntMap (PrimState m) a -> (a -> m a) -> Int -> m ()+modifyM IntMap {..} f k = do+  b <- IS.member setIM k+  when b $ do+    VGM.modifyM valIM f k++-- | \(O(\log n)\) Deletes the \((k, v)\) pair with the key \(k\) from the map. Does nothing if no+-- such key exists. Returns whether the key existed.+--+-- @since 1.1.0.0+{-# INLINE delete #-}+delete :: (PrimMonad m) => IntMap (PrimState m) a -> Int -> m Bool+delete im = IS.delete (setIM im)++-- | \(O(\log n)\) Deletes the \((k, v)\) pair with the key \(k\) from the map. Does nothing if no+-- such key exists.+--+-- @since 1.1.0.0+{-# INLINE delete_ #-}+delete_ :: (PrimMonad m) => IntMap (PrimState m) a -> Int -> m ()+delete_ im = IS.delete_ (setIM im)++-- | \(O(\log n)\) Deletes the \((k, v)\) pair with the minimum key \(k\) in the map.+--+-- @since 1.1.0.0+{-# INLINE deleteMin #-}+deleteMin :: (HasCallStack, PrimMonad m, VU.Unbox a) => IntMap (PrimState m) a -> m (Maybe (Int, a))+deleteMin is = do+  lookupMin is+    >>= mapM+      ( \(!key, !val) -> do+          delete_ is key+          pure (key, val)+      )++-- | \(O(\log n)\) Deletes the \((k, v)\) pair with maximum key \(k\) in the map.+--+-- @since 1.1.0.0+{-# INLINE deleteMax #-}+deleteMax :: (HasCallStack, PrimMonad m, VU.Unbox a) => IntMap (PrimState m) a -> m (Maybe (Int, a))+deleteMax is = do+  lookupMax is+    >>= mapM+      ( \(!k, !v) -> do+          delete_ is k+          pure (k, v)+      )++-- | \(O(n \log n)\) Enumerates the keys in the map.+--+-- @since 1.1.0.0+{-# INLINE keys #-}+keys :: (PrimMonad m) => IntMap (PrimState m) a -> m (VU.Vector Int)+keys = IS.keys . setIM++-- | \(O(n \log n)\) Enumerates the elements (values) in the map.+--+-- @since 1.1.0.0+{-# INLINE elems #-}+elems :: (PrimMonad m, VU.Unbox a) => IntMap (PrimState m) a -> m (VU.Vector a)+elems im@IntMap {..} = do+  n <- IS.size setIM+  VU.unfoldrExactNM+    n+    ( \i -> do+        (!i', !x') <- fromJust <$> lookupGT im i+        pure (x', i')+    )+    (-1)++-- | \(O(n \log n)\) Enumerates the key-value pairs in the map.+--+-- @since 1.1.0.0+{-# INLINE assocs #-}+assocs :: (PrimMonad m, VU.Unbox a) => IntMap (PrimState m) a -> m (VU.Vector (Int, a))+assocs im@IntMap {..} = do+  n <- IS.size setIM+  VU.unfoldrExactNM+    n+    ( \i -> do+        (!i', !x') <- fromJust <$> lookupGT im i+        pure ((i', x'), i')+    )+    (-1)
+ src/AtCoder/Extra/IntSet.hs view
@@ -0,0 +1,391 @@+{-# LANGUAGE RecordWildCards #-}++-- original implementation:+-- <https://github.com/maspypy/library/blob/main/ds/fastset.hpp>++-- | A dense, fast `Int` set implemented as a 64-ary tree that covers an interval \([0, n)\).+--+-- ==== __Example__+-- Create an `IntSet` with capacity \(10\):+--+-- >>> import AtCoder.Extra.IntSet qualified as IS+-- >>> is <- IS.new @_ 10+--+-- `insert`, `delete` and other functions are available:+--+-- >>> IS.insert is 0+-- >>> IS.insert is 9+-- >>> IS.member is 9+-- True+--+-- >>> IS.delete is 0+-- True+--+-- >>> IS.size is+-- 1+--+-- >>> IS.member is 1+-- False+--+-- >>> IS.lookupGT is 5+-- Just 9+--+-- @since 1.1.0.0+module AtCoder.Extra.IntSet+  ( -- * IntSet+    IntSet,++    -- * Constructors+    new,+    build,++    -- * Metadata+    capacity,+    size,+    null,++    -- * Lookups+    member,+    notMember,++    -- ** Compartive lookups+    lookupGE,+    lookupGT,+    lookupLE,+    lookupLT,++    -- ** Max/Min lookups+    lookupMin,+    lookupMax,++    -- * Modifications++    -- ** Insertions+    insert,++    -- ** Deletions+    delete,+    delete_,+    deleteMin,+    deleteMax,++    -- * Conversions+    keys,+  )+where++import AtCoder.Internal.Assert qualified as ACIA+import Control.Monad (unless, void)+import Control.Monad.Primitive (PrimMonad, PrimState)+import Data.Bifunctor (bimap)+import Data.Bits+  ( Bits (clearBit, setBit, testBit),+    FiniteBits (countLeadingZeros, countTrailingZeros),+    (.<<.),+    (.>>.),+  )+import Data.Maybe (fromJust)+import Data.Vector qualified as V+import Data.Vector.Generic qualified as VG+import Data.Vector.Generic.Mutable qualified as VGM+import Data.Vector.Unboxed qualified as VU+import Data.Vector.Unboxed.Mutable qualified as VUM+import GHC.Stack (HasCallStack)+import Prelude hiding (null)++-- | \(O(1)\) Retrieves the most significant bit.+--+-- >>> msbOf 0+-- -1+--+-- >>> msbOf maxBound+-- 62+--+-- >>> msbOf $ 4 + 2 + 1+-- 2+{-# INLINE msbOf #-}+msbOf :: Int -> Int+msbOf !x = 63 - countLeadingZeros x++-- | \(O(1)\) Retrieves the least significant bit.+--+-- >>> lsbOf 0+-- -1+--+-- >>> lsbOf maxBound+-- 0+--+-- >>> lsbOf $ 4 + 2 + 1+-- 0+{-# INLINE lsbOf #-}+lsbOf :: Int -> Int+lsbOf 0 = -1+lsbOf x = countTrailingZeros x++{-# INLINE wordSize #-}+wordSize :: Int+wordSize = 64++-- | A dense, fast `Int` set implemented as a 64-ary tree that covers an interval \([0, n)\).+--+-- @since 1.1.0.0+data IntSet s = IntSet+  { -- | Maximum number of elements.+    capacityIS :: {-# UNPACK #-} !Int,+    -- | The number of elements.+    sizeIS :: !(VUM.MVector s Int),+    -- | Segments.+    vecIS :: !(V.Vector (VUM.MVector s Int))+  }++-- | \(O(n)\) Creates an `IntSet` for the interval \([0, n)\).+--+-- @since 1.1.0.0+{-# INLINE new #-}+new :: (PrimMonad m) => Int -> m (IntSet (PrimState m))+new capacityIS = do+  vecIS <-+    V.unfoldrExactNM+      (max 1 logSize)+      ( \len -> do+          let !len' = (len + wordSize - 1) `div` wordSize+          (,len') <$> VUM.replicate len' 0+      )+      capacityIS+  sizeIS <- VUM.replicate 1 (0 :: Int)+  pure IntSet {..}+  where+    (!_, !logSize) =+      until+        ((<= 1) . fst)+        (bimap ((`div` wordSize) . (+ (wordSize - 1))) (+ 1))+        (capacityIS, 0)++-- | \(O(n + m \log n)\) Creates an `IntSet` for the interval \([0, n)\) with initial values.+--+-- @since 1.1.0.0+{-# INLINE build #-}+build :: (PrimMonad m) => Int -> VU.Vector Int -> m (IntSet (PrimState m))+build n vs = do+  set <- new n+  VU.forM_ vs (insert set)+  pure set++-- | \(O(1)\) Returns the capacity \(n\), where the interval \([0, n)\) is covered by the set.+--+-- @since 1.1.0.0+{-# INLINE capacity #-}+capacity :: IntSet s -> Int+capacity = capacityIS++-- | \(O(1)\) Returns the number of elements in the set.+--+-- @since 1.1.0.0+{-# INLINE size #-}+size :: (PrimMonad m) => IntSet (PrimState m) -> m Int+size = (`VUM.unsafeRead` 0) . sizeIS++-- | \(O(1)\) Returns whether the set is empty.+--+-- @since 1.1.0.0+{-# INLINE null #-}+null :: (PrimMonad m) => IntSet (PrimState m) -> m Bool+null = ((== 0) <$>) . size++-- | \(O(\log n)\) Tests whether \(k\) is in the set.+--+-- @since 1.1.0.0+{-# INLINE member #-}+member :: (PrimMonad m) => IntSet (PrimState m) -> Int -> m Bool+member IntSet {..} k+  | ACIA.testIndex k capacityIS = do+      let (!q, !r) = k `divMod` wordSize+      (`testBit` r) <$> VGM.unsafeRead (VG.unsafeHead vecIS) q+  | otherwise = pure False++-- | \(O(\log n)\) Tests whether \(k\) is not in the set.+--+-- @since 1.1.0.0+{-# INLINE notMember #-}+notMember :: (PrimMonad m) => IntSet (PrimState m) -> Int -> m Bool+notMember dis k = not <$> member dis k++-- | \(O(\log n)\) Looks up the smallest key \(k\) such that \(k \ge k_0\).+--+-- @since 1.1.0.0+{-# INLINE lookupGE #-}+lookupGE :: (PrimMonad m) => IntSet (PrimState m) -> Int -> m (Maybe Int)+lookupGE IntSet {..} i0+  | i0 >= capacityIS = pure Nothing+  | otherwise = inner 0 $ max 0 i0 -- REMARK: it's very important to keep @i@ non-negative.+  where+    inner h i+      | h >= V.length vecIS = pure Nothing+      -- ?+      | q == VUM.length (VG.unsafeIndex vecIS h) = pure Nothing+      | otherwise = do+          d <- (.>>. r) <$> VGM.unsafeRead (VG.unsafeIndex vecIS h) q+          if d == 0+            then inner (h + 1) (q + 1)+            else+              Just+                <$> V.foldM'+                  ( \ !acc vec -> do+                      !dx <- lsbOf <$> VGM.unsafeRead vec acc+                      pure $ acc * wordSize + dx+                  )+                  (i + lsbOf d)+                  (V.unsafeBackpermute vecIS (V.enumFromStepN (h - 1) (-1) h))+      where+        (!q, !r) = i `divMod` wordSize++-- | \(O(\log n)\) Looks up the smallest key \(k\) such that \(k \gt k_0\).+--+-- @since 1.1.0.0+{-# INLINE lookupGT #-}+lookupGT :: (PrimMonad m) => IntSet (PrimState m) -> Int -> m (Maybe Int)+lookupGT is k = lookupGE is (k + 1)++-- | \(O(\log n)\) Looks up the largest key \(k\) such that \(k \le k_0\).+--+-- @since 1.1.0.0+{-# INLINE lookupLE #-}+lookupLE :: (PrimMonad m) => IntSet (PrimState m) -> Int -> m (Maybe Int)+lookupLE IntSet {..} i0+  | i0 <= -1 = pure Nothing+  | otherwise = inner 0 $ min (capacityIS - 1) i0+  where+    inner h i+      | h >= V.length vecIS = pure Nothing+      | i == -1 = pure Nothing+      | otherwise = do+          d <- (.<<. (63 - r)) <$> VGM.unsafeRead (VG.unsafeIndex vecIS h) q+          if d == 0+            then inner (h + 1) (q - 1)+            else do+              Just+                <$> V.foldM'+                  ( \ !acc vec -> do+                      !dx <- msbOf <$> VGM.unsafeRead vec acc+                      pure $ acc * wordSize + dx+                  )+                  (i - countLeadingZeros d)+                  (V.unsafeBackpermute vecIS (V.enumFromStepN (h - 1) (-1) h))+      where+        (!q, !r) = i `divMod` wordSize++-- | \(O(\log n)\) Looks up the largest key \(k\) such that \(k \lt k_0\).+--+-- @since 1.1.0.0+{-# INLINE lookupLT #-}+lookupLT :: (PrimMonad m) => IntSet (PrimState m) -> Int -> m (Maybe Int)+lookupLT is k = lookupLE is (k - 1)++-- | \(O(\log n)\) Looks up the minimum key.+--+-- @since 1.1.0.0+{-# INLINE lookupMin #-}+lookupMin :: (PrimMonad m) => IntSet (PrimState m) -> m (Maybe Int)+lookupMin is = lookupGE is 0++-- | \(O(\log n)\) Looks up the maximum key.+--+-- @since 1.1.0.0+{-# INLINE lookupMax #-}+lookupMax :: (PrimMonad m) => IntSet (PrimState m) -> m (Maybe Int)+lookupMax is = lookupLE is (capacityIS is - 1)++-- | \(O(\log n)\) Inserts a key \(k\) into the set. If an entry with the same key already exists,+-- it is overwritten.+--+-- @since 1.1.0.0+{-# INLINE insert #-}+insert :: (HasCallStack, PrimMonad m) => IntSet (PrimState m) -> Int -> m ()+insert is@IntSet {..} k = do+  b <- member is k+  unless b $ do+    VUM.unsafeModify sizeIS (+ 1) 0+    V.foldM'_+      ( \i vec -> do+          let (!q, !r) = i `divMod` wordSize+          VGM.unsafeModify vec (`setBit` r) q+          pure q+      )+      k+      vecIS+  where+    !_ = ACIA.checkIndex "AtCoder.Extra.IntSet.insert" k capacityIS++-- | \(O(\log n)\) Deletes a key \(k\) from the set. Does nothing if no such key exists. Returns+-- whether the key existed.+--+-- @since 1.1.0.0+{-# INLINE delete #-}+delete :: (PrimMonad m) => IntSet (PrimState m) -> Int -> m Bool+delete is@IntSet {..} k = do+  b_ <- member is k+  if b_+    then do+      VUM.unsafeModify sizeIS (subtract 1) 0+      V.foldM'_+        ( \(!b, !i) vec -> do+            let (!q, !r) = i `divMod` wordSize+            -- TODO: early return is possible+            unless b $ do+              VGM.unsafeModify vec (`clearBit` r) q+            -- `b` remembers if any other bit was on+            b' <- (/= 0) <$> VGM.unsafeRead vec q+            pure (b', q)+        )+        (False, k)+        vecIS+      pure True+    else pure False++-- | \(O(\log n)\) Deletes a key \(k\) from the set. Does nothing if no such key exists.+--+-- @since 1.1.0.0+{-# INLINE delete_ #-}+delete_ :: (PrimMonad m) => IntSet (PrimState m) -> Int -> m ()+delete_ is k = void $ delete is k++-- | \(O(\log n)\) Deletes the minimum key from the set. Returns `Nothing` if the set is empty.+--+-- @since 1.1.0.0+{-# INLINE deleteMin #-}+deleteMin :: (PrimMonad m) => IntSet (PrimState m) -> m (Maybe Int)+deleteMin is = do+  lookupMin is+    >>= mapM+      ( \key -> do+          delete_ is key+          pure key+      )++-- | \(O(\log n)\) Deletes the maximum key from the set. Returns `Nothing` if the set is empty.+--+-- @since 1.1.0.0+{-# INLINE deleteMax #-}+deleteMax :: (PrimMonad m) => IntSet (PrimState m) -> m (Maybe Int)+deleteMax is = do+  lookupMax is+    >>= mapM+      ( \key -> do+          delete_ is key+          pure key+      )++-- | \(O(n \log n)\) Enumerates the keys in the map.+--+-- @since 1.1.0.0+{-# INLINE keys #-}+keys :: (PrimMonad m) => IntSet (PrimState m) -> m (VU.Vector Int)+keys is@IntSet {sizeIS} = do+  n <- VGM.unsafeRead sizeIS 0+  VU.unfoldrExactNM+    n+    ( \i -> do+        i' <- fromJust <$> lookupGT is i+        pure (i', i')+    )+    (-1)
+ src/AtCoder/Extra/IntervalMap.hs view
@@ -0,0 +1,462 @@+{-# LANGUAGE DerivingStrategies #-}++-- original implementation:+-- <https://noimi.hatenablog.com/entry/2021/05/02/195143>++-- | Dense map covering \([0, n)\) that manages non-overlapping intervals \([l, r)\) within it. Each+-- interval has an associated value \(v\). Use @onAdd@ and @onDel@ hooks to track interval state+-- changes during `buildM`, `insertM` and `deleteM` operations.+--+-- ==== Invariant+-- Each interval is operated as a whole, similar to a persistant data structure. When part of an+-- inerval is modified, the whole interval is deleted first, and the subintervals are re-inserted.+-- It's important for tracking non-linear interval information with the @onAdd@ and @onDel@ hooks+-- (callbacks).+--+-- ==== __Example__+-- Create an `IntervalMap` that covers a half-open interval \([0, n)\):+--+-- >>> import AtCoder.Extra.IntervalMap qualified as ITM+-- >>> import Data.Vector.Unboxed qualified as VU+-- >>> import Data.Vector.Unboxed.Mutable qualified as VUM+-- >>> itm <- ITM.new @_ @Int 4+--+-- It handles range set queries in amortized \(O(\log n)\) time:+--+-- >>> ITM.insert itm 0 4 0 -- 0 0 0 0+-- >>> ITM.insert itm 1 3 1 -- 0 1 1 0+-- >>> ITM.freeze itm+-- [(0,(1,0)),(1,(3,1)),(3,(4,0))]+--+-- Track interval informations with the @onAdd@ and @onDel@ hooks:+--+-- >>> import Debug.Trace (traceShow)+-- >>> itm <- ITM.new @_ @Int 4+-- >>> let onAdd l r x = print ("onAdd", l, r, x)+-- >>> let onDel l r x = print ("onDel", l, r, x)+--+-- >>> ITM.insertM itm 0 4 0 onAdd onDel -- 0 0 0 0+-- ("onAdd",0,4,0)+--+-- >>> ITM.insertM itm 1 3 1 onAdd onDel -- 0 1 1 0+-- ("onDel",0,4,0)+-- ("onAdd",0,1,0)+-- ("onAdd",3,4,0)+-- ("onAdd",1,3,1)+--+-- >>> ITM.deleteM itm 0 4 onAdd onDel+-- ("onDel",0,1,0)+-- ("onDel",1,3,1)+-- ("onDel",3,4,0)+--+-- @since 1.1.0.0+module AtCoder.Extra.IntervalMap+  ( -- * IntervalMap+    IntervalMap,++    -- * Constructors+    new,+    build,+    buildM,++    -- * Metadata+    capacity,++    -- * Lookups+    contains,+    intersects,+    lookup,+    read,+    readMaybe,++    -- * Modifications++    -- ** Insertions+    insert,+    insertM,++    -- ** Deletions+    delete,+    deleteM,++    -- ** Overwrites+    overwrite,+    overwriteM,++    -- * Conversions+    freeze,+  )+where++import AtCoder.Extra.IntMap qualified as IM+import Control.Monad (foldM_)+import Control.Monad.Primitive (PrimMonad, PrimState)+import Data.Vector.Generic qualified as G+import Data.Vector.Unboxed qualified as VU+import GHC.Stack (HasCallStack)+import Prelude hiding (lookup, read)++-- | Dense map covering \([0, n)\) that manages non-overlapping intervals \((l, r)\) within it. Each+-- interval has an associated value \(x\). Use @onAdd@ and @onDel@ hooks to track interval state+-- changes during `buildM`, `insertM` and `deleteM` operations.+--+-- @since 1.1.0.0+newtype IntervalMap s a = IntervalMap+  { -- | Maps \(l\) to \((r, a)\).+    unITM :: IM.IntMap s (Int, a)+  }++-- | \(O(n)\) Creates an empty `IntervalMap`.+--+-- @since 1.1.0.0+new :: (PrimMonad m, VU.Unbox a) => Int -> m (IntervalMap (PrimState m) a)+new = fmap IntervalMap . IM.new++-- | \(O(n + m \log n)\) Creates an `IntervalMap` by combining consecutive equal values into one+-- interval.+--+-- ==== __Example__+-- >>> itm <- build @_ @Int (VU.fromList [10,10,11,11,12,12])+-- >>> freeze itm+-- [(0,(2,10)),(2,(4,11)),(4,(6,12))]+--+-- @since 1.1.0.0+build :: (PrimMonad m, Eq a, VU.Unbox a) => VU.Vector a -> m (IntervalMap (PrimState m) a)+build xs = buildM xs onAdd+  where+    onAdd _ _ _ = pure ()++-- | \(O(n + m \log n)\) Creates an `IntervalMap` by combining consecutive equal values into one+-- interval, while performing @onAdd@ hook for each interval.+--+-- @since 1.1.0.0+buildM ::+  (PrimMonad m, Eq a, VU.Unbox a) =>+  -- | Input values+  VU.Vector a ->+  -- | @onAdd@ hook that take an interval \([l, r)\) with associated value \(v\)+  (Int -> Int -> a -> m ()) ->+  -- | The map+  m (IntervalMap (PrimState m) a)+buildM xs onAdd = do+  dim <- IM.new (G.length xs)+  foldM_ (step dim) (0 :: Int) $ G.group xs+  pure $ IntervalMap dim+  where+    step dim !l !xs' = do+      let !l' = l + G.length xs'+      IM.insert dim l (l', G.head xs')+      onAdd l l' (G.head xs')+      pure l'++-- | \(O(1)\) Returns the capacity \(n\), where the interval \([0, n)\) is managed by the map.+--+-- @since 1.1.0.0+{-# INLINE capacity #-}+capacity :: IntervalMap s a -> Int+capacity = IM.capacity . unITM++-- | \(O(\log n)\) Returns whether a point \(x\) is contained within any of the intervals.+--+-- @since 1.1.0.0+contains :: (PrimMonad m, VU.Unbox a) => IntervalMap (PrimState m) a -> Int -> m Bool+contains itm i = intersects itm i (i + 1)++-- | \(O(\log n)\) Returns whether an interval \([l, r)\) is fully contained within any of the+-- intervals.+--+-- @since 1.1.0.0+intersects :: (PrimMonad m, VU.Unbox a) => IntervalMap (PrimState m) a -> Int -> Int -> m Bool+intersects (IntervalMap dim) l r+  | l >= r = pure False+  | otherwise = do+      res <- IM.lookupLE dim l+      pure $ case res of+        Just (!_, (!r', !_)) -> r <= r'+        _ -> False++-- | \(O(\log n)\) Looks up an interval that fully contains \([l, r)\).+--+-- @since 1.1.0.0+lookup :: (PrimMonad m, VU.Unbox a) => IntervalMap (PrimState m) a -> Int -> Int -> m (Maybe (Int, Int, a))+lookup (IntervalMap im) l r+  | l >= r = pure Nothing+  | otherwise = do+      res <- IM.lookupLE im l+      pure $ case res of+        Just (!l', (!r', !a))+          | r <= r' -> Just (l', r', a)+        _ -> Nothing++-- | \(O(\log n)\) Looks up an interval that fully contains \([l, r)\) and reads out the value.+-- Throws an error if no such interval exists.+--+-- @since 1.1.0.0+read :: (HasCallStack, PrimMonad m, VU.Unbox a) => IntervalMap (PrimState m) a -> Int -> Int -> m a+read itm l r = do+  res <- readMaybe itm l r+  pure $ case res of+    Just !a -> a+    Nothing -> error $ "[read] not a member: " ++ show (l, r)++-- | \(O(\log n)\) Looks up an interval that fully contains \([l, r)\) and reads out the value.+-- Returns `Nothing` if no such interval exists.+--+-- @since 1.1.0.0+readMaybe :: (PrimMonad m, VU.Unbox a) => IntervalMap (PrimState m) a -> Int -> Int -> m (Maybe a)+readMaybe (IntervalMap dim) l r+  | l >= r = pure Nothing+  | otherwise = do+      res <- IM.lookupLE dim l+      pure $ case res of+        Just (!_, (!r', !a))+          | r <= r' -> Just a+        _ -> Nothing++-- | Amortized \(O(\log n)\) Inserts an interval \([l, r)\) with associated value \(v\) into the+-- map. Overwrites any overlapping intervals.+--+-- @since 1.1.0.0+insert :: (PrimMonad m, Eq a, VU.Unbox a) => IntervalMap (PrimState m) a -> Int -> Int -> a -> m ()+insert itm l r x = insertM itm l r x onAdd onDel+  where+    onAdd _ _ _ = pure ()+    onDel _ _ _ = pure ()++-- | Amortized \(O(\log n)\) Inserts an interval \([l, r)\) with associated value \(v\) into the+-- map. Overwrites any overlapping intervals. Tracks interval state changes via @onAdd@ and @onDel@+-- hooks.+--+-- @since 1.1.0.0+insertM ::+  (PrimMonad m, Eq a, VU.Unbox a) =>+  -- | The map+  IntervalMap (PrimState m) a ->+  -- | \(l\)+  Int ->+  -- | \(r\)+  Int ->+  -- | \(v\)+  a ->+  -- | @onAdd@ hook that take an interval \([l, r)\) with associated value \(v\)+  (Int -> Int -> a -> m ()) ->+  -- | @onDel@ hook that take an interval \([l, r)\) with associated value \(v\)+  (Int -> Int -> a -> m ()) ->+  m ()+insertM (IntervalMap dim) l0 r0 x onAdd onDel+  | l0 >= r0 = pure ()+  | otherwise = do+      !r <- handleRight l0 r0+      (!l', !r') <- handleLeft l0 r+      onAdd l' r' x+      IM.insert dim l' (r', x)+  where+    handleRight l r = do+      res <- IM.lookupGE dim l+      case res of+        Just interval0@(!_, (!_, !_)) -> run interval0 l r+        Nothing -> pure r++    -- Looks into intervals with @l' >= l0@.+    --           [----]+    -- (i)            *--------]   overwrite if it's x+    -- (ii)   [-------]*      delete anyways+    -- (iii)    *(------]     overwrite if it's x, or+    run (!l', (!r', !x')) l r+      | l' > r = do+          -- not adjacent: end.+          pure r+      -- (i)+      | l' == r && x' == x = do+          -- adjacent interval with the same value: merge into one.+          onDel l' r' x'+          IM.delete_ dim l'+          pure r'+      | l' == r = do+          -- adjacent interval with different values: nothing to do.+          pure r+      -- (ii)+      | r' <= r = do+          -- inside the interval: delete and continue+          onDel l' r' x'+          IM.delete_ dim l'+          res <- IM.lookupGT dim l'+          case res of+            Just rng -> run rng l r+            Nothing -> pure r+      -- (iii)+      | x' == x = do+          -- intersecting interval with the same value: merge into one.+          onDel l' r' x'+          IM.delete_ dim l'+          pure r'+      | otherwise = do+          -- intersecting interval with a different value: delete the intersection.+          onDel l' r' x'+          onAdd r r' x'+          IM.delete_ dim l'+          IM.insert dim r (r', x')+          pure r++    handleLeft l r = do+      res <- IM.lookupLT dim l+      case res of+        Nothing -> pure (l, r)+        Just (!l', (!r', !x'))+          -- (i): adjacent interval+          | r' == l && x' == x -> do+              -- adjacent interval with the same value: merge into one.+              onDel l' r' x'+              IM.delete_ dim l'+              pure (l', r)+          | r' == l -> do+              -- adjacent interval with different values: nothing to do.+              pure (l, r)+          -- (ii): not adjacent or intersecting+          | r' < l -> do+              pure (l, r)+          -- (iii): intersecting+          | x' == x -> do+              -- insersecting interval with the same value: merge into one.+              onDel l' r' x'+              IM.delete_ dim l'+              pure (min l l', max r r')+          | r' > r -> do+              -- [l', r') contains [l, r) with a different value: split into three.+              onDel l' r' x'+              onAdd l' l x'+              onAdd r r' x'+              -- IM.delete_ dim l'+              IM.insert dim l' (l, x')+              IM.insert dim r (r', x')+              pure (l, r)+          | otherwise -> do+              -- insersecting interval with a different value: delete.+              onDel l' r' x'+              onAdd l' l x'+              -- IM.delete_ dim l'+              IM.insert dim l' (l, x')+              pure (l, r)++-- | Amortized \(O(\log n)\) Deletes an interval \([l, r)\) from the map.+--+-- @since 1.1.0.0+delete :: (PrimMonad m, VU.Unbox a) => IntervalMap (PrimState m) a -> Int -> Int -> m ()+delete itm l r = deleteM itm l r onAdd onDel+  where+    onAdd _ _ _ = pure ()+    onDel _ _ _ = pure ()++-- | Amortized \(O(\log n)\) Deletes an interval \([l, r)\) from the map. Tracks interval state+-- changes via @onAdd@ and @onDel@ hooks.+--+-- @since 1.1.0.0+deleteM ::+  (PrimMonad m, VU.Unbox a) =>+  -- | The map+  IntervalMap (PrimState m) a ->+  -- | \(l\)+  Int ->+  -- | \(r\)+  Int ->+  -- | @onAdd@ hook that take an interval \([l, r)\) with associated value \(v\)+  (Int -> Int -> a -> m ()) ->+  -- | @onDel@ hook that take an interval \([l, r)\) with associated value \(v\)+  (Int -> Int -> a -> m ()) ->+  m ()+deleteM (IntervalMap dim) l0 r0 onAdd onDel+  | l0 >= r0 = pure ()+  | otherwise = do+      handleRight l0 r0+      handleLeft l0 r0+  where+    handleRight l r = do+      res <- IM.lookupGE dim l+      case res of+        Just interval0@(!_, (!_, !_)) -> run interval0 l r+        Nothing -> pure ()++    run (!l', (!r', !x')) l r+      | l' >= r = do+          -- not intersecting+          pure ()+      | r' <= r = do+          -- contained+          onDel l' r' x'+          IM.delete_ dim l'+          res <- IM.lookupGT dim l'+          case res of+            Just rng -> run rng l r+            Nothing -> pure ()+      | otherwise = do+          -- intersecting+          onDel l' r' x'+          onAdd r r' x'+          IM.delete_ dim l'+          IM.insert dim r (r', x')+          pure ()++    handleLeft l r = do+      res <- IM.lookupLT dim l+      case res of+        Nothing -> pure ()+        Just (!l', (!r', !x'))+          | r' <= l -> do+              -- not intersecting+              pure ()+          | r' > r -> do+              -- [l', r') contains [l, r)+              onDel l' r' x'+              onAdd l' l x'+              onAdd r r' x'+              -- IM.delete dim l'+              IM.insert dim l' (l, x')+              IM.insert dim r (r', x')+          | otherwise -> do+              -- intersecting+              onDel l' r' x'+              onAdd l' l x'+              -- IM.delete_ dim l'+              IM.insert dim l' (l, x')++-- | \(O(\log n)\) Shorthand for overwriting the value of an interval that contains \([l, r)\).+--+-- @since 1.1.0.0+overwrite :: (PrimMonad m, Eq a, VU.Unbox a) => IntervalMap (PrimState m) a -> Int -> Int -> a -> m ()+overwrite itm l r x = do+  res <- lookup itm l r+  case res of+    Just (!l', !r', !_) -> insert itm l' r' x+    Nothing -> pure ()++-- | \(O(\log n)\). Shorthand for overwriting the value of an interval that contains \([l, r)\).+-- Tracks interval state changes via @onAdd@ and @onDel@ hooks.+--+-- @since 1.1.0.0+overwriteM ::+  (PrimMonad m, Eq a, VU.Unbox a) =>+  -- | The map+  IntervalMap (PrimState m) a ->+  -- | \(l\)+  Int ->+  -- | \(r\)+  Int ->+  -- | \(v\)+  a ->+  -- | @onAdd@ hook that take an interval \([l, r)\) with associated value \(v\)+  (Int -> Int -> a -> m ()) ->+  -- | @onDel@ hook that take an interval \([l, r)\) with associated value \(v\)+  (Int -> Int -> a -> m ()) ->+  m ()+overwriteM itm l r x onAdd onDel = do+  res <- lookup itm l r+  case res of+    Just (!l', !r', !_) -> insertM itm l' r' x onAdd onDel+    Nothing -> pure ()++-- | \(O(n \log n)\) Enumerates the intervals and the associated values as \((l, (r, x))\) tuples,+-- where \([l, r)\) is the interval and \(x\) is the associated value.+--+-- @since 1.1.0.0+freeze :: (PrimMonad m, VU.Unbox a) => IntervalMap (PrimState m) a -> m (VU.Vector (Int, (Int, a)))+freeze = IM.assocs . unITM
src/AtCoder/Extra/Math.hs view
@@ -1,34 +1,50 @@ -- | Extra math module. ----- ==== Examples--- >>> import AtCoder.Extra.Math qualified as M--- >>> import Data.Semigroup (Product(..), Sum(..))--- >>> getProduct $ M.power (<>) 32 (Product 2)--- 4294967296------ >>> getProduct $ M.stimes' 32 (Product 2)--- 4294967296------ >>> getProduct $ M.mtimes' 32 (Product 2)--- 4294967296--- -- @since 1.0.0.0 module AtCoder.Extra.Math-  ( -- * Binary exponential+  ( -- * Re-exports from the internal math module+    isPrime32,+    ACIM.invGcd,+    ACIM.primitiveRoot,++    -- * Binary exponentiation++    -- | ==== __Examples__+    -- >>> import AtCoder.Extra.Math qualified as M+    -- >>> import Data.Semigroup (Product(..), Sum(..))+    -- >>> getProduct $ M.power (<>) 32 (Product 2)+    -- 4294967296+    --+    -- >>> getProduct $ M.stimes' 32 (Product 2)+    -- 4294967296+    --+    -- >>> getProduct $ M.mtimes' 32 (Product 2)+    -- 4294967296     power,     stimes',     mtimes',   ) where +import AtCoder.Internal.Math qualified as ACIM import Data.Bits ((.>>.)) --- TODO: add `HasCallStack` and provide with `unsafePower`.+-- | \(O(k \log^3 n) (k = 3)\). Returns whether the given `Int` value is a prime number.+--+-- ==== Constraints+-- - \(n < 4759123141 (2^{32} < 4759123141)\), otherwise the return value can lie+--   (see [Wikipedia](https://en.wikipedia.org/wiki/Miller%E2%80%93Rabin_primality_test#Testing_against_small_sets_of_bases)).+--+--+-- @since 1.1.0.0+{-# INLINE isPrime32 #-}+isPrime32 :: Int -> Bool+isPrime32 = ACIM.isPrime --- | Calculates \(s^n\) with custom multiplication operator using the binary exponentiation+-- | Calculates \(x^n\) with custom multiplication operator using the binary exponentiation -- technique. ----- The internal implementation is taken from `Data.Semigroup.stimes`, but `power` uses strict+-- The internal implementation is taken from @Data.Semigroup.stimes@, but `power` uses strict -- evaluation and is often much faster. -- -- ==== Complexity@@ -53,7 +69,7 @@       | n == 1 = x `op` z       | otherwise = g (x `op` x) (n .>>. 1) (x `op` z) --- | Strict `Data.Semigroup.stimes`.+-- | Strict variant of @Data.Semigroup.stimes@. -- -- ==== Complexity -- - \(O(\log n)\)@@ -66,7 +82,7 @@ stimes' :: (Semigroup a) => Int -> a -> a stimes' = power (<>) --- | Strict `Data.Monoid.mtimes`.+-- | Strict variant of @Data.Monoid.mtimes@. -- -- ==== Complexity -- - \(O(\log n)\)
src/AtCoder/Extra/Monoid.hs view
@@ -1,31 +1,42 @@ {-# LANGUAGE TypeFamilies #-} --- | Extra module of pre-defined `SegAct` instances.------ Be warned that they're not 100% guaranteed to be correct.+-- | Extra module of pre-defined `SegAct` instances and helpful monoids. -- -- @since 1.0.0.0 module AtCoder.Extra.Monoid-  ( -- * SegAct (re-export)+  ( -- * Re-exports++    -- | It's mainly a list. It is recommended to use specific submodules.++    -- ** SegAct     SegAct (..), -    -- * Affine1+    -- ** Affine1     Affine1 (..),     Affine1Repr, -    -- * Range add+    -- ** Mat2x2+    Mat2x2 (..),+    Mat2x2Repr,+    V2 (..),+    V2Repr,++    -- ** Range add     RangeAdd (..),-    RangeAddId (..), -    -- * Range set+    -- ** Range set     RangeSet (..),-    RangeSetId (..),+    RangeSetRepr,++    -- ** Rolling hash+    RollingHash,   ) where  import AtCoder.Extra.Monoid.Affine1 (Affine1 (..), Affine1Repr)+import AtCoder.Extra.Monoid.Mat2x2 (Mat2x2 (..), Mat2x2Repr) import AtCoder.Extra.Monoid.RangeAdd (RangeAdd (..))-import AtCoder.Extra.Monoid.RangeAddId (RangeAddId (..))-import AtCoder.Extra.Monoid.RangeSet (RangeSet (..))-import AtCoder.Extra.Monoid.RangeSetId (RangeSetId (..))+import AtCoder.Extra.Monoid.RangeSet (RangeSet (..), RangeSetRepr)+import AtCoder.Extra.Monoid.RollingHash (RollingHash)+import AtCoder.Extra.Monoid.V2 (V2 (..), V2Repr) import AtCoder.LazySegTree (SegAct (..))
src/AtCoder/Extra/Monoid/Affine1.hs view
@@ -1,17 +1,23 @@ {-# LANGUAGE TypeFamilies #-} --- | Range add monoid action for \([l, r)\) intervals: \(f: x \rightarrow ax + b\).+-- | Monoid action \(f: x \rightarrow ax + b\). --+-- - Use @Mat2x2@ if inverse operations are required, or if it's necessary to store the monoid+-- length in the acted monoid (@V2@).+-- -- @since 1.0.0.0 module AtCoder.Extra.Monoid.Affine1   ( -- * Affine1     Affine1 (..),     Affine1Repr, -    -- * Constructor+    -- * Constructors     new,+    unAffine1,+    ident,+    zero, -    -- * Action+    -- * Actions     act,   ) where@@ -27,17 +33,16 @@ import Data.Vector.Unboxed qualified as VU import Data.Vector.Unboxed.Mutable qualified as VUM --- Tuple is not the fastest representation, but it's easier to implement `Unbox`.---- | Range add monoid action for \([l, r)\) intervals: \(f: x \rightarrow ax + b\).+-- | Monoid action \(f: x \rightarrow ax + b\). --+-- - Use @Mat2x2@ if inverse operations are required, or if it's necessary to store the monoid+-- length in the acted monoid (@V2@).+-- -- ==== Composition and dual--- `Semigroup` for `Affine1` is implemented like function composition, and rightmost affine--- transformation is applied first: \((f_1 \circ f_2) v := f_1 (f_2(v))\). If you need 'foldr'--- of \([f_l, f_{l+1}, .., f_r)\) on a segment tree, be sure to wrap `Affine1` in--- `Data.Monoid.Dual`.+-- The affine transformation acts as a left monoid action: \(f_2 (f_1 v) = (f_2 \circ f_1) v\). To+-- apply the leftmost transformation first in a segment tree, wrap `Affine1` in @Data.Monoid.Dual@. ----- ==== Example+-- ==== __Example__ -- >>> import AtCoder.Extra.Monoid (SegAct(..), Affine1(..)) -- >>> import AtCoder.LazySegTree qualified as LST -- >>> seg <- LST.build @_ @(Affine1 Int) @(Sum Int) $ VU.generate 3 Sum -- [0, 1, 2]@@ -62,21 +67,42 @@ -- @since 1.0.0.0 type Affine1Repr a = (a, a) --- | Creates `Affine1`.+-- | \(O(1)\) Creates a one-dimensional affine transformation: \(f: x \rightarrow a \times x + b\). -- -- @since 1.0.0.0 {-# INLINE new #-} new :: a -> a -> Affine1 a new !a !b = Affine1 (a, b) --- | Applies \(f: x \rightarrow a \times x + b\).+-- | \(O(1)\) Retrieves the two components of `Affine1`. --+-- @since 1.1.0.0+{-# INLINE unAffine1 #-}+unAffine1 :: Affine1 a -> Affine1Repr a+unAffine1 (Affine1 a) = a++-- | \(O(1)\) Identity transformation.+--+-- @since 1.1.0.0+{-# INLINE ident #-}+ident :: (Num a) => Affine1 a+ident = Affine1 (1, 0)++-- | \(O(1)\) Transformation to zero.+--+-- @since 1.1.0.0+{-# INLINE zero #-}+zero :: (Num a) => Affine1 a+zero = Affine1 (0, 0)++-- | \(O(1)\) Applies the one-dimensional affine transformation \(f: x \rightarrow a \times x + b\).+-- -- @since 1.0.0.0 {-# INLINE act #-} act :: (Num a) => Affine1 a -> a -> a act (Affine1 (!a, !b)) x = a * x + b --- | Acts on @a@ with length in terms of `SegAct`. Works for `Sum a` only.+-- | \(O(1)\) Acts on @a@ with length in terms of `SegAct`. Works for `Sum a` only. -- -- @since 1.0.0.0 {-# INLINE actWithLength #-}
+ src/AtCoder/Extra/Monoid/Mat2x2.hs view
@@ -0,0 +1,202 @@+{-# LANGUAGE TypeFamilies #-}++-- | Monoid action \(f: x \rightarrow ax + b\). Less efficient than @Affine1@, but compatible with+-- inverse opereations.+--+-- @since 1.1.0.0+module AtCoder.Extra.Monoid.Mat2x2+  ( -- * Mat2x2+    Mat2x2 (..),+    Mat2x2Repr,++    -- * Constructors+    new,+    unMat2x2,+    ident,+    zero,++    -- * Actions+    act,++    -- * Operators+    map,+    det,+    inv,+  )+where++import AtCoder.Extra.Math qualified as ACEM+import AtCoder.Extra.Monoid.V2 (V2 (..))+import AtCoder.LazySegTree (SegAct (..))+import Data.Semigroup (Dual (..), Semigroup (..))+import Data.Vector.Generic qualified as VG+import Data.Vector.Generic.Mutable qualified as VGM+import Data.Vector.Unboxed qualified as VU+import Data.Vector.Unboxed.Mutable qualified as VUM+import GHC.Stack (HasCallStack)+import Prelude hiding (map)++-- | Monoid action \(f: x \rightarrow ax + b\). Less efficient than @Affine1@, but compatible with+-- inverse opereations.+--+-- ==== Composition and dual+-- The affine transformation acts as a left monoid action: \(f_2 (f_1 v) = (f_2 \circ f_1) v\). To+-- apply the leftmost transformation first in a segment tree, wrap `Mat2x2` in @Data.Monoid.Dual@.+--+-- ==== __Example__+-- >>> import AtCoder.Extra.Monoid.Mat2x2 qualified as Mat2x2+-- >>> import AtCoder.Extra.Monoid.V2 qualified as V2+-- >>> import AtCoder.Extra.Monoid (SegAct(..), Mat2x2(..), V2(..))+-- >>> import AtCoder.LazySegTree qualified as LST+-- >>> seg <- LST.build @_ @(Mat2x2 Int) @(V2 Int) $ VU.generate 3 V2.new -- [0, 1, 2]+-- >>> LST.applyIn seg 0 3 $ Mat2x2.new 2 1 -- [1, 3, 5]+-- >>> V2.unV2 <$> LST.allProd seg+-- 9+--+-- @since 1.1.0.0+newtype Mat2x2 a = Mat2x2 (Mat2x2Repr a)+  deriving newtype+    ( -- | @since 1.1.0.0+      Eq,+      -- | @since 1.1.0.0+      Ord,+      -- | @since 1.1.0.0+      Show+    )++-- | `Mat2x2` internal representation. Tuples are not the fastest representation, but it's easier+-- to implement `Data.Vector.Unboxed.Unbox`.+--+-- @since 1.1.0.0+type Mat2x2Repr a = (a, a, a, a)++-- | \(O(1)\) Creates a one-dimensional affine transformation: \(f: x \rightarrow a \times x + b\).+--+-- @since 1.1.0.0+{-# INLINE new #-}+new :: (Num a) => a -> a -> Mat2x2 a+new !a !b = Mat2x2 (a, b, 0, 1)++-- | \(O(1)\) Retrieves the four components of `Mat2x2`.+--+-- @since 1.1.0.0+{-# INLINE unMat2x2 #-}+unMat2x2 :: Mat2x2 a -> Mat2x2Repr a+unMat2x2 (Mat2x2 a) = a++-- | \(O(1)\) Transformation to zero.+--+-- @since 1.1.0.0+{-# INLINE zero #-}+zero :: (Num a) => Mat2x2 a+zero = Mat2x2 (0, 0, 0, 0)++-- | \(O(1)\) Identity transformation.+--+-- @since 1.1.0.0+{-# INLINE ident #-}+ident :: (Num a) => Mat2x2 a+ident = Mat2x2 (1, 0, 0, 1)++-- | \(O(1)\) Multiplies `Mat2x2` to `V2`.+{-# INLINE mulMV #-}+mulMV :: (Num a) => Mat2x2 a -> V2 a -> V2 a+mulMV (Mat2x2 (!a11, !a12, !a21, !a22)) (V2 (!x1, !x2)) = V2 (a', b')+  where+    !a' = a11 * x1 + a12 * x2+    !b' = a21 * x1 + a22 * x2++-- | \(O(1)\) Multiplies `Mat2x2` to `Mat2x2`.+{-# INLINE mulMM #-}+mulMM :: (Num a) => Mat2x2 a -> Mat2x2 a -> Mat2x2 a+mulMM (Mat2x2 (!a11, !a12, !a21, !a22)) (Mat2x2 (!b11, !b12, !b21, !b22)) = Mat2x2 (c11, c12, c21, c22)+  where+    !c11 = a11 * b11 + a12 * b21+    !c12 = a11 * b12 + a12 * b22+    !c21 = a21 * b11 + a22 * b21+    !c22 = a21 * b12 + a22 * b22++-- | \(O(1)\) Multiplies `Mat2x2` to `V2`.+--+-- @since 1.1.0.0+{-# INLINE act #-}+act :: (Num a) => Mat2x2 a -> V2 a -> V2 a+act = mulMV++-- | \(O(1)\) Maps the every component of `Mat2x2`.+--+-- @since 1.1.0.0+{-# INLINE map #-}+map :: (a -> b) -> Mat2x2 a -> Mat2x2 b+map f (Mat2x2 (!a11, !a12, !a21, !a22)) = Mat2x2 (a11', a12', a21', a22')+  where+    !a11' = f a11+    !a12' = f a12+    !a21' = f a21+    !a22' = f a22++-- | \(O(1)\) Returns the determinan of the matrix.+--+-- @since 1.1.0.0+{-# INLINE det #-}+det :: (Fractional e) => Mat2x2 e -> e+det (Mat2x2 (!a, !b, !c, !d)) = a * d - b * c++-- | \(O(1)\) Returns the inverse matrix, based on `Fractional` instance (mainly for @ModInt@).+--+-- ==== Constraints+-- - The determinant (`det`) of the matrix must be non-zero, otherwise an error is thrown.+--+-- @since 1.1.0.0+{-# INLINE inv #-}+inv :: (HasCallStack, Fractional e, Eq e) => Mat2x2 e -> Mat2x2 e+inv (Mat2x2 (!a, !b, !c, !d)) = Mat2x2 (a', b', c', d')+  where+    -- NOTE: zero division+    -- !r = recip $ a * d - b * c+    !r+      | det_ == 0 = error "AtCoder.Extra.Mat2x2.inv: the determinant of the matrix must be non zero"+      | otherwise = recip det_+      where+        !det_ = a * d - b * c+    !a' = r * d+    !b' = r * (-b)+    !c' = r * (-c)+    !d' = r * a++-- | @since 1.1.0.0+instance (Num a) => Semigroup (Mat2x2 a) where+  {-# INLINE (<>) #-}+  (<>) = mulMM+  {-# INLINE stimes #-}+  stimes = ACEM.stimes' . fromIntegral++-- | @since 1.1.0.0+instance (Num a) => Monoid (Mat2x2 a) where+  {-# INLINE mempty #-}+  mempty = ident++-- | @since 1.1.0.0+instance (Num a) => SegAct (Mat2x2 a) (V2 a) where+  {-# INLINE segAct #-}+  segAct = mulMV++-- | @since 1.1.0.0+instance (Num a) => SegAct (Dual (Mat2x2 a)) (V2 a) where+  {-# INLINE segAct #-}+  segAct (Dual f) = mulMV f++-- | @since 1.1.0.0+newtype instance VU.MVector s (Mat2x2 a) = MV_Mat2x2 (VU.MVector s (Mat2x2Repr a))++-- | @since 1.1.0.0+newtype instance VU.Vector (Mat2x2 a) = V_Mat2x2 (VU.Vector (Mat2x2Repr a))++-- | @since 1.1.0.0+deriving instance (VU.Unbox a) => VGM.MVector VUM.MVector (Mat2x2 a)++-- | @since 1.1.0.0+deriving instance (VU.Unbox a) => VG.Vector VU.Vector (Mat2x2 a)++-- | @since 1.1.0.0+instance (VU.Unbox a) => VU.Unbox (Mat2x2 a)
src/AtCoder/Extra/Monoid/RangeAdd.hs view
@@ -1,6 +1,6 @@ {-# LANGUAGE TypeFamilies #-} --- | Range add monoid action for \([l, r)\) intervals.+-- | Monoid action \(f: x \rightarrow x + d\). -- -- @since 1.0.0.0 module AtCoder.Extra.Monoid.RangeAdd@@ -9,27 +9,28 @@      -- * Constructor     new,+    unRangeAdd, -    -- * Action+    -- * Actions     act,   ) where  import AtCoder.LazySegTree (SegAct (..))-import Data.Semigroup (Sum (..))+import Data.Semigroup (stimes, Sum (..), Max(..), Min(..)) import Data.Vector.Generic qualified as VG import Data.Vector.Generic.Mutable qualified as VGM import Data.Vector.Unboxed qualified as VU import Data.Vector.Unboxed.Mutable qualified as VUM --- | Range add monoid action.+-- | Monoid action \(f: x \rightarrow x + d\). ----- ==== Example+-- ==== __Example__ -- >>> import AtCoder.Extra.Monoid (SegAct(..), RangeAdd(..)) -- >>> import AtCoder.LazySegTree qualified as LST -- >>> import Data.Semigroup (Max(..))--- >>> seg <- LST.build @_ @(RangeAdd Int) @(Sum Int) $ VU.generate 3 Sum -- [0, 1, 2]--- >>> LST.applyIn seg 0 3 $ RangeAdd 5 -- [5, 6, 7]+-- >>> seg <- LST.build @_ @(RangeAdd (Sum Int)) @(Sum Int) $ VU.generate 3 Sum -- [0, 1, 2]+-- >>> LST.applyIn seg 0 3 $ RangeAdd (Sum 5) -- [5, 6, 7] -- >>> getSum <$> LST.prod seg 0 3 -- 18 --@@ -51,36 +52,51 @@ new :: a -> RangeAdd a new = RangeAdd --- | Applies one-length range add: \(f: x \rightarrow d + x\).+-- | \(O(1)\) Retrieves the internal value of `RangeAdd`. --+-- @since 1.1.0.0+{-# INLINE unRangeAdd #-}+unRangeAdd :: RangeAdd a -> a+unRangeAdd (RangeAdd a) = a++-- | \(O(1)\) Applies one-length range add: \(f: x \rightarrow d + x\).+-- -- @since 1.0.0.0 {-# INLINE act #-}-act :: (Num a) => RangeAdd a -> a -> a-act (RangeAdd dx) x = dx + x+act :: (Semigroup a) => RangeAdd a -> a -> a+act (RangeAdd dx) x = dx <> x --- | Acts on @a@ with length in terms of `SegAct`.+-- | \(O(1)\) Acts on @a@ with length in terms of `SegAct`. -- -- @since 1.0.0.0 {-# INLINE actWithLength #-}-actWithLength :: (Num a) => Int -> RangeAdd a -> a -> a-actWithLength len (RangeAdd f) x = fromIntegral len * f + x+actWithLength :: (Semigroup a) => Int -> RangeAdd a -> a -> a+actWithLength len (RangeAdd f) x = stimes len f <> x  -- | @since 1.0.0.0-instance (Num a) => Semigroup (RangeAdd a) where+instance (Semigroup a) => Semigroup (RangeAdd a) where   {-# INLINE (<>) #-}-  (RangeAdd a) <> (RangeAdd b) = RangeAdd $! a + b+  (RangeAdd a) <> (RangeAdd b) = RangeAdd $! a <> b --- | @since 1.0.0.0-instance (Num a) => Monoid (RangeAdd a) where+-- | @since 1.1.0.0+instance (Monoid a) => Monoid (RangeAdd a) where   {-# INLINE mempty #-}-  mempty = RangeAdd 0+  mempty = RangeAdd mempty --- | @since 1.0.0.0-instance (Num a) => SegAct (RangeAdd a) (Sum a) where+-- | @since 1.1.0.0+instance (Monoid (Sum a)) => SegAct (RangeAdd (Sum a)) (Sum a) where   {-# INLINE segActWithLength #-}-  segActWithLength len a (Sum x) = Sum $! actWithLength len a x+  segActWithLength len f x = actWithLength len f x --- not works as SegAct for Product, Min, and Max.+-- | @since 1.1.0.0+instance (Monoid (Max a)) => SegAct (RangeAdd (Max a)) (Max a) where+  {-# INLINE segActWithLength #-}+  segActWithLength len f x = actWithLength len f x++-- | @since 1.1.0.0+instance (Monoid (Min a)) => SegAct (RangeAdd (Min a)) (Min a) where+  {-# INLINE segActWithLength #-}+  segActWithLength len f x = actWithLength len f x  -- | @since 1.0.0.0 newtype instance VU.MVector s (RangeAdd a) = MV_RangeAdd (VU.MVector s a)
− src/AtCoder/Extra/Monoid/RangeAddId.hs
@@ -1,95 +0,0 @@-{-# LANGUAGE TypeFamilies #-}---- | Range add monoid action for \([l, r)\) intervals. Works on ideomponent monoids such as `Max`--- or `Min` only.------ @since 1.0.0.0-module AtCoder.Extra.Monoid.RangeAddId-  ( -- * RangeAddId-    RangeAddId (..),-    -- * Constructor-    new,-    -- * Action-    act,-  )-where--import AtCoder.LazySegTree (SegAct (..))-import Data.Semigroup (Max (..), Min (..))-import Data.Vector.Generic qualified as VG-import Data.Vector.Generic.Mutable qualified as VGM-import Data.Vector.Unboxed qualified as VU-import Data.Vector.Unboxed.Mutable qualified as VUM---- | Range add monoid action.------ ==== Example--- >>> import AtCoder.Extra.Monoid (SegAct(..), RangeAddId(..))--- >>> import AtCoder.LazySegTree qualified as LST--- >>> import Data.Semigroup (Max(..))--- >>> seg <- LST.build @_ @(RangeAddId Int) @(Max Int) $ VU.generate 3 Max -- [0, 1, 2]--- >>> LST.applyIn seg 0 3 $ RangeAddId 5 -- [5, 6, 7]--- >>> getMax <$> LST.prod seg 0 3--- 7------ @since 1.0.0.0-newtype RangeAddId a = RangeAddId a-  deriving newtype-    ( -- | @since 1.0.0.0-      Eq,-      -- | @since 1.0.0.0-      Ord,-      -- | @since 1.0.0.0-      Show-    )---- | Creates `RangeAddId`.------ @since 1.0.0.0-{-# INLINE new #-}-new :: a -> RangeAddId a-new = RangeAddId---- | Applies one-length range add: \(f: x \rightarrow d + x\).------ @since 1.0.0.0-{-# INLINE act #-}-act :: (Num a) => RangeAddId a -> a -> a-act (RangeAddId f) x = f + x---- | @since 1.0.0.0-instance (Num a) => Semigroup (RangeAddId a) where-  {-# INLINE (<>) #-}-  (RangeAddId a) <> (RangeAddId b) = RangeAddId $! a + b---- | @since 1.0.0.0-instance (Num a) => Monoid (RangeAddId a) where-  {-# INLINE mempty #-}-  mempty = RangeAddId 0---- | @since 1.0.0.0-instance (Num a) => SegAct (RangeAddId a) (Max a) where-  {-# INLINE segAct #-}-  segAct f (Max x) = Max $! act f x---- | @since 1.0.0.0-instance (Num a) => SegAct (RangeAddId a) (Min a) where-  {-# INLINE segAct #-}-  segAct f (Min x) = Min $! act f x---- not works as SegAct for Sum and Product.---- | @since 1.0.0.0-newtype instance VU.MVector s (RangeAddId a) = MV_RangeAddId (VU.MVector s a)---- | @since 1.0.0.0-newtype instance VU.Vector (RangeAddId a) = V_RangeAddId (VU.Vector a)---- | @since 1.0.0.0-deriving instance (VU.Unbox a) => VGM.MVector VUM.MVector (RangeAddId a)---- | @since 1.0.0.0-deriving instance (VU.Unbox a) => VG.Vector VU.Vector (RangeAddId a)---- | @since 1.0.0.0-instance (VU.Unbox a) => VU.Unbox (RangeAddId a)
src/AtCoder/Extra/Monoid/RangeSet.hs view
@@ -1,21 +1,22 @@ {-# LANGUAGE TypeFamilies #-} --- | Range set monoid action for \([l, r)\) intervals.+-- | Monoid action \(f: x \rightarrow a\). -- -- @since 1.0.0.0 module AtCoder.Extra.Monoid.RangeSet   ( -- * RangeSet     RangeSet (..),+    RangeSetRepr, -    -- * Constructor+    -- * Constructors     new,+    unRangeSet, -    -- * Action+    -- * Actions     act,   ) where -import AtCoder.Extra.Math qualified as ACEM import AtCoder.LazySegTree (SegAct (..)) import Data.Bit (Bit (..)) import Data.Semigroup (stimes)@@ -24,9 +25,9 @@ import Data.Vector.Unboxed qualified as VU import Data.Vector.Unboxed.Mutable qualified as VUM --- | Range set monoid action.+-- | Monoid action \(f: x \rightarrow a\). ----- ==== Example+-- ==== __Example__ -- >>> import AtCoder.Extra.Monoid (SegAct(..), RangeSet(..)) -- >>> import AtCoder.LazySegTree qualified as LST -- >>> import Data.Bit (Bit (..))@@ -51,18 +52,25 @@ -- Tuples are not the fastest representation, but it's easier to implement -- `Data.Vector.Unboxed.Unbox`. ----- @since 1.0.0.0+-- @since 1.1.0.0 type RangeSetRepr a = (Bit, a) --- | Creates a new `RangeSet` action.+-- | \(O(1)\) Creates a new `RangeSet` action. -- -- @since 1.0.0.0 {-# INLINE new #-} new :: a -> RangeSet a new = RangeSet . (Bit True,) --- | Applies one-length range set: \(f: x \rightarrow y\).+-- | \(O(1)\) Retrieves the internal representation of `RangeSet`. --+-- @since 1.1.0.0+{-# INLINE unRangeSet #-}+unRangeSet :: RangeSet a -> RangeSetRepr a+unRangeSet (RangeSet a) = a++-- | \(O(1)\) Applies one-length range set: \(f: x \rightarrow y\).+-- -- @since 1.0.0.0 {-# INLINE act #-} act :: RangeSet a -> a -> a@@ -74,7 +82,7 @@ -- @since 1.0.0.0 {-# INLINE actWithLength #-} actWithLength :: (Semigroup a) => Int -> RangeSet a -> a -> a-actWithLength len (RangeSet (Bit True, !f)) _ = ACEM.power (<>) len f+actWithLength len (RangeSet (Bit True, !f)) _ = stimes len f actWithLength _ (RangeSet (Bit False, !_)) x = x  -- | @since 1.0.0.0
− src/AtCoder/Extra/Monoid/RangeSetId.hs
@@ -1,124 +0,0 @@-{-# LANGUAGE TypeFamilies #-}---- | Range set monoid action for \([l, r)\) intervals. Works on ideomponent monoids such as `Max`--- or `Min` only.--------- @since 1.0.0.0-module AtCoder.Extra.Monoid.RangeSetId-  ( -- * RangeSetId-    RangeSetId (..),--    -- * Constructor-    new,--    -- * Action-    act,-  )-where--import AtCoder.LazySegTree (SegAct (..))-import Data.Bit (Bit (..))-import Data.Semigroup (Max (..), Min (..), stimes)-import Data.Vector.Generic qualified as VG-import Data.Vector.Generic.Mutable qualified as VGM-import Data.Vector.Unboxed qualified as VU-import Data.Vector.Unboxed.Mutable qualified as VUM---- | Range set monoid action.------ ==== Example--- >>> import AtCoder.Extra.Monoid (SegAct(..), RangeSetId(..))--- >>> import AtCoder.LazySegTree qualified as LST--- >>> import Data.Bit (Bit (..))--- >>> import Data.Semigroup (Max(..))--- >>> seg <- LST.build @_ @(RangeSetId (Max Int)) @(Max Int) $ VU.generate 3 (Max . (+ 10)) -- [10, 11, 12]--- >>> LST.applyIn seg 0 2 $ RangeSetId (Bit True, Max 5) -- [5, 5, 12]--- >>> getMax <$> LST.prod seg 0 3--- 12------ @since 1.0.0.0-newtype RangeSetId a = RangeSetId (RangeSetIdRepr a)-  deriving newtype-    ( -- | @since 1.0.0.0-      Eq,-      -- | @since 1.0.0.0-      Ord,-      -- | @since 1.0.0.0-      Show-    )---- | `RangeSetId` internal representation. The first value represents if it is an identity action.--- Tuples are not the fastest representation, but it's easier to implement--- `Data.Vector.Unboxed.Unbox`.------ @since 1.0.0.0-type RangeSetIdRepr a = (Bit, a)---- | Creates a new `RangeSet` action.------ @since 1.0.0.0-{-# INLINE new #-}-new :: a -> RangeSetId a-new = RangeSetId . (Bit True,)---- | Applies one-length range set: \(f: x \rightarrow y\).------ @since 1.0.0.0-{-# INLINE act #-}-act :: RangeSetId a -> a -> a-act (RangeSetId (Bit True, !f)) _ = f-act (RangeSetId (Bit False, !_)) x = x---- segActWithLength works for ideomponent monoids only.---- | @since 1.0.0.0-instance Semigroup (RangeSetId a) where-  {-# INLINE (<>) #-}-  RangeSetId (Bit False, !_) <> old = old-  new_ <> _ = new_-  {-# INLINE stimes #-}-  stimes _ x = x---- The `Monoid` constraint is just for their default value.---- | @since 1.0.0.0-instance (Monoid a) => Monoid (RangeSetId a) where-  {-# INLINE mempty #-}-  mempty = RangeSetId (Bit False, mempty)-  {-# INLINE mconcat #-}-  -- find the first non-mempty-  mconcat [] = mempty-  mconcat (RangeSetId (Bit False, !_) : as) = mconcat as-  mconcat (a : _) = a---- The target is limited to ideomponent monoids. The `Monoid` constraint is just for their default--- value.---- | @since 1.0.0.0-instance (Ord a, Bounded a) => SegAct (RangeSetId (Max a)) (Max a) where-  {-# INLINE segAct #-}-  segAct = act---- The target is limited to ideomponent monoids. The `Monoid` constraint is just for their default--- value.---- | @since 1.0.0.0-instance (Ord a, Bounded a) => SegAct (RangeSetId (Min a)) (Min a) where-  {-# INLINE segAct #-}-  segAct = act---- | @since 1.0.0.0-newtype instance VU.MVector s (RangeSetId a) = MV_RangeSetId (VU.MVector s (RangeSetIdRepr a))---- | @since 1.0.0.0-newtype instance VU.Vector (RangeSetId a) = V_RangeSetId (VU.Vector (RangeSetIdRepr a))---- | @since 1.0.0.0-deriving instance (VU.Unbox a) => VGM.MVector VUM.MVector (RangeSetId a)---- | @since 1.0.0.0-deriving instance (VU.Unbox a) => VG.Vector VU.Vector (RangeSetId a)---- | @since 1.0.0.0-instance (VU.Unbox a) => VU.Unbox (RangeSetId a)
+ src/AtCoder/Extra/Monoid/RollingHash.hs view
@@ -0,0 +1,121 @@+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE DerivingVia #-}+{-# LANGUAGE MagicHash #-}+{-# LANGUAGE StandaloneDeriving #-}+{-# LANGUAGE TypeFamilies #-}++-- | Rolling hash algorithm implemented as a monoid, typically stored in a segment tree. The type+-- parameters \(b\) and \(p\) represent the B-adic base and the modulus, respectively.+--+-- Combining `RollingHash` with `SegTree` enables \(O(\log |s|)\) string slice creation and+-- \(O(1)\) slice comparison.+--+-- @since 1.1.0.0+module AtCoder.Extra.Monoid.RollingHash+  ( -- * Rolling hash+    RollingHash (..),++    -- * Constructors+    new,+    unsafeNew,+  )+where++import Data.Vector.Generic qualified as VG+import Data.Vector.Generic.Mutable qualified as VGM+import Data.Vector.Unboxed qualified as VU+import Data.Vector.Unboxed.Mutable qualified as VUM+import GHC.Exts (proxy#)+import GHC.TypeNats (KnownNat, natVal')++-- | Rolling hash algorithm implemented as a monoid, typically stored in a segment tree. The type+-- parameters \(b\) and \(p\) represent the B-adic base and the modulus, respectively.+--+-- Combining `RollingHash` with `SegTree` enables \(O(\log |s|)\) string slice creation and+-- \(O(1)\) slice comparison.+--+--+-- ==== __Example__+-- It's convenient to define a type alias of `RollingHash`:+--+-- >>> import AtCoder.Extra.Monoid.RollingHash qualified as RH+-- >>> import AtCoder.SegTree qualified as ST+-- >>> import Data.Char (ord)+-- >>> import Data.Semigroup (Dual (..))+-- >>> type RH = RH.RollingHash 100 998244353+--+-- Let's test whether "abcba" is a palindrome:+--+-- >>> seg <- ST.build @_ @RH . VU.map (RH.unsafeNew . ord) $ VU.fromList "abcba"+-- >>> seg' <- ST.build @_ @(Dual RH) . VU.map (Dual . RH.unsafeNew . ord) $ VU.fromList "abcba"+-- >>> hash1 <- ST.prod seg 2 5       --   cba  (left to right)+-- >>> Dual hash2 <- ST.prod seg' 0 3 -- abc    (right to lett)+-- >>> hash1 == hash2+-- True+--+-- @since 1.1.0.0+data RollingHash b p = RollingHash+  { -- | The hash value.+    hashRH :: {-# UNPACK #-} !Int,+    -- | \(b^{\mathrm{length}} \bmod p\).+    nextDigitRH :: {-# UNPACK #-} !Int+  }+  deriving+    ( -- | @since 1.1.0.0+      Eq,+      -- | @since 1.1.0.0+      Show+    )++-- | \(O(1)\) Creates a one-length `RollingHash` from an integer.+--+-- @since 1.1.0.0+{-# INLINE new #-}+new :: forall b p. (KnownNat b, KnownNat p) => Int -> RollingHash b p+new h = RollingHash (h `mod` fromIntegral (natVal' (proxy# @p))) (fromIntegral (natVal' (proxy# @b)))++-- | \(O(1)\) Creates a one-length `RollingHash` from an integer without taking the mod.+--+-- @since 1.1.0.0+{-# INLINE unsafeNew #-}+unsafeNew :: forall b p. (KnownNat b, KnownNat p) => Int -> RollingHash b p+unsafeNew h = RollingHash h (fromIntegral (natVal' (proxy# @b)))++-- | @since 1.1.0.0+instance (KnownNat b, KnownNat p) => Semigroup (RollingHash b p) where+  -- \| \(O(1)\)+  {-# INLINE (<>) #-}+  (RollingHash !digit1 !hash1) <> (RollingHash !digit2 !hash2) = RollingHash digit' hash'+    where+      !p = fromIntegral $ natVal' (proxy# @p)+      !digit' = digit1 * digit2 `mod` p+      !hash' = (hash1 * digit2 + hash2) `mod` p++-- | @since 1.1.0.0+instance (KnownNat b, KnownNat p) => Monoid (RollingHash b p) where+  {-# INLINE mempty #-}+  mempty = RollingHash 1 0++type RHRepr = (Int, Int)++-- | @since 1.1.0.0+instance VU.IsoUnbox (RollingHash b p) RHRepr where+  {-# INLINE toURepr #-}+  toURepr (RollingHash a b) = (a, b)+  {-# INLINE fromURepr #-}+  fromURepr (!a, !b) = RollingHash a b++-- | @since 1.1.0.0+newtype instance VU.MVector s (RollingHash b p) = MV_RH (VUM.MVector s RHRepr)++-- | @since 1.1.0.0+newtype instance VU.Vector (RollingHash b p) = V_RH (VU.Vector RHRepr)++-- | @since 1.1.0.0+deriving via (RollingHash b p `VU.As` RHRepr) instance VGM.MVector VUM.MVector (RollingHash b p)++-- | @since 1.1.0.0+deriving via (RollingHash b p `VU.As` RHRepr) instance VG.Vector VU.Vector (RollingHash b p)++-- | @since 1.1.0.0+instance VU.Unbox (RollingHash b p)
+ src/AtCoder/Extra/Monoid/V2.hs view
@@ -0,0 +1,81 @@+{-# LANGUAGE TypeFamilies #-}++-- | A monoid acted on by `Mat2x2`, an affine transformation target.+--+-- @since 1.1.0.0+module AtCoder.Extra.Monoid.V2+  ( -- * V2+    V2 (..),+    V2Repr,++    -- * Constructor+    new,+    unV2,+  )+where++import Data.Vector.Generic qualified as VG+import Data.Vector.Generic.Mutable qualified as VGM+import Data.Vector.Unboxed qualified as VU+import Data.Vector.Unboxed.Mutable qualified as VUM++-- | A monoid acted on by `Mat2x2`, an affine transformation target.+--+-- @since 1.1.0.0+newtype V2 a = V2 (V2Repr a)+  deriving newtype+    ( -- | @since 1.1.0.0+      Eq,+      -- | @since 1.1.0.0+      Ord,+      -- | @since 1.1.0.0+      Show+    )++-- | `V2` internal representation. Tuples are not the fastest representation, but it's easier+-- to implement `Data.Vector.Unboxed.Unbox`.+--+-- @since 1.1.0.0+type V2Repr a = (a, a)++-- | \(O(1)\) Creates `V2` of length \(1\).+--+-- @since 1.1.0.0+{-# INLINE new #-}+new :: (Num a) => a -> V2 a+new !a = V2 (a, 1)++-- | \(O(1)\) Retrieves the value of `V2`, discarding the length information.+--+-- @since 1.1.0.0+{-# INLINE unV2 #-}+unV2 :: V2 a -> a+unV2 (V2 (!a, !_)) = a++-- | @since 1.1.0.0+instance (Num a) => Semigroup (V2 a) where+  {-# INLINE (<>) #-}+  (V2 (!a1, !a2)) <> (V2 (!b1, !b2)) = V2 (a', b')+    where+      !a' = a1 + b1+      !b' = a2 + b2++-- | @since 1.1.0.0+instance (Num a) => Monoid (V2 a) where+  {-# INLINE mempty #-}+  mempty = V2 (0, 0)++-- | @since 1.1.0.0+newtype instance VU.MVector s (V2 a) = MV_V2 (VU.MVector s (V2Repr a))++-- | @since 1.1.0.0+newtype instance VU.Vector (V2 a) = V_V2 (VU.Vector (V2Repr a))++-- | @since 1.1.0.0+deriving instance (VU.Unbox a) => VGM.MVector VUM.MVector (V2 a)++-- | @since 1.1.0.0+deriving instance (VU.Unbox a) => VG.Vector VU.Vector (V2 a)++-- | @since 1.1.0.0+instance (VU.Unbox a) => VU.Unbox (V2 a)
+ src/AtCoder/Extra/MultiSet.hs view
@@ -0,0 +1,280 @@+{-# LANGUAGE RecordWildCards #-}++-- | A fast, mutable multiset for `Int` keys backed by a @HashMap@.  Most operations are performed+-- in \(O(1)\) time, but in average.+--+-- ==== Invariant+-- The count for each key must be non-negative. An exception is thrown if this invariant is+-- violated.+--+-- ==== Capacity limitation+-- The maximum number of distinct keys that can be inserted is fixed at \(n\), even if some keys are+-- deleted. This is due to the limitation of the internal @HashMap@.+--+-- ==== __Example__+-- Create a `MultiSet` with capacity \(4\):+--+-- >>> import AtCoder.Extra.MultiSet qualified as MS+-- >>> ms <- MS.new 4+--+-- `inc` and `dec` are the primary API:+--+-- >>> MS.inc ms 10+-- >>> MS.inc ms 10+-- >>> MS.lookup ms 10+-- Just 2+--+-- >>> MS.dec ms 10+-- >>> MS.lookup ms 10+-- Just 1+--+-- Entries with zero count are considered to be non-existing:+--+-- >>> MS.dec ms 10+-- >>> MS.member ms 10+-- False+--+-- >>> MS.lookup ms 10+-- Nothing+--+-- >>> MS.size ms+-- 0+--+-- Creating a negative count results in an exception:+--+-- >>> MS.inc ms 11+-- >>> MS.sub ms 11 2+-- *** Exception: AtCoder.Extra.Multiset.sub: the count of `11` is becoming a negative value: `-1`+-- ...+--+-- Decrementing a non-existing key does nothing and does not throw an exception:+--+-- >>> MS.dec ms 12+--+-- Misc:+--+-- >>> MS.insert ms 12 112+-- >>> MS.assocs ms+-- [(11,1),(12,112)]+--+-- @since 1.1.0.0+module AtCoder.Extra.MultiSet+  ( -- * MultiSet+    MultiSet,++    -- * Construtors+    new,++    -- * Metadata+    capacity,+    size,++    -- * Lookups+    lookup,+    member,+    notMember,++    -- * Modifications+    inc,+    dec,+    add,+    sub,+    insert,+    delete,++    -- * Conversions++    -- ** Safe conversions+    keys,+    elems,+    assocs,++    -- ** Unsafe conversions+    unsafeKeys,+    unsafeElems,+    unsafeAssocs,+  )+where++import AtCoder.Extra.HashMap qualified as HM+import Control.Monad (when)+import Control.Monad.Primitive (PrimMonad, PrimState)+import Data.Functor ((<&>))+import Data.Vector.Generic.Mutable qualified as VGM+import Data.Vector.Unboxed qualified as VU+import Data.Vector.Unboxed.Mutable qualified as VUM+import GHC.Stack (HasCallStack)+import Prelude hiding (lookup)++-- | A fast, mutable multiset for `Int` keys backed by a @HashMap@.+--+-- @since 1.1.0.0+data MultiSet s = MultiSet+  { mapMS :: !(HM.HashMap s Int),+    cntMS :: !(VUM.MVector s Int)+  }++-- | \(O(n)\) Creates a `MultiSet` with capacity \(n\).+--+-- @since 1.1.0.0+new :: (PrimMonad m) => Int -> m (MultiSet (PrimState m))+new n = do+  mapMS <- HM.new n+  cntMS <- VUM.replicate 1 0+  pure $ MultiSet {..}++-- | \(O(1)\) Returns the maximum number of distinct keys that can be inserted into the internal+-- hash map.+--+-- @since 1.1.0.0+capacity :: MultiSet s -> Int+capacity = HM.capacity . mapMS++-- | \(O(1)\) Returns the number of distinct keys with positive counts.+--+-- @since 1.1.0.0+size :: (PrimMonad m) => MultiSet (PrimState m) -> m Int+size MultiSet {..} = do+  VGM.unsafeRead cntMS 0++-- | \(O(1)\) Looks up the count for a key.+--+-- @since 1.1.0.0+lookup :: (PrimMonad m) => MultiSet (PrimState m) -> Int -> m (Maybe Int)+lookup MultiSet {..} k = do+  HM.lookup mapMS k <&> \case+    Just i | i > 0 -> Just i+    _ -> Nothing++-- | \(O(1)\) Tests whether \(k\) is in the set.+--+-- @since 1.1.0.0+member :: (PrimMonad m) => MultiSet (PrimState m) -> Int -> m Bool+member MultiSet {..} k = do+  HM.lookup mapMS k <&> \case+    Just i -> i > 0+    _ -> False++-- | \(O(1)\) Tests whether \(k\) is not in the set.+--+-- @since 1.1.0.0+notMember :: (PrimMonad m) => MultiSet (PrimState m) -> Int -> m Bool+notMember ms k = not <$> member ms k++-- | \(O(1)\) Increments the count of a key.+--+-- @since 1.1.0.0+inc :: (HasCallStack, PrimMonad m) => MultiSet (PrimState m) -> Int -> m ()+inc ms k = add ms k 1++-- | \(O(1)\) Decrements the count of a key.+--+-- @since 1.1.0.0+dec :: (HasCallStack, PrimMonad m) => MultiSet (PrimState m) -> Int -> m ()+dec ms k = sub ms k 1++-- | \(O(1)\) Increments the count of a key \(k\) by \(c\). If the key does not exist in the set,+-- the \((k, c)\) pair is inserted. If \(v\) is negative, it falls back to `sub`.+--+-- @since 1.1.0.0+add :: (HasCallStack, PrimMonad m) => MultiSet (PrimState m) -> Int -> Int -> m ()+add ms@MultiSet {..} k v = case compare v 0 of+  LT -> sub ms k (-v)+  EQ -> pure ()+  GT -> do+    HM.lookup mapMS k >>= \case+      Just n ->  do+        HM.insert mapMS k $ n + v+        when (n <= 0) $ do+          VGM.unsafeModify cntMS (+ 1) 0+      Nothing -> do+        HM.insert mapMS k v+        VGM.unsafeModify cntMS (+ 1) 0++-- | \(O(1)\) Decrements the count of a key \(k\) by \(c\). If \(c\) is negative, it falls back to+-- `add`.+--+-- @since 1.1.0.0+sub :: (HasCallStack, PrimMonad m) => MultiSet (PrimState m) -> Int -> Int -> m ()+sub ms@MultiSet {..} k v = case compare v 0 of+  LT -> add ms k (-v)+  EQ -> pure ()+  GT -> do+    HM.lookup mapMS k >>= \case+      Just 0 -> pure () -- ignored+      Just n -> case compare n v of+        GT -> do+          HM.insert mapMS k (n - v)+        EQ -> do+          HM.insert mapMS k 0+          VGM.unsafeModify cntMS (subtract 1) 0+        LT -> error $ "AtCoder.Extra.Multiset.sub: the count of `" ++ show k ++ "` is becoming a negative value: `" ++ show (n - v) ++ "`"+      _ -> pure ()++-- | \(O(1)\) Inserts a key-count pair into the set. `MultiSet` is actually a count map.+--+-- @since 1.1.0.0+insert :: (HasCallStack, PrimMonad m) => MultiSet (PrimState m) -> Int -> Int -> m ()+insert MultiSet {..} k v+  | v <= 0 = error $ "AtCoder.Extra.Multiset.insert: new count must be positive`" ++ show k ++ "`: `" ++ show v ++ "`"+  | otherwise = do+      HM.lookup mapMS k >>= \case+        Just n | n > 0 -> do+          HM.insert mapMS k v+        _ -> do+          HM.insert mapMS k v+          VGM.unsafeModify cntMS (+ 1) 0++-- | \(O(1)\) Deletes a key. Note that it does not undo its insertion and does not increase the+-- number of distinct keys that can be inserted into the internal hash map.+--+-- @since 1.1.0.0+delete :: (HasCallStack, PrimMonad m) => MultiSet (PrimState m) -> Int -> m ()+delete MultiSet {..} k = do+  HM.lookup mapMS k >>= \case+    Just i | i > 0 -> do+      HM.insert mapMS k 0+      VGM.unsafeModify cntMS (subtract 1) 0+    _ -> pure ()++-- | \(O(n)\) Enumerates the keys in the set.+--+-- @since 1.1.0.0+{-# INLINE keys #-}+keys :: (PrimMonad m) => MultiSet (PrimState m) -> m (VU.Vector Int)+keys ms = VU.force <$> unsafeKeys ms++-- | \(O(n)\) Enumerates the counts in the set.+--+-- @since 1.1.0.0+{-# INLINE elems #-}+elems :: (PrimMonad m) => MultiSet (PrimState m) -> m (VU.Vector Int)+elems ms = VU.force <$> unsafeElems ms++-- | \(O(n)\) Enumerates the key-count pairs in the set.+--+-- @since 1.1.0.0+{-# INLINE assocs #-}+assocs :: (PrimMonad m) => MultiSet (PrimState m) -> m (VU.Vector (Int, Int))+assocs ms = VU.force <$> unsafeAssocs ms++-- | \(O(n)\) Enumerates the keys in the set.+--+-- @since 1.1.0.0+{-# INLINE unsafeKeys #-}+unsafeKeys :: (PrimMonad m) => MultiSet (PrimState m) -> m (VU.Vector Int)+unsafeKeys = (VU.mapMaybe (\(!k, !n) -> if n > 0 then Just k else Nothing) <$>) . HM.unsafeAssocs . mapMS++-- | \(O(n)\) Enumerates the counts in the set.+--+-- @since 1.1.0.0+{-# INLINE unsafeElems #-}+unsafeElems :: (PrimMonad m) => MultiSet (PrimState m) -> m (VU.Vector Int)+unsafeElems = (VU.filter (> 0) <$>) . HM.unsafeElems . mapMS++-- | \(O(n)\) Enumerates the key-count pairs in the set.+--+-- @since 1.1.0.0+{-# INLINE unsafeAssocs #-}+unsafeAssocs :: (PrimMonad m) => MultiSet (PrimState m) -> m (VU.Vector (Int, Int))+unsafeAssocs = (VU.filter (\(!_, !n) -> n > 0) <$>) . HM.unsafeAssocs . mapMS
+ src/AtCoder/Extra/Pdsu.hs view
@@ -0,0 +1,306 @@+{-# LANGUAGE RecordWildCards #-}++-- original implementation:+-- <https://qiita.com/drken/items/cce6fc5c579051e64fab>++-- | A potentialized disjoint set union on a [group](https://en.wikipedia.org/wiki/Group_(mathematics\))+-- under a differential constraint system. Each vertex \(v\) is assigned a potential value \(p(v)\),+-- where representatives (`leader`) of each group have a potential of `mempty`, and other vertices have+-- potentials relative to their representative.+--+-- The group type is represented as a `Monoid` with a inverse operator, passed on `new`. This+-- approach avoids defining a separate typeclass for groups.+--+-- ==== Invariant+-- New monoids always come from the left: @new <> old@. The order is important for non-commutative+-- monoid implementations.+--+-- @since 1.1.0.0+module AtCoder.Extra.Pdsu+  ( -- * Pdsu+    Pdsu (nPdsu),++    -- * Constructors+    new,++    -- * Inspection+    leader,+    pot,+    diff,+    unsafeDiff,+    same,+    canMerge,++    -- * Merging+    merge,+    merge_,++    -- * Group information+    size,+    groups,++    -- * Reset+    clear,+  )+where++import AtCoder.Internal.Assert qualified as ACIA+import Control.Monad+import Control.Monad.Primitive (PrimMonad, PrimState)+import Data.Vector qualified as V+import Data.Vector.Generic qualified as VG+import Data.Vector.Generic.Mutable qualified as VGM+import Data.Vector.Unboxed qualified as VU+import Data.Vector.Unboxed.Mutable qualified as VUM+import GHC.Stack (HasCallStack)++-- | A potentialized disjoint set union on a [group](https://en.wikipedia.org/wiki/Group_(mathematics\))+-- under a differential constraint system. Each vertex \(v\) is assigned a potential value \(p(v)\),+--+-- ==== __Example__+-- Create a `Pdsu` with four vertices with potential type @Sum Int@. Use `negate` as the inverse+-- operator:+--+-- >>> import AtCoder.Extra.Pdsu qualified as Pdsu+-- >>> import Data.Semigroup (Sum (..))+-- >>> dsu <- Pdsu.new @_ @(Sum Int) 4 negate+--+-- The API is similar to @Dsu@, but with differential potential values:+--+-- >>> Pdsu.merge dsu 1 0 (Sum 1)  -- p(1) - p(0) := Sum 1+-- True+--+-- >>> Pdsu.merge_ dsu 2 0 (Sum 2) -- p(2) - p(0) := Sum 2+-- >>> Pdsu.leader dsu 0+-- 0+--+-- Potential values can be retrieved with `pot`:+--+-- >>> Pdsu.pot dsu 0+-- Sum {getSum = 0}+--+-- >>> Pdsu.pot dsu 1+-- Sum {getSum = 1}+--+-- >>> Pdsu.pot dsu 2+-- Sum {getSum = 2}+--+-- Difference of potentials in the same group can be retrieved with `diff`:+--+-- >>> Pdsu.diff dsu 2 1+-- Just (Sum {getSum = 1})+--+-- >>> Pdsu.diff dsu 2 3+-- Nothing+--+-- Retrieve group information with `groups`+--+-- >>> Pdsu.groups dsu+-- [[2,1,0],[3]]+--+-- @since 1.1.0.0+data Pdsu s a = Pdsu+  { -- | The number of vertices.+    nPdsu :: {-# UNPACK #-} !Int,+    -- | Parent: non-positive, size: positive+    parentOrSizePdsu :: !(VUM.MVector s Int),+    -- | Diffierencial potential of each vertex.+    potentialPdsu :: !(VUM.MVector s a),+    invertPdsu :: !(a -> a)+  }++-- | \(O(n)\) Creates a new DSU under a differential constraint system.+--+-- @since 1.1.0.0+{-# INLINE new #-}+new ::+  forall m a.+  (PrimMonad m, Monoid a, VU.Unbox a) =>+  -- | The number of vertices+  Int ->+  -- | The inverse operator of the monoid+  (a -> a) ->+  -- | A DSU+  m (Pdsu (PrimState m) a)+new n f = Pdsu n <$> VUM.replicate n (-1 {- size 1 -}) <*> VUM.replicate n (mempty :: a) <*> pure f++-- | \(O(\alpha(n))\) Returns the representative of the connected component that contains the+-- vertex.+--+-- @since 1.1.0.0+{-# INLINE leader #-}+leader :: (HasCallStack, PrimMonad m, Semigroup a, VU.Unbox a) => Pdsu (PrimState m) a -> Int -> m Int+leader Pdsu {..} v0 = inner v0+  where+    !_ = ACIA.checkIndex "AtCoder.Extra.Pdsu.leader" v0 nPdsu+    inner v = do+      p <- VGM.read parentOrSizePdsu v+      if {- size? -} p < 0+        then pure v+        else do+          -- NOTE(perf): Path compression.+          -- Handle the nodes closer to the root first and move them onto just under the root+          !r <- inner p+          when (p /= r) $ do+            !pp <- VGM.read potentialPdsu p+            -- Move `v` to just under the root:+            VGM.write parentOrSizePdsu v {- root -} r+            -- INVARIANT: new coming monoids always come from the left. And we're performing+            -- reverse folding.+            VGM.modify potentialPdsu (<> pp) v+          pure r++-- | \(O(\alpha(n))\) Returns \(p(v)\), the potential value of vertex \(v\) relative to the+-- reprensetative of its group.+--+-- @since 1.1.0.0+{-# INLINE pot #-}+pot :: (HasCallStack, PrimMonad m, Semigroup a, VU.Unbox a) => Pdsu (PrimState m) a -> Int -> m a+pot dsu@Pdsu {..} v1 = do+  -- Perform path compression+  _ <- leader dsu v1+  VGM.read potentialPdsu v1+  where+    !_ = ACIA.checkIndex "AtCoder.Extra.Pdsu.pot" v1 nPdsu++-- | \(O(\alpha(n))\) Returns whether the vertices \(a\) and \(b\) are in the same connected+-- component.+--+-- @since 1.1.0.0+{-# INLINE same #-}+same :: (HasCallStack, PrimMonad m, Semigroup a, VU.Unbox a) => Pdsu (PrimState m) a -> Int -> Int -> m Bool+same !dsu !v1 !v2 = (==) <$> leader dsu v1 <*> leader dsu v2++-- TODO: call it unsafeDiff++-- | \(O(\alpha(n))\) Returns the potential of \(v_1\) relative to \(v_2\): \(p(v_1) \cdot p^{-1}(v_2)\)+-- if the two vertices belong to the same group. Returns `Nothing` when the two vertices are not+-- connected.+--+-- @since 1.1.0.0+{-# INLINE diff #-}+diff :: (HasCallStack, PrimMonad m, Monoid a, VU.Unbox a) => Pdsu (PrimState m) a -> Int -> Int -> m (Maybe a)+diff !dsu !v1 !v2 = do+  b <- same dsu v1 v2+  if b+    then Just <$> unsafeDiff dsu v1 v2+    else pure Nothing++-- | \(O(\alpha(n))\) Returns the potential of \(v_1\) relative to \(v_2\): \(p(v_1) \cdot p^{-1}(v_2)\)+-- if the two vertices belong to the same group. Returns meaningless value if the two vertices are+-- not connected.+--+-- @since 1.1.0.0+{-# INLINE unsafeDiff #-}+unsafeDiff :: (HasCallStack, PrimMonad m, Monoid a, VU.Unbox a) => Pdsu (PrimState m) a -> Int -> Int -> m a+unsafeDiff !dsu !v1 !v2 = do+  p1 <- pot dsu v1+  p2 <- pot dsu v2+  pure $ p1 <> invertPdsu dsu p2++-- | \(O(\alpha(n))\) Merges \(v_1\) to \(v_2\) with differential (relative) potential+-- \(\mathrm{dp}\): \(p(v1) := \mathrm{dp} \cdot p(v2)\). Returns `True` if they're newly merged.+--+-- @since 1.1.0.0+{-# INLINE merge #-}+merge :: (HasCallStack, PrimMonad m, Monoid a, Ord a, VU.Unbox a) => Pdsu (PrimState m) a -> Int -> Int -> a -> m Bool+merge dsu@Pdsu {..} v10 v20 !dp0 = inner v10 v20 dp0+  where+    !_ = ACIA.checkIndex "AtCoder.Extra.Pdsu.merge" v10 nPdsu+    !_ = ACIA.checkIndex "AtCoder.Extra.Pdsu.merge" v20 nPdsu+    inner v1 v2 !dp = do+      !r1 <- leader dsu v1+      !r2 <- leader dsu v2+      if r1 == r2+        then pure False+        else do+          -- NOTE(perf): Union by size (choose smaller one for root).+          -- Another, more proper optimization would be union by rank (depth).+          !size1 <- VGM.read potentialPdsu v1+          !size2 <- VGM.read potentialPdsu v2+          if size1 >= size2+            then do+              -- Merge `r1` onto `r2`++              -- Update the size of `r1`+              !negativeSize1 <- negate {- retrieve size -} <$> VGM.read parentOrSizePdsu r1+              !negativeSize2 <- negate {- retrieve size -} <$> VGM.read parentOrSizePdsu r2+              VGM.write parentOrSizePdsu r1 ({- size -} negativeSize1 + negativeSize2)++              -- p(v1) becomes p'(v1) under r2 after merge. p(r1) becomes p'(r1).+              --     p'(v1) = dp <> p(v2)+              --     p'(v1) = p(v1) <> 'p(r1)+              -- Therefore,+              --     p'(r1) = p^{-1}(v1) <> dp <> p(v2)+              !p1 <- VGM.read potentialPdsu v1+              !p2 <- VGM.read potentialPdsu v2+              let !pr1' = invertPdsu p1 <> dp <> p2++              -- Move `r1` to just under `r2`:+              VGM.write parentOrSizePdsu r1 {- record new root -} r2+              VGM.write potentialPdsu r1 pr1'++              pure True+            else do+              inner v2 v1 $ invertPdsu dp++-- | \(O(\alpha(n))\) `merge` with the return value discarded.+--+-- @since 1.1.0.0+{-# INLINE merge_ #-}+merge_ :: (HasCallStack, PrimMonad m, Monoid a, Ord a, VU.Unbox a) => Pdsu (PrimState m) a -> Int -> Int -> a -> m ()+merge_ !dsu !v1 !v2 !dp = do+  _ <- merge dsu v1 v2 dp+  pure ()++-- | \(O(\alpha(n))\) Returns `True` if the two vertices belong to different groups or they belong+-- to the same group under the condition \(p(v_1) = dp \cdot p(v_2)\). It's just a convenient+-- helper function.+--+-- @since 1.1.0.0+{-# INLINE canMerge #-}+canMerge :: (HasCallStack, PrimMonad m, Semigroup a, Eq a, VU.Unbox a) => Pdsu (PrimState m) a -> Int -> Int -> a -> m Bool+canMerge !dsu !v1 !v2 !dp = do+  b <- same dsu v1 v2+  if not b+    then pure True+    else do+      !p1 <- VGM.read (potentialPdsu dsu) v1+      !p2 <- VGM.read (potentialPdsu dsu) v2+      pure $ p1 == dp <> p2++-- | \(O(\alpha(n))\) Returns the number of vertices belonging to the same group.+--+-- @since 1.1.0.0+{-# INLINE size #-}+size :: (HasCallStack, PrimMonad m, Semigroup a, VU.Unbox a) => Pdsu (PrimState m) a -> Int -> m Int+size !dsu !v = (negate <$>) . VGM.read (parentOrSizePdsu dsu) =<< leader dsu v++-- | \(O(n)\) Divides the graph into connected components and returns the list of them.+--+-- @since 1.1.0.0+{-# INLINE groups #-}+groups :: (PrimMonad m, Semigroup a, VU.Unbox a) => Pdsu (PrimState m) a -> m (V.Vector (VU.Vector Int))+groups dsu@Pdsu {..} = do+  groupSize <- VUM.replicate nPdsu (0 :: Int)+  leaders <- VU.generateM nPdsu $ \i -> do+    li <- leader dsu i+    VGM.modify groupSize (+ 1) li+    pure li+  result <- do+    groupSize' <- VU.unsafeFreeze groupSize+    V.mapM VUM.unsafeNew $ VU.convert groupSize'+  VU.iforM_ leaders $ \i li -> do+    i' <- subtract 1 <$> VGM.read groupSize li+    VGM.write (result VG.! li) i' i+    VGM.write groupSize li i'+  V.filter (not . VU.null) <$> V.mapM VU.unsafeFreeze result++-- | \(O(n)\) Clears the `Pdsu` to the initial state.+--+-- @since 1.1.0.0+{-# INLINE clear #-}+clear :: forall m a. (PrimMonad m, Monoid a, VU.Unbox a) => Pdsu (PrimState m) a -> m ()+clear !dsu = do+  VGM.set (potentialPdsu dsu) (mempty @a)+  VGM.set (parentOrSizePdsu dsu) (-1 {- size -})
+ src/AtCoder/Extra/Semigroup/Matrix.hs view
@@ -0,0 +1,264 @@+{-# LANGUAGE MagicHash #-}+{-# LANGUAGE RecordWildCards #-}++-- | A simple HxW matrix backed by a vector, mainly for binary exponention.+--+-- The matrix is a left semigroup action: \(m_2 (m_1 v) = (m_2 \circ m_1) v\).+--+-- @since 1.1.0.0+module AtCoder.Extra.Semigroup.Matrix+  ( -- * Matrix+    Matrix (..),++    -- * Constructors+    new,+    zero,+    ident,+    diag,++    -- * Mapping+    map,++    -- * Multiplications+    mulToCol,+    mul,+    mulMod,+    mulMint,++    -- * Powers+    pow,+    powMod,+    powMint,+  )+where++import AtCoder.Extra.Math qualified as ACEM+import AtCoder.Internal.Assert qualified as ACIA+import AtCoder.Internal.Barrett qualified as BT+import AtCoder.ModInt qualified as M+import Data.Foldable (for_)+import Data.Semigroup (Semigroup (..))+import Data.Vector qualified as V+import Data.Vector.Generic qualified as VG+import Data.Vector.Generic.Mutable qualified as VGM+import Data.Vector.Unboxed qualified as VU+import Data.Vector.Unboxed.Mutable qualified as VUM+import GHC.Exts (proxy#)+import GHC.Stack (HasCallStack)+import GHC.TypeNats (KnownNat, natVal')+import Prelude hiding (map)++-- | A simple HxW matrix backed by a vector, mainly for binary exponention.+--+-- The matrix is a left semigroup action: \(m_2 (m_1 v) = (m_2 \circ m_1) v\).+--+--+-- @since 1.1.0.0+data Matrix a = Matrix+  { -- | @since 1.1.0.0+    hM :: {-# UNPACK #-} !Int,+    -- | @since 1.1.0.0+    wM :: {-# UNPACK #-} !Int,+    -- | @since 1.1.0.0+    vecM :: !(VU.Vector a)+  }+  deriving+    ( -- | @since 1.1.0.0+      Show,+      -- | @since 1.1.0.0+      Eq+    )++-- | Type alias of a column vector.+--+-- @since 1.1.0.0+type Col a = VU.Vector a++-- | \(O(hw)\) Creates an HxW matrix.+--+-- @since 1.1.0.0+{-# INLINE new #-}+new :: (HasCallStack, VU.Unbox a) => Int -> Int -> VU.Vector a -> Matrix a+new h w vec+  | VU.length vec /= h * w = error "AtCoder.Extra.Matrix: size mismatch"+  | otherwise = Matrix h w vec++-- | \(O(n^2)\) Creates an NxN zero matrix.+--+-- @since 1.1.0.0+{-# INLINE zero #-}+zero :: (VU.Unbox a, Num a) => Int -> Matrix a+zero n = Matrix n n $ VU.replicate (n * n) 0++-- | \(O(n^2)\) Creates an NxN identity matrix.+--+-- @since 1.1.0.0+{-# INLINE ident #-}+ident :: (VU.Unbox a, Num a) => Int -> Matrix a+ident n = Matrix n n $ VU.create $ do+  vec <- VUM.replicate (n * n) 0+  for_ [0 .. n - 1] $ \i -> do+    VGM.write vec (i + n * i) 1+  pure vec++-- | \(O(n^2)\) Creates an NxN diagonal matrix.+--+-- @since 1.1.0.0+{-# INLINE diag #-}+diag :: (VU.Unbox a, Num a) => Int -> VU.Vector a -> Matrix a+diag n xs = Matrix n n $ VU.create $ do+  vec <- VUM.replicate (n * n) 0+  VU.iforM_ xs $ \i x -> do+    VGM.write vec (i + n * i) x+  pure vec++-- | \(O(n^2)\) Maps the `Matrix`.+--+-- @since 1.1.0.0+{-# INLINE map #-}+map :: (VU.Unbox a, VU.Unbox b) => (a -> b) -> Matrix a -> Matrix b+map f Matrix {..} = Matrix hM wM $ VU.map f vecM++-- | \(O(hw)\) Multiplies HxW matrix to a Hx1 column vector.+--+-- @since 1.1.0.0+{-# INLINE mulToCol #-}+mulToCol :: (Num a, VU.Unbox a) => Matrix a -> Col a -> Col a+mulToCol Matrix {..} !col = VU.convert $ V.map (VU.sum . VU.zipWith (*) col) rows+  where+    !n = VU.length col+    !_ = ACIA.runtimeAssert (n == wM) "AtCoder.Extra.Matrix.mulToCol: size mismatch"+    rows = V.unfoldrExactN hM (VU.splitAt wM) vecM++-- | \(O(h_1 K w_2)\) Multiplies H1xK matrix to a KxW2 matrix.+--+-- @since 1.1.0.0+{-# INLINE mul #-}+mul :: (Num e, VU.Unbox e) => Matrix e -> Matrix e -> Matrix e+mul !a !b =+  Matrix h w' $+    VU.unfoldrExactN+      (h * w')+      ( \(!row, !col) ->+          let !x = f row col+           in if col + 1 >= w'+                then (x, (row + 1, 0))+                else (x, (row, col + 1))+      )+      (0, 0)+  where+    f row col = VU.sum $ VU.imap (\iRow x -> x * VG.unsafeIndex vecB (col + iRow * w')) (VU.unsafeSlice (w * row) w vecA)+    h = hM a+    w = wM a+    h' = hM b+    vecA = vecM a+    w' = wM b+    vecB = vecM b+    !_ = ACIA.runtimeAssert (w == h') "AtCoder.Extra.Matrix.mul: matrix size mismatch"++-- | \(O(h_1 w_2 K)\) Multiplies H1xK matrix to a KxW2 matrix, taking the mod.+--+-- @since 1.1.0.0+{-# INLINE mulMod #-}+mulMod :: Int -> Matrix Int -> Matrix Int -> Matrix Int+mulMod !m !a !b =+  Matrix h w' $+    VU.unfoldrExactN+      (h * w')+      ( \(!row, !col) ->+          let !x = f row col+           in if col + 1 >= w'+                then (x, (row + 1, 0))+                else (x, (row, col + 1))+      )+      (0, 0)+  where+    !bt = BT.new32 $ fromIntegral m+    f row col = VU.foldl1' addMod $ VU.imap (\iRow x -> mulMod_ x (VG.unsafeIndex vecB (col + (iRow * w')))) (VU.unsafeSlice (w * row) w vecA)+    addMod x y = (x + y) `rem` m+    mulMod_ x y = fromIntegral $ BT.mulMod bt (fromIntegral x) (fromIntegral y)+    h = hM a+    w = wM a+    h' = hM b+    vecA = vecM a+    w' = wM b+    vecB = vecM b+    !_ = ACIA.runtimeAssert (w == h') "AtCoder.Extra.Matrix.mulMod: matrix size mismatch"++-- | \(O(h_1 w_2 K)\) `mul` specialized to `M.ModInt`.+--+-- @since 1.1.0.0+{-# INLINE mulMint #-}+mulMint :: forall a. (KnownNat a) => Matrix (M.ModInt a) -> Matrix (M.ModInt a) -> Matrix (M.ModInt a)+mulMint = mulMintImpl bt+  where+    !bt = BT.new32 $ fromIntegral (natVal' (proxy# @a))++{-# INLINE mulMintImpl #-}+mulMintImpl :: forall a. (KnownNat a) => BT.Barrett -> Matrix (M.ModInt a) -> Matrix (M.ModInt a) -> Matrix (M.ModInt a)+mulMintImpl !bt !a !b =+  Matrix h w' $+    VU.unfoldrExactN+      (h * w')+      ( \(!row, !col) ->+          let !x = f row col+           in if col + 1 >= w'+                then (x, (row + 1, 0))+                else (x, (row, col + 1))+      )+      (0, 0)+  where+    f :: Int -> Int -> M.ModInt a+    f row col = VU.sum $ VU.imap (\iRow x -> mulMod_ x (VG.unsafeIndex vecB (col + (iRow * w')))) (VU.unsafeSlice (w * row) w vecA)+    mulMod_ :: M.ModInt a -> M.ModInt a -> M.ModInt a+    mulMod_ (M.ModInt x) (M.ModInt y) = M.unsafeNew . fromIntegral $ BT.mulMod bt (fromIntegral x) (fromIntegral y)+    h = hM a+    w = wM a+    h' = hM b+    vecA = vecM a+    w' = wM b+    vecB = vecM b+    !_ = ACIA.runtimeAssert (w == h') "AtCoder.Extra.Matrix.mulMint: matrix size mismatch"++-- | \(O(w n^3)\) Calculates \(M^k\).+--+-- @since 1.1.0.0+{-# INLINE pow #-}+pow :: Int -> Matrix Int -> Matrix Int+pow k mat+  | k < 0 = error "AtCoder.Extra.Matrix.powMod: the exponential must be non-negative"+  | k == 0 = ident $ hM mat+  | otherwise = ACEM.power mul k mat+  where+    !_ = ACIA.runtimeAssert (hM mat == wM mat) "AtCoder.Extra.Matrix.powMod: matrix size mismatch"++-- | \(O(w n^3)\) Calculates \(M^k\), taking the mod.+--+-- @since 1.1.0.0+{-# INLINE powMod #-}+powMod :: Int -> Int -> Matrix Int -> Matrix Int+powMod m k mat+  | k < 0 = error "AtCoder.Extra.Matrix.powMod: the exponential must be non-negative"+  | k == 0 = ident $ hM mat+  | otherwise = ACEM.power (mulMod m) k mat+  where+    !_ = ACIA.runtimeAssert (hM mat == wM mat) "AtCoder.Extra.Matrix.powMod: matrix size mismatch"++-- | \(O(w n^3)\) Calculates \(M^k\), specialized to `M.ModInt`.+--+-- @since 1.1.0.0+powMint :: forall m. (KnownNat m) => Int -> Matrix (M.ModInt m) -> Matrix (M.ModInt m)+powMint k mat+  | k < 0 = error "AtCoder.Extra.Matrix.powMint: the exponential must be non-negative"+  | k == 0 = ident $ hM mat+  | otherwise = ACEM.power (mulMintImpl bt) k mat+  where+    !_ = ACIA.runtimeAssert (hM mat == wM mat) "AtCoder.Extra.Matrix.powMint: matrix size mismatch"+    !bt = BT.new32 $ fromIntegral (natVal' (proxy# @m))++-- | @since 1.1.0.0+instance (Num a, VU.Unbox a) => Semigroup (Matrix a) where+  {-# INLINE (<>) #-}+  (<>) = mul+  {-# INLINE stimes #-}+  stimes = ACEM.power (<>) . fromIntegral
+ src/AtCoder/Extra/Semigroup/Permutation.hs view
@@ -0,0 +1,114 @@+-- | A permutation represented by a vector, mainly for binary exponentiation.+--+-- The permutation is a left semigroup action: \(p_2 (p_1 x) = (p_2 \circ p_1) x\).+--+-- ==== __Example__+-- >>> import AtCoder.Extra.Semigroup.Permutation qualified as Permutation+-- >>> import Data.Semigroup (Semigroup (stimes))+-- >>> import Data.Vector.Unboxed qualified as VU+-- >>> let perm = Permutation.new $ VU.fromList [1, 2, 3, 0]+-- >>> Permutation.act perm 1+-- 2+--+-- >>> Permutation.act (perm <> perm) 1+-- 3+--+-- >>> Permutation.act (stimes 3 perm) 1+-- 0+--+-- @since 1.1.0.0+module AtCoder.Extra.Semigroup.Permutation+  ( -- * Permutation+    Permutation (..),++    -- * Constructors+    new,+    unsafeNew,+    ident,+    zero,++    -- * Actions+    act,++    -- * Metadata+    length,+  )+where++import AtCoder.Internal.Assert qualified as ACIA+import Data.Vector.Generic qualified as VG+import Data.Vector.Unboxed qualified as VU+import GHC.Stack (HasCallStack)+import Prelude hiding (length)++-- | A permutation represented by a vector, mainly for binary exponentiation.+--+-- The permutation is a left semigroup action: \(p_2 (p_1 x) = (p_2 \circ p_1) x\).+--+-- @since 1.1.0.0+newtype Permutation = Permutation+  { unPermutation :: VU.Vector Int+  }+  deriving newtype+    ( -- | @since 1.1.0.0+      Eq,+      -- | @since 1.1.0.0+      Show+    )++-- | \(O(1)\) Creates a `Permutation`, performing boundary check on input vector.+--+-- @since 1.1.0.0+{-# INLINE new #-}+new :: (HasCallStack) => VU.Vector Int -> Permutation+new xs = Permutation xs+  where+    n = VU.length xs+    !_ = VU.foldl' (\() i -> let !_ = ACIA.runtimeAssert (-1 <= i && i < n) "AtCoder.Extra.Semigroup.Permutation.new: index boundary error" in ()) () xs++-- | \(O(1)\) Creates a `Permutation`, without performing boundary check on input vector.+--+-- @since 1.1.0.0+{-# INLINE unsafeNew #-}+unsafeNew :: (HasCallStack) => VU.Vector Int -> Permutation+unsafeNew = Permutation++-- | \(O(1)\) Creates an identity `Permutation` of length \(n\).+--+-- @since 1.1.0.0+{-# INLINE ident #-}+ident :: Int -> Permutation+ident = Permutation . (`VU.generate` id)++-- | \(O(1)\) Creates a zero `Permutation` of length \(n\). It's similar to `ident`, but filled+-- with \(-1\) and invalidates corresponding slots on composition.+--+-- @since 1.1.0.0+{-# INLINE zero #-}+zero :: Int -> Permutation+zero n = Permutation $ VU.replicate n (-1)++-- | \(O(1)\) Maps an index.+--+-- @since 1.1.0.0+{-# INLINE act #-}+act :: (HasCallStack) => Permutation -> Int -> Int+act (Permutation vec) i = case vec VG.! i of+  (-1) -> i+  i' -> i'++-- | \(O(1)\) Returns the length of the internal vector.+--+-- @since 1.1.0.0+{-# INLINE length #-}+length :: (HasCallStack) => Permutation -> Int+length = VU.length . unPermutation++-- | @since 1.1.0.0+instance Semigroup Permutation where+  {-# INLINE (<>) #-}+  Permutation r2 <> Permutation r1 = Permutation $ VU.map f r1+    where+      !_ = ACIA.runtimeAssert (VU.length r2 == VU.length r1) "AtCoder.Extra.Semigroup.Permutation.(<>): legth mismatch"+      f (-1) = -1+      f i = VG.unsafeIndex r2 i
+ src/AtCoder/Extra/Tree.hs view
@@ -0,0 +1,207 @@+-- | Generic tree functions.+--+-- @since 1.1.0.0+module AtCoder.Extra.Tree+  ( -- * Tree folding++    -- | These function are built around the three type parameters: \(w\), \(f\) and \(a\).+    --+    -- - \(w\): Edge weight.+    -- - \(f\): Monoid action to a vertex value. These actions are created from vertex value \(a\)+    -- and edge information @(Int, w)@.+    -- - \(a\): Monoid values stored at vertices.+    fold,+    scan,+    foldReroot,+  )+where++import Data.Functor.Identity (runIdentity)+import Data.Vector.Generic qualified as VG+import Data.Vector.Generic.Mutable qualified as VGM+import Data.Vector.Unboxed qualified as VU+import Data.Vector.Unboxed.Mutable qualified as VUM+import GHC.Stack (HasCallStack)++{-# INLINE foldImpl #-}+foldImpl ::+  forall m w f a.+  (HasCallStack, Monad m, VU.Unbox w) =>+  (Int -> VU.Vector (Int, w)) ->+  (Int -> a) ->+  (a -> (Int, w) -> f) ->+  (f -> a -> a) ->+  Int ->+  (Int -> a -> m ()) ->+  m a+foldImpl tree valAt toF act root memo = inner (-1) root+  where+    inner :: Int -> Int -> m a+    inner !parent !v1 = do+      let !acc0 = valAt v1+      let !v2s = VU.filter ((/= parent) . fst) $ tree v1+      !res <- VU.foldM' (\acc (!v2, !w) -> (`act` acc) . (`toF` (v1, w)) <$> inner v1 v2) acc0 v2s+      memo v1 res+      pure res++-- | \(O(n)\) Folds a tree from a root vertex, also known as tree DP.+--+-- ==== __Example__+-- >>> import AtCoder.Extra.Graph qualified as Gr+-- >>> import AtCoder.Extra.Tree qualified as Tree+-- >>> import Data.Semigroup (Sum (..))+-- >>> import Data.Vector.Unboxed qualified as VU+-- >>> let gr = Gr.build @(Sum Int) 5 . Gr.swapDupe $ VU.fromList [(2, 1, Sum 1), (1, 0, Sum 1), (2, 3, Sum 1), (3, 4, Sum 1)]+-- >>> type W = Sum Int -- edge weight+-- >>> type F = Sum Int -- action type+-- >>> type X = Sum Int -- vertex value+-- >>> :{+--  let res = Tree.fold (gr `Gr.adjW`) valAt toF act 2+--        where+--          valAt :: Int -> X+--          valAt = const $ mempty @(Sum Int)+--          toF :: X -> (Int, W) -> F+--          toF x (!_i, !dx) = x + dx+--          act :: F -> X -> X+--          act dx x = dx + x+--   in getSum res+-- :}+-- 4+--+-- @since 1.1.0.0+{-# INLINE fold #-}+fold ::+  (HasCallStack, VU.Unbox w) =>+  -- | Graph as a function.+  (Int -> VU.Vector (Int, w)) ->+  -- | @valAt@: Assignment of initial vertex values.+  (Int -> a) ->+  -- | @toF@: Converts a vertex value into an action onto a neighbor vertex.+  (a -> (Int, w) -> f) ->+  -- | @act@: Performs an action onto a vertex value.+  (f -> a -> a) ->+  -- | Root vertex.+  Int ->+  -- | Tree folding result from the root vertex.+  a+fold tree valAt toF act root = runIdentity $ do+  foldImpl tree valAt toF act root (\_ _ -> pure ())++-- | \(O(n)\) Folds a tree from a root vertex, also known as tree DP. The calculation process on+-- every vertex is recoreded and returned as a vector.+--+-- ==== __Example__+-- >>> import AtCoder.Extra.Graph qualified as Gr+-- >>> import AtCoder.Extra.Tree qualified as Tree+-- >>> import Data.Semigroup (Sum (..))+-- >>> import Data.Vector.Unboxed qualified as VU+-- >>> let n = 5+-- >>> let gr = Gr.build @(Sum Int) n . Gr.swapDupe $ VU.fromList [(2, 1, Sum 1), (1, 0, Sum 1), (2, 3, Sum 1), (3, 4, Sum 1)]+-- >>> type W = Sum Int -- edge weight+-- >>> type F = Sum Int -- action type+-- >>> type X = Sum Int -- vertex value+-- >>> :{+--  let res = Tree.scan n (gr `Gr.adjW`) valAt toF act 2+--        where+--          valAt :: Int -> X+--          valAt = const $ mempty @(Sum Int)+--          toF :: X -> (Int, W) -> F+--          toF x (!_i, !dx) = x + dx+--          act :: F -> X -> X+--          act dx x = dx + x+--   in VU.map getSum res+-- :}+-- [0,1,4,1,0]+--+-- @since 1.1.0.0+{-# INLINE scan #-}+scan ::+  (VU.Unbox w, VG.Vector v a) =>+  -- | The number of vertices.+  Int ->+  -- | Graph as a function.+  (Int -> VU.Vector (Int, w)) ->+  -- | @valAt@: Assignment of initial vertex values.+  (Int -> a) ->+  -- | @toF@: Converts a vertex value into an action onto a neighbor vertex.+  (a -> (Int, w) -> f) ->+  -- | @act@: Performs an action onto a vertex value.+  (f -> a -> a) ->+  -- | Root vertex.+  Int ->+  -- | Tree scanning result from a root vertex.+  v a+scan n tree acc0At toF act root = VG.create $ do+  dp <- VGM.unsafeNew n+  !_ <- foldImpl tree acc0At toF act root $ \v a -> do+    VGM.unsafeWrite dp v a+  pure dp++-- | \(O(n)\) Folds a tree from every vertex, using the rerooting technique.+--+-- ==== __Example__+-- >>> import AtCoder.Extra.Graph qualified as Gr+-- >>> import AtCoder.Extra.Tree qualified as Tree+-- >>> import Data.Semigroup (Sum (..))+-- >>> import Data.Vector.Unboxed qualified as VU+-- >>> let n = 5+-- >>> let gr = Gr.build @(Sum Int) n . Gr.swapDupe $ VU.fromList [(2, 1, Sum 1), (1, 0, Sum 1), (2, 3, Sum 1), (3, 4, Sum 1)]+-- >>> type W = Sum Int -- edge weight+-- >>> type F = Sum Int -- action type+-- >>> type X = Sum Int -- vertex value+-- >>> :{+--  let res = Tree.foldReroot n (gr `Gr.adjW`) valAt toF act+--        where+--          valAt :: Int -> X+--          valAt = const $ mempty @(Sum Int)+--          toF :: X -> (Int, W) -> F+--          toF x (!_i, !dx) = x + dx+--          act :: F -> X -> X+--          act dx x = dx + x+--   in VU.map getSum res+-- :}+-- [4,4,4,4,4]+--+-- @since 1.1.0.0+{-# INLINE foldReroot #-}+foldReroot ::+  forall w f a.+  (HasCallStack, VU.Unbox w, VU.Unbox a, VU.Unbox f, Monoid f) =>+  -- | The number of vertices.+  Int ->+  -- | Graph as a function.+  (Int -> VU.Vector (Int, w)) ->+  -- | @valAt@:Assignment of initial vertex values.+  (Int -> a) ->+  -- | @toF@: Converts a vertex value into an action onto a neighbor vertex.+  (a -> (Int, w) -> f) ->+  -- | @act@: Performs an action onto a vertex value.+  (f -> a -> a) ->+  -- | Tree folding result from every vertex as a root.+  VU.Vector a+foldReroot n tree valAt toF act = VU.create $ do+  -- Calculate tree DP for every vertex as a root:+  !dp <- VUM.unsafeNew n+  let reroot parent parentF v1 = do+        -- TODO: when the operator is not commutative?+        let !children = VU.filter ((/= parent) . fst) $ tree v1+        let !fL = VU.scanl' (\ !f (!v2, !w) -> (f <>) . (`toF` (v1, w)) $ treeDp VG.! v2) f0 children+        let !fR = VU.scanr' (\(!v2, !w) !f -> (<> f) . (`toF` (v1, w)) $ treeDp VG.! v2) f0 children++        -- save+        let !x1 = (parentF <> VU.last fL) `act` valAt v1+        VGM.unsafeWrite dp v1 x1++        VU.iforM_ children $ \i2 (!v2, !w) -> do+          -- composited operator excluding @v2@:+          let !f1 = parentF <> (fL VG.! i2) <> (fR VG.! (i2 + 1))+          let !v1Acc = f1 `act` valAt v1+          let !f2 = toF v1Acc (v2, w)+          reroot v1 f2 v2++  reroot (-1 :: Int) f0 root0+  pure dp+  where+    !root0 = 0 :: Int+    !f0 = mempty @f+    !treeDp = scan n tree valAt toF act root0 :: VU.Vector a
+ src/AtCoder/Extra/Tree/Hld.hs view
@@ -0,0 +1,512 @@+{-# LANGUAGE RecordWildCards #-}++-- | Heavy-light decomposition is a method for partitioning a tree into segments with consecutive+-- indices. It processes various path queries in \(O(\log n)\) time. For segment tree integration+-- and monoid products, refer to the @TreeMonoid@ module.+--+-- ==== __Overview of the internals__+-- The following is for understanding the internals, not for using the API. Skip to the examples if+-- you want.+--+-- ===== Original tree+--+-- Consider a tree with arbitrary vertex order:+--+-- @+--  0--8--7--3--1--2--12--13--15--14     XX: original Vertex+--     |        |                        --: edge+-- 10--5        11--8--6                 |: edge+--     |+--     4+-- @+--+-- ===== `indexHld`: Vertex -> VertexHld+--+-- The tree vertices are reindexed with `indexHld`, where each segment is assigned consecutive+-- vertex indices:+--+-- @+--  0==1==2==3==4==5==6==7==8==9     XX: VertexHld+--     |        |                    ==: edges on the same semgent+-- 14==13       10==11==12           |: edge between different segments+--     |+--     15+-- @+--+-- Note that vertices on higher (closer to the root) segments are assigned smaller indices. This is+-- very internally very important when calculating `lca`.+--+-- ===== `headHld`: Vertex -> Vertex+--+-- `headHld` points the "head" vertex of each segment. It can be used for finding LCA of two+-- vertices. To find the LCA, move up to the head, go up to the parental segment's vertex and+-- repeat until the two vertices are on the same segment.+--+-- @+--  0==0==0==0==0==0==0==0==0==0     XX: original Vertex+--     |     |+--  5==5     11==11==11+--     |+--     4+-- @+--+-- `headHld` also works for identifying segments. When two vertices are on the same segment, they+-- have the same head.+--+-- ===== `parentHld`: Vertex -> Vertex+--+-- `parentHld` points the parental segment's vertex from a head:+--+-- @+-- (-1)==0==8==7==3==1==2==12==13==15     XX: original Vertex+--       |        |+--    5==8        1==11=8+--       |+--       5+-- @+--+-- ==== __Example__+-- Create an `Hld` for a tree:+--+-- >>> import AtCoder.Extra.Graph qualified as Gr+-- >>> import AtCoder.Extra.Tree.Hld qualified as Hld+-- >>> import Data.Vector.Unboxed qualified as VU+-- >>> -- 0--1--2--3+-- >>> --    ++-- >>> --    +--4--5+-- >>> let n = 6+-- >>> let tree = Gr.build' n . Gr.swapDupe' $ VU.fromList [(0, 1), (1, 2), (2, 3), (1, 4), (4, 5)]+-- >>> let hld = Hld.new tree+--+-- `Hld` can process various queries in \(O(\log n)\) time:+--+-- >>> Hld.ancestor hld 5 3 -- go up three parents from `5`+-- 0+--+-- >>> Hld.jump hld 5 2 3   -- go to the third vertex from `5` to `2`:+-- Just 2+--+-- >>> Hld.lengthBetween hld 5 3 -- get the length (the number of edges) between `5` and `3`:+-- 4+--+-- >>> Hld.path hld 5 3     -- get the path between `5` and `3`:+-- [5,4,1,2,3]+--+-- Our `Hld` is rooted at @0@ vertex and subtree queries are available:+--+-- >>> Hld.isInSubtree hld 2 3 -- `3` is in the subtree of `2`+-- True+--+-- >>> Hld.isInSubtree hld 2 4 -- `4` is not in the subtree of `2`+-- False+--+-- ===== Segment queries+-- Products and segment queries are primarily used by the @TreeMonoid@ module and is not intended+-- for diretct use, but here's some examples. This time the reindex by the HLD is identity:+--+-- >>> Hld.indexHld hld+-- [0,1,2,3,4,5]+--+-- So we can easily understand the outputs:+--+-- >>> Hld.pathSegmentsInclusive Hld.WeightsAreOnVertices hld 5 3+-- [(5,4),(1,3)]+--+-- >>> Hld.pathSegmentsInclusive Hld.WeightsAreOnEdges hld 5 3 -- LCA (1) is removed+-- [(5,4),(2,3)]+--+-- >>> Hld.subtreeSegmentInclusive hld 1+-- (1,5)+--+-- @since 1.1.0.0+module AtCoder.Extra.Tree.Hld+  ( -- * Hld+    Hld (..),+    Vertex,+    VertexHld,++    -- * Constructors+    new,+    newAt,++    -- * LCA+    lca,++    -- * Jump+    ancestor,+    jump,++    -- * Path+    lengthBetween,+    path,+    pathSegmentsInclusive,++    -- * Subtree+    subtreeSegmentInclusive,+    isInSubtree,++    -- * Products+    WeightPolicy (..),+    prod,+  )+where++import AtCoder.Extra.Graph qualified as Gr+import AtCoder.Internal.Assert qualified as ACIA+import Control.Monad+import Control.Monad.Fix+import Control.Monad.ST+import Data.Maybe+import Data.Vector.Generic qualified as VG+import Data.Vector.Generic.Mutable qualified as VGM+import Data.Vector.Unboxed qualified as VU+import Data.Vector.Unboxed.Mutable qualified as VUM+import GHC.Stack (HasCallStack)++-- | Original graph vertex.+--+-- @since 1.1.0.0+type Vertex = Int++-- | Vertex reindexed by `indexHld`.+--+-- @since 1.1.0.0+type VertexHld = Vertex++-- | `Hld` partitions a tree into segments and assignes contiguous `VertexHld` for each segment.+--+-- @since 1.1.0.0+data Hld = Hld+  { -- | The root vertex.+    --+    -- @since 1.1.0.0+    rootHld :: {-# UNPACK #-} !Vertex,+    -- | Maps `Vertex` to the parent `Vertex`. Returns @-1@ for the root node.+    --+    -- @since 1.1.0.0+    parentHld :: !(VU.Vector Vertex),+    -- | Maps `Vertex` to `VertexHld`, re-indexed vertices contiguous in each segment.+    --+    -- @since 1.1.0.0+    indexHld :: !(VU.Vector VertexHld),+    -- | Maps `Vertex` to the head `Vertex` of the segment.+    --+    -- @since 1.1.0.0+    headHld :: !(VU.Vector Vertex),+    -- | Maps `VertexHld` back to `Vertex`. Used for `ancestor` etc.+    --+    -- @since 1.1.0.0+    revIndexHld :: !(VU.Vector Vertex),+    -- | Maps `Vertex` to their depth from the root. Used for `jump` etc.+    --+    -- @since 1.1.0.0+    depthHld :: !(VU.Vector Int),+    -- | Maps `Vertex` to the subtree size. This is for subtree products.+    --+    -- @since 1.1.0.0+    subtreeSizeHld :: !(VU.Vector Int)+  }+  deriving+    ( -- | @since 1.1.0.0+      Show,+      -- | @since 1.1.0.0+      Eq+    )++-- | \(O(n)\) Creates an `Hld` with \(0\) as the root vertex.+--+-- @since 1.1.0.0+{-# INLINE new #-}+new :: forall w. (HasCallStack) => Gr.Csr w -> Hld+new tree = newAt tree 0++-- | \(O(n)\) Creates an `Hld` with a root vertex specified.+--+-- @since 1.1.0.0+{-# INLINE newAt #-}+newAt :: forall w. (HasCallStack) => Gr.Csr w -> Vertex -> Hld+newAt tree root = runST $ do+  -- Re-create adjacent vertices so that the biggest subtree's head vertex comes first.+  --+  -- We /could/ instead record the biggest adjacent subtree vertex for each vertex, but the other+  -- DFS would be harder.+  let (!tree', !parent, !depths, !subtreeSize) = runST $ do+        adjVec <- VU.thaw (Gr.adjCsr tree)+        parent_ <- VUM.unsafeNew n+        depths_ <- VUM.unsafeNew n+        subtreeSize_ <- VUM.unsafeNew n++        _ <- (\f -> fix f 0 (-1) root) $ \loop depth p v1 -> do+          VGM.write parent_ v1 p+          VGM.write depths_ v1 depth++          (!size1, !eBig) <-+            VU.foldM'+              ( \(!size1, !eBig) (!e2, !v2) -> do+                  if v2 == p+                    then pure (size1, eBig)+                    else do+                      size2 <- loop (depth + 1) v1 v2+                      -- NOTE: It's `>` because we should swap at least once if there's some vertex other+                      -- that the parent_.+                      pure (size1 + size2, if size1 > size2 then eBig else e2)+              )+              (1 :: Int, -1)+              (tree `Gr.eAdj` v1)++          -- move the biggest subtree's head to the first adjacent vertex.+          -- it means the "heavy edge" or the longest segment.+          when (eBig /= -1) $ do+            VGM.swap adjVec eBig $ fst (VG.head (tree `Gr.eAdj` v1))++          -- record subtree size+          VGM.write subtreeSize_ v1 size1++          pure size1++        !vec <- VU.unsafeFreeze adjVec+        (tree {Gr.adjCsr = vec},,,)+          <$> VU.unsafeFreeze parent_+          <*> VU.unsafeFreeze depths_+          <*> VU.unsafeFreeze subtreeSize_++  -- vertex -> reindexed vertex index+  indices <- VUM.replicate n (-1 :: Int)++  -- vertex -> head vertex of the segment+  heads <- VUM.replicate n (-1 :: Int)++  _ <- (\f -> fix f (0 :: Int) root (-1) root) $ \loop acc h p v1 -> do+    -- reindex:+    VGM.write indices v1 acc+    let !acc' = acc + 1++    VGM.write heads v1 h++    -- when the first vertex is within the same segment:+    let (!adj1, !rest) = fromJust $ VU.uncons (tree' `Gr.adj` v1)+    acc'' <-+      if adj1 == p+        then pure acc'+        else loop acc' h v1 adj1++    -- the others are in other segments:+    VU.foldM'+      ( \a v2 -> do+          if v2 == p+            then pure a+            else loop a v2 v1 v2+      )+      acc''+      rest++  !indices' <- VU.unsafeFreeze indices+  let !revIndex = VU.update (VU.replicate n (-1)) $ VU.imap (flip (,)) indices'++  Hld root parent indices'+    <$> VU.unsafeFreeze heads+    <*> pure revIndex+    <*> pure depths+    <*> pure subtreeSize+  where+    !n = Gr.nCsr tree+    !_ = ACIA.runtimeAssert (2 * (Gr.nCsr tree - 1) == Gr.mCsr tree) "AtCoder.Extra.Hld.newAt: not a non-directed tree"++-- | \(O(\log n)\) Calculates the lowest common ancestor of \(u\) and \(v\).+--+-- @since 1.1.0.0+{-# INLINE lca #-}+lca :: (HasCallStack) => Hld -> Vertex -> Vertex -> Vertex+lca Hld {..} = inner+  where+    inner !x !y+      -- sort for easier processing+      -- TODO: @case compare ix iy@ would be easier for me to understand+      | ix > iy = inner y x+      -- @x@ and @y@ are in other segments:+      | hx /= hy = inner x $ parentHld VG.! hy+      -- @x@ and @y@ are within the same segment:+      -- select the smaller one, which is closer to the root and that is the LCA.+      | otherwise = x+      where+        !ix = indexHld VG.! x+        !iy = indexHld VG.! y+        hx = headHld VG.! x+        hy = headHld VG.! y++-- | \(O(\log n)\) Go up \(k\) times from a vertex \(v\) to the root node. Throws an error if \(k\)+-- is bigger than the depth of \(v\).+--+-- @since 1.1.0.0+{-# INLINE ancestor #-}+ancestor :: (HasCallStack) => Hld -> Vertex -> Int -> Vertex+ancestor Hld {..} parent k0 = inner parent k0+  where+    !_ = ACIA.runtimeAssert (0 <= k0 && k0 <= depthHld VG.! parent) $ "AtCoder.Extra.Tree.Hld.ancestor: k-th ancestor is out of the bounds (`k = " ++ show k0 ++ "`)"+    inner v k+      -- on this segment+      | k <= iv - ihv = revIndexHld VG.! (iv - k)+      -- next segment+      | otherwise = inner (parentHld VG.! hv) (k - (iv - ihv + 1))+      where+        iv = indexHld VG.! v+        hv = headHld VG.! v+        ihv = indexHld VG.! hv++-- | \(O(\log n)\) Returns the \(k\)-th vertex of the path between \(u\) and \(v\) from \(u\).+-- Throws an error if `k` is out+--+-- @since 1.1.0.0+{-# INLINE jump #-}+jump :: (HasCallStack) => Hld -> Vertex -> Vertex -> Int -> Maybe Vertex+jump hld@Hld {..} u v k+  | k > lenU + lenV = Nothing+  | k <= lenU = Just $ ancestor hld u k+  | otherwise = Just $ ancestor hld v (lenU + lenV - k)+  where+    lca_ = lca hld u v+    du = depthHld VG.! u+    dv = depthHld VG.! v+    lenU = du - depthHld VG.! lca_+    lenV = dv - depthHld VG.! lca_++-- | \(O(\log n)\) Returns the length of the path between \(u\) and \(v\).+--+-- @since 1.1.0.0+{-# INLINE lengthBetween #-}+lengthBetween :: (HasCallStack) => Hld -> Vertex -> Vertex -> Int+lengthBetween hld@Hld {..} u v = du - dLca + dv - dLca+  where+    !lca_ = lca hld u v+    !dLca = depthHld VG.! lca_+    !du = depthHld VG.! u+    !dv = depthHld VG.! v++-- | \(O(n)\) Returns the vertices on the path between \(u\) and \(v\).+--+-- @since 1.1.0.0+{-# INLINE path #-}+path :: (HasCallStack) => Hld -> Vertex -> Vertex -> [Vertex]+path hld@Hld {..} u v = concatMap expand $ pathSegmentsInclusive WeightsAreOnVertices hld u v+  where+    expand (!l, !r)+      | l <= r = map (revIndexHld VG.!) [l .. r]+      | otherwise = map (revIndexHld VG.!) [l, l - 1 .. r]++-- | \(O(\log n)\) Decomposes a path between two vertices \(u\) and \(v\) into segments. Each+-- segment is represented as an __inclusive__ range \([u_i, v_i]\) of `VertexHLD`.+--+-- The LCA is omitted from the returning vertices when the weight policy is set to+-- `WeightsAreOnEdges`. This is the trick to put edge weights to on vertices.+--+-- @since 1.1.0.0+{-# INLINE pathSegmentsInclusive #-}+pathSegmentsInclusive :: (HasCallStack) => WeightPolicy -> Hld -> Vertex -> Vertex -> [(VertexHld, VertexHld)]+pathSegmentsInclusive weightPolicy Hld {..} x0 y0 = done $ inner x0 [] y0 []+  where+    isEdge = weightPolicy == WeightsAreOnEdges+    done (!up, !down) = reverse up ++ down+    -- @up@: bottom to top. [(max, min)]+    -- @down@: top to bottom. [(min, max)]+    inner :: Vertex -> [(VertexHld, VertexHld)] -> Vertex -> [(VertexHld, VertexHld)] -> ([(VertexHld, VertexHld)], [(VertexHld, VertexHld)])+    inner x up y down+      | hx == hy && isEdge = case compare ix iy of+          -- skip LCA on edge vertices+          LT -> (up, (ix {- edge -} + 1, iy) : down)+          GT -> ((ix, iy {- edge -} + 1) : up, down)+          EQ -> (up, down)+      | hx == hy && not isEdge = case compare ix iy of+          LT -> (up, (ix, iy) : down)+          _ -> ((ix, iy) : up, down)+      | otherwise = case compare ix iy of+          LT -> inner x up phy ((ihy, iy) : down)+          GT -> inner phx ((ix, ihx) : up) y down+          EQ -> error "unreachable"+      where+        ix, iy :: VertexHld+        !ix = indexHld VG.! x+        !iy = indexHld VG.! y+        hx, hy :: Vertex+        hx = headHld VG.! x+        hy = headHld VG.! y+        ihx, ihy :: VertexHld+        ihx = indexHld VG.! hx+        ihy = indexHld VG.! hy+        phx, phy :: VertexHld+        phx = parentHld VG.! hx+        phy = parentHld VG.! hy++-- | \(O(1)\) Returns a half-open interval of `VertexHld` \([\mathrm{start}, \mathrm{end})\) that+-- corresponds to the subtree segments rooted at the given @subtreeRoot@.+--+-- @since 1.1.0.0+{-# INLINE subtreeSegmentInclusive #-}+subtreeSegmentInclusive :: (HasCallStack) => Hld -> Vertex -> (VertexHld, VertexHld)+subtreeSegmentInclusive Hld {..} subtreeRoot = (ir, ir + sr - 1)+  where+    ir = indexHld VG.! subtreeRoot+    sr = subtreeSizeHld VG.! subtreeRoot++-- | \(O(1)\) Returns `True` if \(u\) is in a subtree of \(r\).+--+-- @since 1.1.0.0+{-# INLINE isInSubtree #-}+isInSubtree :: (HasCallStack) => Hld -> Vertex -> Vertex -> Bool+isInSubtree hld@Hld {..} r_ u = l <= iu && iu <= r+  where+    (!l, !r) = subtreeSegmentInclusive hld r_+    !iu = indexHld VG.! u++-- | Represents whether weights are put on vertices or edges.+--+-- @since 1.1.0.0+data WeightPolicy+  = -- | Weights are put on vertices.+    --+    -- @since 1.1.0.0+    WeightsAreOnVertices+  | -- | Weights are put on edges.+    --+    -- @since 1.1.0.0+    WeightsAreOnEdges+  deriving+    ( -- | @since 1.1.0.0+      Eq,+      -- | @since 1.1.0.0+      Show+    )++-- | \(O(\log n f)\) Returns product of the path between \(u\) and \(v\), using the user functions+-- of time complexity \(O(f)\).+--+-- @since 1.1.0.0+{-# INLINE prod #-}+prod ::+  (HasCallStack, Monoid mono, Monad m) =>+  -- | The `WeightPolicy`.+  WeightPolicy ->+  -- | The `Hld`.+  Hld ->+  -- | User function for getting products in \([u, v)\), where \(u < v\) and+  -- \(\mathrm{depth}(u) < \mathrm{depth}(v)\).+  (VertexHld -> VertexHld -> m mono) ->+  -- | User function for getting products in \([u, v)\), where \(u < v\) and+  -- \(\mathrm{depth}(u) > \mathrm{depth}(v)\).+  (VertexHld -> VertexHld -> m mono) ->+  -- | \(u\).+  Vertex ->+  -- | \(v\).+  Vertex ->+  -- | Product of the path between \(u\) and \(v\).+  m mono+prod weightPolicy hld prodF prodB u0 v0 = do+  foldM+    ( \ !acc (!u, !v) -> do+        !x <-+          if u <= v+            then prodF u $ v + 1+            else prodB v $ u + 1+        pure $! acc <> x+    )+    mempty+    (pathSegmentsInclusive weightPolicy hld u0 v0)
+ src/AtCoder/Extra/Tree/TreeMonoid.hs view
@@ -0,0 +1,297 @@+{-# LANGUAGE RecordWildCards #-}++-- | Integration of segment trees with the heavy-light decomposition technique. Computes monoid+-- products on a path in \(O(\log^2 n)\) time or on a subtree in \(O(\log n)\) time.+--+-- - If vertices have weights, create a `TreeMonoid` with `fromVerts`.+-- - If edges have weights, create a tree monoid with `fromEdges`.+--+-- ==== __(Internals) Weights on edges__+--+-- When vertices are unweighted and only edges have weights, treat edges as new vertices or assign+-- edge weights to the deeper vertex.+--+-- Idea 1. Convert edges into new vertices. This is inefficient.+--+-- @+-- o--o--o  --> o-x-o-x-o+-- @+--+-- Idea 2. Assign edge weight to the deeper vertex. The is the internal implementation of+-- `fromEdges` and LCAs are ignored on `prod`:+--+-- @+--   o+--   | <--- edge 1+--   o <- write weight 1 here+--   | <--- edge 2+--   o <- write weight 2 here+-- @+--+-- ==== __Example (1): Weights are on vertices__+-- >>> import AtCoder.Extra.Graph qualified as Gr+-- >>> import AtCoder.Extra.Tree.Hld qualified as Hld+-- >>> import AtCoder.Extra.Tree.TreeMonoid qualified as TM+-- >>> import Data.Semigroup (Sum (..))+-- >>> import Data.Vector.Unboxed qualified as VU+-- >>> -- 0--1--2--3+-- >>> --    ++-- >>> --    +--4--5+-- >>> let n = 6+-- >>> let tree = Gr.build' n . Gr.swapDupe' $ VU.fromList [(0, 1), (1, 2), (2, 3), (1, 4), (4, 5)]+-- >>> let weights = VU.generate n Sum -- vertex `i` is given weight of `i`+-- >>> let hld = Hld.new tree+-- >>> tm <- TM.fromVerts hld {- `Sum` is commutative -} Commute weights+-- >>> TM.prod tm 1 3+-- Sum {getSum = 6}+--+-- >>> TM.prodSubtree tm 1+-- Sum {getSum = 15}+--+-- >>> TM.write tm 1 $ Sum 10+-- >>> TM.prod tm 1 3+-- Sum {getSum = 15}+--+-- ==== __Example (2): Weights are on edges__+-- >>> import AtCoder.Extra.Graph qualified as Gr+-- >>> import AtCoder.Extra.Tree.Hld qualified as Hld+-- >>> import AtCoder.Extra.Tree.TreeMonoid qualified as TM+-- >>> import Data.Semigroup (Sum (..))+-- >>> import Data.Vector.Unboxed qualified as VU+-- >>> -- 0--1--2--3+-- >>> --    ++-- >>> --    +--4--5+-- >>> let n = 6+-- >>> let edges = VU.fromList [(0, 1, Sum (1 :: Int)), (1, 2, Sum 2), (2, 3, Sum 3), (1, 4, Sum 4), (4, 5, Sum 5)]+-- >>> let tree = Gr.build n $ Gr.swapDupe edges+-- >>> let hld = Hld.new tree+-- >>> tm <- TM.fromEdges hld {- `Sum` is commutative -} Commute edges+-- >>> TM.prod tm 1 3+-- Sum {getSum = 5}+--+-- >>> TM.prodSubtree tm 1+-- Sum {getSum = 14}+--+-- >>> TM.write tm 2 $ Sum 10+-- >>> TM.prod tm 1 3+-- Sum {getSum = 13}+--+-- @since 1.1.0.0+module AtCoder.Extra.Tree.TreeMonoid+  ( -- * TreeMonoid+    TreeMonoid,+    Vertex,+    VertexHld,+    Commutativity (..),++    -- * Constructors+    fromVerts,+    fromEdges,++    -- * Segment tree methods++    -- ** Reading+    prod,+    prodSubtree,+    read,++    -- ** Modifications+    write,+    exchange,+    modify,+    modifyM,+  )+where++import AtCoder.Extra.Tree.Hld qualified as Hld+import AtCoder.Internal.Assert qualified as ACIA+import AtCoder.SegTree qualified as ST+import Control.Monad+import Control.Monad.Primitive (PrimMonad, PrimState)+import Data.Monoid (Dual (..))+import Data.Vector.Generic qualified as VG+import Data.Vector.Generic.Mutable qualified as VGM+import Data.Vector.Unboxed qualified as VU+import Data.Vector.Unboxed.Mutable qualified as VUM+import GHC.Stack (HasCallStack)+import Prelude hiding (read)++-- | Original graph vertex.+--+-- @since 1.1.0.0+type Vertex = Int++-- | Vertex reindexed by `indexHld`.+--+-- @since 1.1.0.0+type VertexHld = Vertex++-- | A wrapper for `Hld` getting product on paths on a tree using `Hld` and segment tree(s).+--+-- @since 1.1.0.0+data TreeMonoid a s = TreeMonoid+  { -- | Borrowed Hld.+    hldTM :: !Hld.Hld,+    -- | Indicates if it's targetting commutative monoids.+    commuteTM :: !Commutativity,+    -- | Indicates if it's targetting edge weights (If not, it's targetting vertex weights).+    weightPolicyTM :: !Hld.WeightPolicy,+    -- | Segment tree for getting products upwards.+    segFTM :: !(ST.SegTree s a),+    -- | Segment tree for getting products downwards. Only created when the monoid is+    -- `NonCommute`.+    segBTM :: !(ST.SegTree s (Dual a))+  }++-- | Represents whether a monoid is commutative or noncommutative.+--+-- @since 1.1.0.0+data Commutativity+  = -- | Commutative: \(a \cdot b = b \cdot a\).+    --+    -- @since 1.1.0.0+    Commute+  | -- | Noncommutative: \(a \cdot b \neq b \cdot a\).+    --+    -- @since 1.1.0.0+    NonCommute+  deriving+    ( -- | @since 1.1.0.0+      Eq,+      -- | @since 1.1.0.0+      Show+    )++-- | \(O(n)\)+buildImpl ::+  (HasCallStack, PrimMonad m, Monoid a, VU.Unbox a) =>+  Hld.Hld ->+  Commutativity ->+  Hld.WeightPolicy ->+  VU.Vector a ->+  m (TreeMonoid a (PrimState m))+buildImpl hldTM commuteTM weightPolicyTM weights = do+  segFTM <- ST.build weights+  segBTM <-+    case commuteTM of+      Commute -> ST.build VU.empty+      NonCommute -> ST.build $ VU.map Dual weights+  pure TreeMonoid {..}++-- | \(O(n)\) Creates a `TreeMonoid` with weights on vertices.+--+-- @since 1.1.0.0+fromVerts ::+  (HasCallStack, PrimMonad m, Monoid a, VU.Unbox a) =>+  -- | `Hld.Hld`.+  Hld.Hld ->+  -- | Whether the monoid is commutative or not.+  Commutativity ->+  -- | The vertex weights.+  VU.Vector a ->+  -- | A `TreeMonoid` with weights on vertices.+  m (TreeMonoid a (PrimState m))+fromVerts hld@Hld.Hld {indexHld} commuteTM xs_ = do+  let !_ = ACIA.runtimeAssert (VU.length indexHld == VU.length xs_) $ "AtCoder.Extra.Tree.TreeMonoid.fromVerts: vertex number mismatch (`" ++ show (VU.length indexHld) ++ "` and `" ++ show (VU.length xs_) ++ "`)"+  let !xs = VU.create $ do+        vec <- VUM.unsafeNew $ VU.length xs_+        VU.iforM_ xs_ $ \i x -> do+          VGM.write vec (indexHld VG.! i) x+        pure vec+  buildImpl hld commuteTM Hld.WeightsAreOnVertices xs++-- | \(O(n)\) Creates a `TreeMonoid` with weignts on edges. The edges are not required to be+-- duplicated: only one of \((u, v, w)\) or \((v, u, w)\) is needed.+--+-- @since 1.1.0.0+fromEdges ::+  (HasCallStack, PrimMonad m, Monoid a, VU.Unbox a) =>+  -- | `Hld.Hld`.+  Hld.Hld ->+  -- | Whether the monoid is commutative or not.+  Commutativity ->+  -- | Input edges.+  VU.Vector (Vertex, Vertex, a) ->+  -- | A `TreeMonoid` with weights on edges.+  m (TreeMonoid a (PrimState m))+fromEdges hld@Hld.Hld {indexHld} commuteTM edges = do+  let !xs = VU.create $ do+        vec <- VUM.unsafeNew $ VU.length indexHld+        VU.forM_ edges $ \(!u, !v, !w) -> do+          let u' = indexHld VG.! u+          let v' = indexHld VG.! v+          VGM.write vec (max u' v') w+        pure vec+  buildImpl hld commuteTM Hld.WeightsAreOnEdges xs++-- | \(O(\log^2 n)\) Returns the product of the path between two vertices \(u\), \(v\) (invlusive).+--+-- @since 1.1.0.0+prod :: (HasCallStack, PrimMonad m, Monoid a, VU.Unbox a) => TreeMonoid a (PrimState m) -> Vertex -> Vertex -> m a+prod TreeMonoid {..} u v = do+  case commuteTM of+    Commute -> Hld.prod weightPolicyTM hldTM (ST.prod segFTM) (ST.prod segFTM) u v+    NonCommute -> Hld.prod weightPolicyTM hldTM (ST.prod segFTM) (\l r -> getDual <$> ST.prod segBTM l r) u v++-- | \(O(\log n)\) Returns the product of the subtree rooted at the given `Vertex`.+--+-- @since 1.1.0.0+prodSubtree :: (HasCallStack, PrimMonad m, Monoid a, VU.Unbox a) => TreeMonoid a (PrimState m) -> Vertex -> m a+prodSubtree TreeMonoid {..} subtreeRoot = do+  let (!l, !r) = Hld.subtreeSegmentInclusive hldTM subtreeRoot+  case weightPolicyTM of+    Hld.WeightsAreOnVertices -> ST.prod segFTM l (r + 1)+    Hld.WeightsAreOnEdges -> do+      -- ignore the root of the subtree, which has the minimum index among the subtree vertices+      if l == r+        then pure mempty+        else ST.prod segFTM (l + 1) (r + 1)++-- | \(O(1)\) Reads a `TreeMonoid` value on a `Vertex`.+--+-- @since 1.1.0.0+read :: (HasCallStack, PrimMonad m, Monoid a, VU.Unbox a) => TreeMonoid a (PrimState m) -> Vertex -> m a+read TreeMonoid {..} i_ = do+  let !i = Hld.indexHld hldTM VG.! i_+  ST.read segFTM i++-- | \(O(\log n)\) Write a `TreeMonoid` value on a `Vertex`.+--+-- @since 1.1.0.0+write :: (HasCallStack, PrimMonad m, Monoid a, VU.Unbox a) => TreeMonoid a (PrimState m) -> Vertex -> a -> m ()+write TreeMonoid {..} i_ x = do+  let !i = Hld.indexHld hldTM VG.! i_+  ST.write segFTM i x+  when (commuteTM == NonCommute) $ do+    ST.write segBTM i $ Dual x++-- | \(O(\log n)\) Exchanges a `TreeMonoid` value on a `Vertex`.+--+-- @since 1.1.0.0+exchange :: (HasCallStack, PrimMonad m, Monoid a, VU.Unbox a) => TreeMonoid a (PrimState m) -> Vertex -> a -> m a+exchange TreeMonoid {..} i_ x = do+  let !i = Hld.indexHld hldTM VG.! i_+  !res <- ST.exchange segFTM i x+  when (commuteTM == NonCommute) $ do+    ST.write segBTM i $ Dual x+  pure res++-- | \(O(\log n)\) Modifies a `TreeMonoid` value on a `Vertex`.+--+-- @since 1.1.0.0+modify :: (HasCallStack, PrimMonad m, Monoid a, VU.Unbox a) => TreeMonoid a (PrimState m) -> (a -> a) -> Int -> m ()+modify TreeMonoid {..} f i_ = do+  let !i = Hld.indexHld hldTM VG.! i_+  ST.modify segFTM f i+  when (commuteTM == NonCommute) $ do+    ST.modify segBTM (Dual . f . getDual) i++-- | \(O(\log n)\) Modifies a `TreeMonoid` value on a `Vertex`.+--+-- @since 1.1.0.0+modifyM :: (HasCallStack, PrimMonad m, Monoid a, VU.Unbox a) => TreeMonoid a (PrimState m) -> (a -> m a) -> Int -> m ()+modifyM TreeMonoid {..} f i_ = do+  let !i = Hld.indexHld hldTM VG.! i_+  ST.modifyM segFTM f i+  when (commuteTM == NonCommute) $ do+    ST.modifyM segBTM ((Dual <$>) . f . getDual) i
+ src/AtCoder/Extra/WaveletMatrix.hs view
@@ -0,0 +1,407 @@+{-# 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+    rawWM :: !Rwm.RawWaveletMatrix,+    -- | Index compression dictionary.+    --+    -- @since 1.1.0.0+    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 ys =+  let !xDictWM = VU.uniq $ VU.modify (VAI.sortBy compare) ys+      !ys' = VU.map (fromJust . lowerBound xDictWM) ys+      !rawWM = Rwm.build (VG.length ys) ys'+   in WaveletMatrix {..}++-- | \(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 {..} i = (xDictWM VG.!) <$> Rwm.access rawWM 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 wm l r y = rankBetween wm l r y (y + 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 {..} l r y1 y2+  | not $ 0 <= l && l < r && r <= n = 0+  | y1' >= y2' = 0+  | otherwise = Rwm.rankBetween rawWM l r y1' y2'+  where+    -- Handles the case @yl@ or  @yr@ is not in the dict+    n = Rwm.lengthRwm rawWM+    y1' = fromMaybe n (bisectR 0 (VG.length xDictWM) ((< y1) . VG.unsafeIndex xDictWM))+    y2' = maybe (-1) (+ 1) (bisectL 0 (VG.length xDictWM) ((< y2) . VG.unsafeIndex 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 wm = selectKth wm 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 {..} k y = do+  i <- lowerBound xDictWM y+  -- TODO: we don't need such an explicit branch?+  let !y' = xDictWM VG.! i+  guard $ y' == y+  Rwm.selectKth rawWM k 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 wm l r = selectKthIn wm l r 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 {..} l r k y = do+  i <- lowerBound xDictWM y+  -- TODO: we don't need such an explicit branch?+  let !y' = xDictWM VG.! i+  guard $ y' == y+  Rwm.selectKthIn rawWM l r k 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 {..} l r k+  | Just !y <- Rwm.kthLargestIn rawWM l r k = Just $ xDictWM VG.! y+  | otherwise = 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 {..} l r k+  | Just (!i, !y) <- Rwm.ikthLargestIn rawWM l r k = Just (i, xDictWM VG.! y)+  | otherwise = 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 {..} l r k+  | Just !y <- Rwm.kthSmallestIn rawWM l r k = Just $ xDictWM VG.! y+  | otherwise = 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 {..} l r k+  | Just (!i, !y) <- Rwm.ikthSmallestIn rawWM l r k = Just (i, xDictWM VG.! y)+  | otherwise = Nothing++-- | \(O(\log |S|)\)+--+-- @since 1.1.0.0+{-# INLINE unsafeKthSmallestIn #-}+unsafeKthSmallestIn :: WaveletMatrix -> Int -> Int -> Int -> Int+unsafeKthSmallestIn WaveletMatrix {..} l r k =+  xDictWM VG.! Rwm.unsafeKthSmallestIn rawWM l r 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 wm l r y0+  | r' == l' = Nothing+  | rank_ == 0 = Nothing+  | otherwise = Just $ unsafeKthSmallestIn wm l' r' (rank_ - 1)+  where+    -- clamp+    l' = max 0 l+    r' = min (Rwm.lengthRwm (rawWM wm)) r+    rank_ = rankBetween wm l' r' minBound (y0 + 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 wm l r y0 = lookupLE wm l r (y0 - 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 wm l r y0+  | r' == l' = Nothing+  | rank_ >= r - l = Nothing+  | otherwise = Just $ unsafeKthSmallestIn wm l r rank_+  where+    -- clamp+    l' = max 0 l+    r' = min (Rwm.lengthRwm (rawWM wm)) r+    rank_ = rankBetween wm l' r' minBound 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 wm l r y0 = lookupGE wm l r (y0 + 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 {..} l r = Rwm.assocsWith rawWM l r (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 {..} l r = Rwm.descAssocsInWith rawWM l r (xDictWM VG.!)
+ src/AtCoder/Extra/WaveletMatrix/BitVector.hs view
@@ -0,0 +1,179 @@+{-# LANGUAGE RecordWildCards #-}++-- | A compact bit vector, a collection of bits that can process @rank@ in \(O(1)\) and @select@ in+-- \(O(\log n)\).+--+-- @since 1.1.0.0+module AtCoder.Extra.WaveletMatrix.BitVector+  ( -- * Bit vector+    BitVector (..),++    -- * Constructor+    build,++    -- * (Internal) Word-based cumultaive sum+    wordSize,+    csumInPlace,++    -- * Rank+    rank0,+    rank1,++    -- * Select+    select0,+    select1,+    selectKthIn0,+    selectKthIn1,+  )+where++import AtCoder.Extra.Bisect (bisectL)+import Control.Monad.Primitive (PrimMonad (PrimState))+import Data.Bit (Bit (..))+import Data.Bits (popCount)+import Data.Vector.Generic qualified as VG+import Data.Vector.Generic.Mutable qualified as VGM+import Data.Vector.Unboxed qualified as VU+import Data.Vector.Unboxed.Mutable qualified as VUM++-- | A compact bit vector.+--+-- @since 1.1.0.0+data BitVector = BitVector+  { -- | Packed bits.+    --+    -- @since 1.1.0.0+    bitsBv :: !(VU.Vector Bit),+    -- | Cumulative sum of bits by 64 words.+    --+    -- @since 1.1.0.0+    csumBv :: !(VU.Vector Int)+    -- we could use Word32 for csumBv, as 2^32 is large enough+  }+  deriving (Eq, Show)++-- | \(O(n)\) Creates a `BitVector`.+--+-- @since 1.1.0.0+{-# INLINE build #-}+build :: VU.Vector Bit -> BitVector+build bitsBv =+  let csumBv = VU.create $ do+        vec <- VUM.replicate ((VU.length bitsBv + 63) `div` 64 + 1) 0+        _ <- csumInPlace vec bitsBv+        pure vec+   in BitVector {..}++-- | The block size \(64\) for the internal cumultaive sum in the bit vector.+--+-- @since 1.1.0.0+{-# INLINE wordSize #-}+wordSize :: Int+wordSize = 64++-- | \(O(n)\) Calculates the cumulative sum in-place for the bit vector and returns the sum.+--+-- @since 1.1.0.0+{-# INLINE csumInPlace #-}+csumInPlace ::+  (PrimMonad m) =>+  -- | Cumulative sum of length \(\lceil |\mathrm{bits}| / 64 \rceil\).+  VUM.MVector (PrimState m) Int ->+  -- | Bits+  VU.Vector Bit ->+  -- | Sum of the bits+  m Int+csumInPlace csum bits = do+  VGM.unsafeWrite csum 0 (0 :: Int)++  -- Calcuate popCount by word. TODO: use `castToWords` for most elements+  VU.ifoldM'+    ( \ !acc i wordSum -> do+        let !acc' = acc + wordSum+        VGM.unsafeWrite csum (i + 1) acc'+        pure acc'+    )+    (0 :: Int)+    $ VU.unfoldrExactN+      (VGM.length csum - 1)+      (\bits' -> (popCount (VU.take wordSize bits'), VU.drop wordSize bits'))+      bits++-- | \(O(1)\) Counts the number of \(0\) bits in the interval \([0, i)\).+--+-- @since 1.1.0.0+{-# INLINE rank0 #-}+rank0 :: BitVector -> Int -> Int+rank0 bv i = i - rank1 bv i++-- | \(O(1)\) Counts the number of \(1\) bits in an interval \([0, i)\).+--+-- @since 1.1.0.0+{-# INLINE rank1 #-}+rank1 :: BitVector -> Int -> Int+rank1 BitVector {..} i = fromCSum + fromRest+  where+    -- TODO: check bounds for i?+    (!nWords, !nRest) = i `divMod` wordSize+    fromCSum = VG.unsafeIndex csumBv nWords+    fromRest = popCount . VU.take nRest . VU.drop (nWords * wordSize) $ bitsBv++-- | \(O(\log n)\) Returns the index of \(k\)-th \(0\) (0-based), or `Nothing` if no such bit exists.+--+-- @since 1.1.0.0+{-# INLINE select0 #-}+select0 :: BitVector -> Int -> Maybe Int+select0 bv = selectKthIn0 bv 0 (VG.length (bitsBv bv))++-- | \(O(\log n)\) Returns the index of \(k\)-th \(1\) (0-based), or `Nothing` if no such bit exists.+--+-- @since 1.1.0.0+{-# INLINE select1 #-}+select1 :: BitVector -> Int -> Maybe Int+select1 bv = selectKthIn1 bv 0 (VG.length (bitsBv bv))++-- | \(O(\log n)\) Returns the index of \(k\)-th \(0\) (0-based) in \([l, r)\), or `Nothing` if no+-- such bit exists.+--+-- @since 1.1.0.0+{-# INLINE selectKthIn0 #-}+selectKthIn0 ::+  -- | A bit vector+  BitVector ->+  -- | \(l\)+  Int ->+  -- | \(r\)+  Int ->+  -- | \(k\)+  Int ->+  -- | The index of \(k\)-th \(0\) in \([l, r)\)+  Maybe Int+selectKthIn0 bv l r k+  | k < 0 || nZeros <= k = Nothing+  | otherwise = bisectL l r $ \i -> rank0 bv i - rankL0 < k + 1+  where+    nZeros = rank0 bv r - rankL0+    rankL0 = rank0 bv l++-- | \(O(\log n)\) Returns the index of \(k\)-th \(1\) (0-based) in \([l, r)\), or `Nothing` if no+-- such bit exists.+--+-- @since 1.1.0.0+{-# INLINE selectKthIn1 #-}+selectKthIn1 ::+  -- | A bit vector+  BitVector ->+  -- | \(l\)+  Int ->+  -- | \(r\)+  Int ->+  -- | \(k\)+  Int ->+  -- | The index of \(k\)-th \(1\) in \([l, r)\)+  Maybe Int+selectKthIn1 bv l r k+  | k < 0 || nOnes <= k = Nothing+  | otherwise = bisectL l r $ \i -> rank1 bv i - rankL1 < k + 1+  where+    nOnes = rank1 bv r - rankL1+    rankL1 = rank1 bv l
+ src/AtCoder/Extra/WaveletMatrix/Raw.hs view
@@ -0,0 +1,651 @@+{-# LANGUAGE RecordWildCards #-}++-- original implementation:+-- <https://miti-7.hatenablog.com/entry/2018/04/28/152259>++-- NOTE: We could integrate cumulative sum / fenwick tree / segment tree.+-- NOTE: `topK` and `intersects` are not implemented as they are slow.++-- | A static Wavelet Matrix without automatic index comperssion. Consider using+-- @AtCoder.Extra.WaveletMatrix@ instead.+--+-- @since 1.1.0.0+module AtCoder.Extra.WaveletMatrix.Raw+  ( -- * RawWaveletMatrix+    RawWaveletMatrix (..),++    -- * Constructors+    build,++    -- * Access (indexing)+    access,++    -- * rank+    rankLT,+    rank,+    rankBetween,++    -- * Select+    select,+    selectKth,+    selectIn,+    selectKthIn,++    -- * Quantile (value-ordered access)++    -- ** Safe (total)+    kthSmallestIn,+    ikthSmallestIn,+    kthLargestIn,+    ikthLargestIn,++    -- ** Unsafe+    unsafeKthSmallestIn,+    unsafeIKthSmallestIn,+    unsafeKthLargestIn,+    unsafeIKthLargestIn,++    -- * Lookup+    lookupLE,+    lookupLT,+    lookupGE,+    lookupGT,++    -- * Conversions+    assocsIn,+    assocsWith,+    descAssocsIn,+    descAssocsInWith,+  )+where++import AtCoder.Extra.WaveletMatrix.BitVector qualified as BV+import AtCoder.Internal.Assert qualified as ACIA+import AtCoder.Internal.Bit qualified as ACIB+import Control.Monad.ST (runST)+import Data.Bit (Bit (..))+import Data.Bits (bit, countTrailingZeros, setBit, testBit, (.|.))+import Data.Maybe+import Data.Vector qualified as V+import Data.Vector.Algorithms.Radix qualified as VAR+import Data.Vector.Generic qualified as VG+import Data.Vector.Generic.Mutable qualified as VGM+import Data.Vector.Unboxed qualified as VU+import Data.Vector.Unboxed.Mutable qualified as VUM+import GHC.Stack (HasCallStack)++-- | A static Wavelet Matrix without automatic index comperssion.+--+-- @since 1.1.0.0+data RawWaveletMatrix = RawWaveletMatrix+  { -- | \(\lceil \log_2 N \rceil\).+    --+    -- @since 1.1.0.0+    heightRwm :: {-# UNPACK #-} !Int,+    -- | The length of the original array.+    --+    -- @since 1.1.0.0+    lengthRwm :: {-# UNPACK #-} !Int,+    -- | The bit matrix. Each row represents (heightRwm - 1 - iRow) bit's on/off.+    --+    -- @since 1.1.0.0+    bitsRwm :: !(V.Vector BV.BitVector),+    -- | The number of zeros bits in each row in the bit matrix.+    --+    -- @since 1.1.0.0+    nZerosRwm :: !(VU.Vector Int)+  }+  deriving (Eq, Show)++-- | \(O(n \log n)\) Creates a `RawWaveletMatrix` from a vector \(a\).+--+-- @since 1.1.0.0+{-# INLINE build #-}+build ::+  (HasCallStack) =>+  -- | The number of different values in the compressed vector.+  Int ->+  -- | A compressed vector+  VU.Vector Int ->+  -- | A wavelet matrix+  RawWaveletMatrix+build nx xs+  | nx < 0 = error "AtCoder.Extra.WaveletMatrix.Raw.build: given negative `n`"+  | otherwise = runST $ do+      -- TODO: less mutable variables+      orgBits <- VUM.replicate (lengthRwm * heightRwm) $ Bit False+      orgCsum <- VUM.replicate (lenCSum * heightRwm) (0 :: Int)+      nZeros <- VUM.unsafeNew heightRwm++      -- views by row over the contiguous memory:+      let !bits = V.unfoldrExactN heightRwm (VUM.splitAt lengthRwm) orgBits+      let !csums = V.unfoldrExactN heightRwm (VUM.splitAt lenCSum) orgCsum++      -- the vector will be sorted by bits.+      vec <- VU.thaw xs+      V.izipWithM_+        ( \iRow bitVec csum -> do+            let !iBit = heightRwm - 1 - iRow+            vec' <- VU.unsafeFreeze vec+            VU.iforM_ vec' $ \i x -> do+              VGM.unsafeWrite bitVec i . Bit $ testBit x iBit++            -- csum.+            VGM.unsafeWrite csum 0 (0 :: Int)+            bitVec' <- VU.unsafeFreeze bitVec++            -- get popCount by word. TODO: use `castToWords` for most elements+            nOnes <- BV.csumInPlace csum bitVec'+            VGM.unsafeWrite nZeros iRow (lengthRwm - nOnes)++            -- preform a stable sort by the bit:+            VAR.sortBy 2 2 (\_ x -> fromEnum (testBit x iBit)) vec+        )+        bits+        csums+      nZerosRwm <- VU.unsafeFreeze nZeros+      bits' <- V.unfoldrExactN heightRwm (VU.splitAt lengthRwm) <$> VU.unsafeFreeze orgBits+      csums' <- V.unfoldrExactN heightRwm (VU.splitAt lenCSum) <$> VU.unsafeFreeze orgCsum+      let !bitsRwm = V.zipWith BV.BitVector bits' csums'+      pure $ RawWaveletMatrix {..}+  where+    !lengthRwm = VG.length xs+    !lenCSum = (lengthRwm + BV.wordSize - 1) `div` BV.wordSize + 1 -- +1 for the zero+    !heightRwm = countTrailingZeros $ ACIB.bitCeil nx++-- | \(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 :: RawWaveletMatrix -> Int -> Maybe Int+access RawWaveletMatrix {..} i0+  | ACIA.testIndex i0 lengthRwm =+      let (!_, !res) =+            V.ifoldl'+              ( \(!i, !acc) !iRow !bits ->+                  let Bit !goRight = VG.unsafeIndex (BV.bitsBv bits) i+                      !i'+                        | goRight = BV.rank1 bits i + VG.unsafeIndex nZerosRwm iRow+                        | otherwise = BV.rank0 bits i+                      !acc'+                        | goRight = setBit acc (heightRwm - 1 - iRow)+                        | otherwise = acc+                   in (i', acc')+              )+              (i0, 0)+              bitsRwm+       in Just res+  | otherwise = Nothing++-- | \(O(\log |A|)\) Goes down the wavelet matrix for collecting the kth smallest value.+--+-- @since 1.1.0.0+{-# INLINE goDown #-}+goDown :: RawWaveletMatrix -> Int -> Int -> Int -> (Int, Int, Int, Int)+goDown RawWaveletMatrix {..} l_ r_ k_ = V.ifoldl' step (0 :: Int, l_, r_, k_) bitsRwm+  where+    -- It's binary search over the value range. In each row, we'll focus on either 0 bit values or+    -- 1 bit values in [l, r) and update the range to [l', r').+    step (!acc, !l, !r, !k) !iRow !bits+      -- `r0 - l0`, the number of zeros in [l, r), is bigger than or equal to k:+      -- Go left.+      | k < r0 - l0 = (acc, l0, r0, k)+      -- Go right.+      | otherwise =+          let !acc' = acc .|. bit (heightRwm - 1 - iRow)+              !nZeros = VG.unsafeIndex nZerosRwm iRow+              -- every zero bits come to the left after the move.+              !l' = l + nZeros - l0 -- add the number of zeros in [0, l)+              !r' = r + nZeros - r0 -- add the number of zeros in [0, r)+              !k' = k - (r0 - l0) -- `r0 - l0` zeros go left+           in (acc', l', r', k')+      where+        !l0 = BV.rank0 bits l+        !r0 = BV.rank0 bits r++-- | \(O(\log |A|)\) Goes up the wavelet matrix for collecting the value \(x\).+--+-- @since 1.1.0.0+{-# INLINE goUp #-}+goUp :: RawWaveletMatrix -> Int -> Int -> Maybe Int+goUp RawWaveletMatrix {..} i0 x =+  V.ifoldM'+    ( \ !i !iBit !bits ->+        if testBit x iBit+          then BV.select1 bits $ i - nZerosRwm VG.! (heightRwm - 1 - iBit)+          else BV.select0 bits i+    )+    i0+    (V.reverse bitsRwm)++-- | \(O(\log |S|)\) Returns the number of \(y\) in \([l, r) \times [0, y_0)\).+--+-- @since 1.1.0.0+{-# INLINE rankLT #-}+rankLT :: RawWaveletMatrix -> Int -> Int -> Int -> Int+rankLT RawWaveletMatrix {..} l_ r_ xr+  -- REMARK: This is required. The function below cannot handle the case N = 2^i and xr = N.+  | xr >= bit heightRwm = r'_ - l'_+  | xr <= 0 = 0+  | r'_ <= l'_ = 0+  | otherwise =+      let (!res, !_, !_) = V.ifoldl' step (0, l'_, r'_) bitsRwm+       in res+  where+    -- clamp+    l'_ = max 0 l_+    r'_ = min lengthRwm r_+    -- [l, r)+    step (!acc, !l, !r) !iRow !bits =+      let !b = testBit xr (heightRwm - 1 - iRow)+          !l0 = BV.rank0 bits l+          !r0 = BV.rank0 bits r+       in if b+            then (acc + r0 - l0, l - l0 + VG.unsafeIndex nZerosRwm iRow, r - r0 + VG.unsafeIndex nZerosRwm iRow)+            else (acc, l0, r0)++-- | \(O(\log |S|)\) Returns the number of \(y\) in \([l, r)\).+--+-- @since 1.1.0.0+{-# INLINE rank #-}+rank ::+  RawWaveletMatrix ->+  -- | \(l\)+  Int ->+  -- | \(r\)+  Int ->+  -- | \(y\)+  Int ->+  -- | The number of \(y\) in \([l, r)\).+  Int+rank wm l r x = rankBetween wm l r x (x + 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 ::+  RawWaveletMatrix ->+  -- | \(l\)+  Int ->+  -- | \(r\)+  Int ->+  -- | \(y_1\)+  Int ->+  -- | \(y_2\)+  Int ->+  -- | The number of \(y\) in \([l, r) \times [y_1, y_2)\).+  Int+rankBetween wm l r lx rx = rankLT wm l r rx - rankLT wm l r lx++-- | \(O(\log |S|)\) Returns the index of the first \(y\) in the sequence, or `Nothing` if \(y\) is+-- not found.+--+-- @since 1.1.0.0+{-# INLINE select #-}+select :: RawWaveletMatrix -> Int -> Maybe Int+select wm = selectKth wm 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 ::+  RawWaveletMatrix ->+  -- | \(k\)+  Int ->+  -- | \(y\)+  Int ->+  -- | The index of \(k\)-th \(y\)+  Maybe Int+selectKth wm = selectKthIn wm 0 (lengthRwm wm)++-- | \(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+  RawWaveletMatrix ->+  -- | \(l\)+  Int ->+  -- | \(r\)+  Int ->+  -- | \(k\)+  Int ->+  -- | The index of the first \(y\) in \([l, r)\).+  Maybe Int+selectIn wm = selectKthIn wm 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 ::+  RawWaveletMatrix ->+  -- | \(l\)+  Int ->+  -- | \(r\)+  Int ->+  -- | \(k\)+  Int ->+  -- | \(y\)+  Int ->+  -- | The index of the \(k\)-th \(y\) in \([l, r)\).+  Maybe Int+selectKthIn wm@RawWaveletMatrix {..} l_ r_ k x+  | not (0 <= x && x < lengthRwm && 0 <= k && k < lengthRwm) = Nothing+  | l'_ < r'_ = inner+  | otherwise = Nothing+  where+    -- clamp+    l'_ = max 0 l_+    r'_ = min lengthRwm r_+    inner :: Maybe Int+    inner+      | rEnd <= lEnd + k = Nothing+      -- go up+      | otherwise = goUp wm (lEnd + k) x+      where+        -- TODO: replace with goDown+        -- Go down. Gets the [l, r) range of @x@ in the last array.+        (!lEnd, !rEnd) =+          V.ifoldl'+            ( \(!l, !r) !iRow !bits ->+                let !l0 = BV.rank0 bits l+                    !r0 = BV.rank0 bits r+                 in if testBit x (heightRwm - 1 - iRow)+                      then (l + nZerosRwm VG.! iRow - l0, r + nZerosRwm VG.! iRow - r0)+                      else (l0, r0)+            )+            (l'_, r'_)+            bitsRwm++-- | \(O(\log |S|)\) Given an interval \([l, r)\), it returns the index of the \(k\)-th (0-based)+-- largest value. Note that duplicated values are counted as distinct occurrences.+--+-- @since 1.1.0.0+{-# INLINE kthLargestIn #-}+kthLargestIn ::+  -- | A wavelet matrix+  RawWaveletMatrix ->+  -- | \(l\)+  Int ->+  -- | \(r\)+  Int ->+  -- | \(k\)+  Int ->+  -- | \(k\)-th largest \(y\) in \([l, r)\)+  Maybe Int+kthLargestIn wm l r k+  | k < 0 || k >= r - l = Nothing+  | 0 <= l && l < r && r <= lengthRwm wm = Just $ unsafeKthLargestIn wm l r k+  | otherwise = Nothing++-- | \(O(\log |S|)\) Given an interval \([l, r)\), it returns both the index and the value of the+-- \(k\)-th (0-based) largest value. Note that duplicated values are counted as distinct occurrences.+--+-- @since 1.1.0.0+{-# INLINE ikthLargestIn #-}+ikthLargestIn ::+  -- | A wavelet matrix+  RawWaveletMatrix ->+  -- | \(l\)+  Int ->+  -- | \(r\)+  Int ->+  -- | \(k\)+  Int ->+  -- | \((i, y)\) for \(k\)-th largest \(y\) in \([l, r)\)+  Maybe (Int, Int)+ikthLargestIn wm l r k+  | k < 0 || k >= r - l = Nothing+  | 0 <= l && l < r && r <= lengthRwm wm = Just $ unsafeIKthLargestIn wm l r k+  | otherwise = Nothing++-- | \(O(\log |S|)\) Given an interval \([l, r)\), it returns the index of the \(k\)-th (0-based)+-- smallest value. Note that duplicated values are counted as distinct occurrences.+--+-- @since 1.1.0.0+{-# INLINE kthSmallestIn #-}+kthSmallestIn ::+  -- | A wavelet matrix+  RawWaveletMatrix ->+  -- | \(l\)+  Int ->+  -- | \(r\)+  Int ->+  -- | \(k\)+  Int ->+  -- | \(k\)-th largest \(y\) in \([l, r)\)+  Maybe Int+kthSmallestIn wm l r k+  | k < 0 || k >= r - l = Nothing+  | 0 <= l && l < r && r <= lengthRwm wm = Just $ unsafeKthSmallestIn wm l r k+  | otherwise = Nothing++-- | \(O(\log |S|)\) Given an interval \([l, r)\), it returns both the index and the value of the+-- \(k\)-th (0-based) smallest value. Note that duplicated values are counted as distinct occurrences.+--+-- @since 1.1.0.0+{-# INLINE ikthSmallestIn #-}+ikthSmallestIn ::+  RawWaveletMatrix ->+  -- | \(l\)+  Int ->+  -- | \(r\)+  Int ->+  -- | \(k\)+  Int ->+  -- | \((i, y)\) for \(k\)-th largest \(y\) in \([l, r)\)+  Maybe (Int, Int)+ikthSmallestIn wm l r k+  | k < 0 || k >= r - l = Nothing+  | 0 <= l && l < r && r <= lengthRwm wm = Just $ unsafeIKthSmallestIn wm l r k+  | otherwise = Nothing++-- | \(O(\log a)\) Returns \(k\)-th (0-based) biggest number in \([l, r)\). Note that duplicated+-- values are counted as distinct occurrences.+--+-- @since 1.1.0.0+{-# INLINE unsafeKthLargestIn #-}+unsafeKthLargestIn :: RawWaveletMatrix -> Int -> Int -> Int -> Int+unsafeKthLargestIn wm l r k = unsafeKthSmallestIn wm l r (r - l - (k + 1))++-- | \(O(\log a)\)+--+-- @since 1.1.0.0+{-# INLINE unsafeIKthLargestIn #-}+unsafeIKthLargestIn :: RawWaveletMatrix -> Int -> Int -> Int -> (Int, Int)+unsafeIKthLargestIn wm l r k = unsafeIKthSmallestIn wm l r (r - l - (k + 1))++-- | \(O(\log a)\)+--+-- @since 1.1.0.0+{-# INLINE unsafeKthSmallestIn #-}+unsafeKthSmallestIn :: RawWaveletMatrix -> Int -> Int -> Int -> Int+unsafeKthSmallestIn wm l_ r_ k_ =+  let (!x, !_, !_, !_) = goDown wm l_ r_ k_+   in x++-- | \(O(\log a)\)+--+-- @since 1.1.0.0+{-# INLINE unsafeIKthSmallestIn #-}+unsafeIKthSmallestIn :: RawWaveletMatrix -> Int -> Int -> Int -> (Int, Int)+unsafeIKthSmallestIn wm l_ r_ k_ =+  let (!x, !l, !_, !k) = goDown wm l_ r_ k_+      !i' = fromJust $ goUp wm (l + k) x+   in (i', x)++-- | \(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+  RawWaveletMatrix ->+  -- | \(l\)+  Int ->+  -- | \(r\)+  Int ->+  -- | \(y_0\)+  Int ->+  -- | Maximum \(y\) in \([l, r) \times (-\infty, y_0]\)+  Maybe Int+lookupLE wm l r x+  | r' == l' = Nothing+  | rank_ == 0 = Nothing+  | otherwise = Just $ unsafeKthSmallestIn wm l' r' (rank_ - 1)+  where+    -- clamp+    l' = max 0 l+    r' = min (lengthRwm wm) r+    rank_ = rankBetween wm l r minBound (x + 1)++-- | \(O(\log a)\) Finds the maximum \(x\) in \([l, r)\) s.t. \(x_{0} \lt x\).+--+-- @since 1.1.0.0+{-# INLINE lookupLT #-}+lookupLT ::+  RawWaveletMatrix ->+  -- | \(l\)+  Int ->+  -- | \(r\)+  Int ->+  -- | \(x\)+  Int ->+  -- | Maximum \(y\) in \([l, r) \times (-\infty, y_0)\)+  Maybe Int+lookupLT wm l r x = lookupLE wm l r (x - 1)++-- | \(O(\log |S|)\) Looks up the minimum \(y\) in \([l, r) \times [y_0, \infty)\).+--+-- @since 1.1.0.0+{-# INLINE lookupGE #-}+lookupGE ::+  RawWaveletMatrix ->+  -- | \(l\)+  Int ->+  -- | \(r\)+  Int ->+  -- | \(y_0\)+  Int ->+  -- | Minimum \(y\) in \([l, r) \times [y_0, \infty)\).+  Maybe Int+lookupGE wm l r x+  | r' == l' = Nothing+  | rank_ >= r' - l' = Nothing+  | otherwise =+      Just $ unsafeKthSmallestIn wm l' r' rank_+  where+    -- clamp+    l' = max 0 l+    r' = min (lengthRwm wm) r+    rank_ = rankBetween wm l' r' minBound x++-- | \(O(\log |S|)\) Looks up the minimum \(y\) in \([l, r) \times (y_0, \infty)\).+--+-- @since 1.1.0.0+{-# INLINE lookupGT #-}+lookupGT ::+  RawWaveletMatrix ->+  -- | \(l\)+  Int ->+  -- | \(r\)+  Int ->+  -- | \(y_0\)+  Int ->+  -- | Minimum \(y\) in \([l, r) \times (y_0, \infty)\)+  Maybe Int+lookupGT wm l r x = lookupGE wm l r (x + 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 :: RawWaveletMatrix -> Int -> Int -> [(Int, Int)]+assocsIn wm l r = assocsWith wm l r id++-- | \(O(\log A \min(|A|, L))\) Internal implementation of `assocs`.+--+-- @since 1.1.0.0+{-# INLINE assocsWith #-}+assocsWith :: RawWaveletMatrix -> Int -> Int -> (Int -> Int) -> [(Int, Int)]+assocsWith RawWaveletMatrix {..} l_ r_ f+  | l'_ < r'_ = inner (0 :: Int) (0 :: Int) l'_ r'_ []+  | otherwise = []+  where+    -- clamp+    l'_ = max 0 l_+    r'_ = min lengthRwm r_+    -- DFS. [l, r)+    inner !acc iRow !l !r res+      | iRow >= heightRwm =+          let !n = r - l+              !acc' = f acc+           in (acc', n) : res+      | otherwise = do+          let !bits = bitsRwm VG.! iRow+              !l0 = BV.rank0 bits l+              !r0 = BV.rank0 bits r+              !nZeros = nZerosRwm VG.! iRow+              -- go right (visit bigger values first)+              !l' = l + nZeros - l0+              !r' = r + nZeros - r0+              !res'+                | l' < r' = inner (acc .|. bit (heightRwm - 1 - iRow)) (iRow + 1) l' r' res+                | otherwise = res+              !res''+                -- go left+                | l0 < r0 = inner acc (iRow + 1) l0 r0 res'+                | otherwise = res'+           in res''++-- | \(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 :: RawWaveletMatrix -> Int -> Int -> [(Int, Int)]+descAssocsIn wm l r = descAssocsInWith wm l r id++-- | \(O(\log A \min(|A|, L))\) Internal implementation of `descAssoc`.+--+-- @since 1.1.0.0+{-# INLINE descAssocsInWith #-}+descAssocsInWith :: RawWaveletMatrix -> Int -> Int -> (Int -> Int) -> [(Int, Int)]+descAssocsInWith RawWaveletMatrix {..} l_ r_ f+  | l'_ < r'_ = inner (0 :: Int) (0 :: Int) l'_ r'_ []+  | otherwise = []+  where+    -- clamp+    l'_ = max 0 l_+    r'_ = min lengthRwm r_+    -- DFS. [l, r)+    inner !acc iRow !l !r res+      | iRow >= heightRwm =+          let !n = r - l+              !acc' = f acc+           in (acc', n) : res+      | otherwise = do+          let !bits = bitsRwm VG.! iRow+              !l0 = BV.rank0 bits l+              !r0 = BV.rank0 bits r+              !nZeros = nZerosRwm VG.! iRow+              !res'+                -- go left+                | l0 < r0 = inner acc (iRow + 1) l0 r0 res+                | otherwise = res+              -- go right (visit bigger values first)+              !l' = l + nZeros - l0+              !r' = r + nZeros - r0+              !res''+                | l' < r' = inner (acc .|. bit (heightRwm - 1 - iRow)) (iRow + 1) l' r' res'+                | otherwise = res'+           in res''
+ src/AtCoder/Extra/WaveletMatrix2d.hs view
@@ -0,0 +1,277 @@+{-# LANGUAGE RecordWildCards #-}++-- | A 2D, static wavelet matrix with segment tree, that can handle point add and rectangle sum+-- queries. Points cannot be added after construction, but monoid values in each point can be+-- modified later.+--+-- ==== __Example__+-- Create a `WaveletMatrix2d` with initial vertex values:+--+-- >>> import AtCoder.Extra.WaveletMatrix2d qualified as WM+-- >>> import Data.Semigroup (Sum (..))+-- >>> import Data.Vector.Unboxed qualified as VU+-- >>> -- 8  9 10 11+-- >>> -- 4  5  6  7+-- >>> -- 0  1  2  3+-- >>> wm <- WM.build negate $ VU.generate 12 $ \i -> let (!y, !x) = i `divMod` 4 in (x, y, Sum i)+--+-- Read the value at \(x = 2, y = 1\):+--+-- >>> WM.read wm (2, 1)+-- Sum {getSum = 6}+--+-- Other segment tree methods are also available, but in 2D:+--+-- >>> WM.allProd wm -- (0 + 11) * 12 / 2 = 66+-- Sum {getSum = 66}+--+-- >>> WM.prod wm {- x -} 1 3 {- y -} 0 3 -- 1 + 2 + 5 + 6 + 9 + 10+-- Sum {getSum = 33}+--+-- >>> WM.modify wm (+ 2) (1, 1)+-- >>> WM.prod wm {- x -} 1 3 {- y -} 0 3 -- 1 + 2 + 7 + 6 + 9 + 10+-- Sum {getSum = 35}+--+-- >>> WM.write wm (1, 1) $ Sum 0+-- >>> WM.prod wm {- x -} 1 3 {- y -} 0 3 -- 1 + 2 + 0 + 6 + 9 + 10+-- Sum {getSum = 28}+module AtCoder.Extra.WaveletMatrix2d+  ( -- * Wavelet matrix 2D+    WaveletMatrix2d (..),++    -- * Counstructor+    new,+    build,++    -- * Segment tree methods+    read,+    write,+    modify,+    prod,+    prodMaybe,+    allProd,+    -- wavelet matrix methods could be implemented, too+  )+where++import AtCoder.Extra.Bisect (bisectR, lowerBound)+import AtCoder.Extra.WaveletMatrix.BitVector qualified as BV+import AtCoder.Extra.WaveletMatrix.Raw qualified as Rwm+import AtCoder.Internal.Assert qualified as ACIA+import AtCoder.SegTree qualified as ST+import Control.Monad.Primitive (PrimMonad, PrimState)+import Data.Bit (Bit (..))+import Data.Bits (Bits (testBit))+import Data.Maybe (fromJust, fromMaybe)+import Data.Vector qualified as V+import Data.Vector.Algorithms.Intro qualified as VAI+import Data.Vector.Generic qualified as VG+import Data.Vector.Unboxed qualified as VU+import GHC.Stack (HasCallStack)+import Prelude hiding (read)++-- NOTE: There are many possible improvements.+-- - Use cumulative sum or fenwick tree instead for the speed.+-- - The inverse operator is not actually required.+-- - Wavelet matrix methods such as `rank` can be implemented+-- - `maxRight` can be implemented.++-- | Segment Tree on Wavelet Matrix: points on a 2D plane and rectangle products.+data WaveletMatrix2d s a = WaveletMatrix2d+  { -- | The wavelet matrix that represents points on a 2D plane.+    rawWmWm2d :: !Rwm.RawWaveletMatrix,+    -- | (x, y) index compression dictionary.+    xyDictWm2d :: !(VU.Vector (Int, Int)),+    -- | y index compression dictionary.+    yDictWm2d :: !(VU.Vector Int),+    -- | The segment tree of the weights of the points in the order of `xyDictWm2d`.+    segTreesWm2d :: !(V.Vector (ST.SegTree s a)),+    -- | The inverse operator of the interested monoid.+    invWm2d :: !(a -> a)+  }++-- | \(O(n \log n)\) Creates a `WaveletMatrix2d` with `mempty` as the initial monoid+-- values for each point.+{-# INLINE new #-}+new ::+  (PrimMonad m, Monoid a, VU.Unbox a) =>+  -- | Inverse operator of the monoid+  (a -> a) ->+  -- | Input points+  VU.Vector (Int, Int) ->+  -- | A 2D wavelet matrix+  m (WaveletMatrix2d (PrimState m) a)+new invWm2d xys = do+  let n = VG.length xys+  let xyDictWm2d = VU.uniq . VU.modify (VAI.sortBy compare) $ xys+  let (!_, !ys) = VU.unzip xys+  let yDictWm2d = VU.uniq $ VU.modify (VAI.sortBy compare) ys+  -- REMARK: Be sure to use `n + 1` because the product function cannot handle the case+  --         `yUpper` is `2^{height}`.+  let (!_, !ysInput) = VU.unzip xyDictWm2d+  let rawWmWm2d = Rwm.build (n + 1) $ VU.map (fromJust . lowerBound yDictWm2d) ysInput+  segTreesWm2d <- V.replicateM (Rwm.heightRwm rawWmWm2d) (ST.new n)+  pure WaveletMatrix2d {..}++-- | \(O(n \log n)\) Creates a `WaveletMatrix2d` with wavelet matrix with segment tree+-- with initial monoid values. Monoids on a duplicate point are accumulated with `(<>)`.+{-# INLINE build #-}+build ::+  (PrimMonad m, Monoid a, VU.Unbox a) =>+  -- | Inverse operator of the monoid+  (a -> a) ->+  -- | Input points with initial values+  VU.Vector (Int, Int, a) ->+  -- | A 2D wavelet matrix+  m (WaveletMatrix2d (PrimState m) a)+build invWm2d xysw = do+  let (!xs, !ys, !_) = VU.unzip3 xysw+  wm <- new invWm2d $ VU.zip xs ys+  -- not the fastest implementation though+  VU.forM_ xysw $ \(!x, !y, !w) -> do+    modify wm (<> w) (x, y)+  pure wm++-- | \(O(1)\) Returns the monoid value at \((x, y)\).+{-# INLINE read #-}+read :: (HasCallStack, VU.Unbox a, Monoid a, PrimMonad m) => WaveletMatrix2d (PrimState m) a -> (Int, Int) -> m a+read WaveletMatrix2d {..} (!x, !y) = do+  ST.read (V.head segTreesWm2d) . fromJust $ lowerBound xyDictWm2d (x, y)++-- | \(O(\log^2 n)\) Writes the monoid value at \((x, y)\). Access to unknown points are undefined.+{-# INLINE write #-}+write :: (HasCallStack, Monoid a, VU.Unbox a, PrimMonad m) => WaveletMatrix2d (PrimState m) a -> (Int, Int) -> a -> m ()+write WaveletMatrix2d {..} (!x, !y) v = do+  let !i_ = fromJust $ lowerBound xyDictWm2d (x, y)+  V.ifoldM'_+    ( \i iRow (!bits, !seg) -> do+        let !i0 = BV.rank0 bits i+        let !i'+              | unBit $ VG.unsafeIndex (BV.bitsBv bits) i =+                  i + Rwm.nZerosRwm rawWmWm2d VG.! iRow - i0+              | otherwise = i0+        ST.write seg i' v+        pure i'+    )+    i_+    $ V.zip (Rwm.bitsRwm rawWmWm2d) segTreesWm2d++-- | \(O(\log^2 n)\) Modifies the monoid value at \((x, y)\). Access to unknown points are+-- undefined.+{-# INLINE modify #-}+modify :: (HasCallStack, Monoid a, VU.Unbox a, PrimMonad m) => WaveletMatrix2d (PrimState m) a -> (a -> a) -> (Int, Int) -> m ()+modify WaveletMatrix2d {..} f (!x, !y) = do+  let !i_ = fromJust $ lowerBound xyDictWm2d (x, y)+  V.ifoldM'_+    ( \i iRow (!bits, !seg) -> do+        let !i0 = BV.rank0 bits i+        let !i'+              | unBit $ VG.unsafeIndex (BV.bitsBv bits) i =+                  i + Rwm.nZerosRwm rawWmWm2d VG.! iRow - i0+              | otherwise = i0+        ST.modify seg f i'+        pure i'+    )+    i_+    $ V.zip (Rwm.bitsRwm rawWmWm2d) segTreesWm2d++-- | \(O(\log^2 n)\) Returns the monoid product in \([l, r) \times [y_1, y_2)\).+{-# INLINE prod #-}+prod :: (HasCallStack, VU.Unbox a, Monoid a, PrimMonad m) => WaveletMatrix2d (PrimState m) a -> Int -> Int -> Int -> Int -> m a+prod wm@WaveletMatrix2d {..} !xl !xr !yl !yr+  | xl' >= xr' || yl' >= yr' = pure mempty+  | otherwise = unsafeProd wm xl' xr' yl' yr'+  where+    (!xDict, !_) = VU.unzip xyDictWm2d+    -- NOTE: clamping here!+    xl' = fromMaybe 0 $ bisectR 0 (VG.length xDict) $ (< xl) . VG.unsafeIndex xDict+    xr' = fromMaybe (VG.length xDict) $ bisectR 0 (VG.length xDict) $ (< xr) . VG.unsafeIndex xDict+    yl' = fromMaybe 0 $ bisectR 0 (VG.length yDictWm2d) $ (< yl) . VG.unsafeIndex yDictWm2d+    yr' = fromMaybe (VG.length yDictWm2d) $ bisectR 0 (VG.length yDictWm2d) $ (< yr) . VG.unsafeIndex yDictWm2d+    !_ = ACIA.checkInterval "AtCoder.Extra.WaveletMatrix.SegTree.prod (compressed x)" xl' xr' (VG.length xDict)+    !_ = ACIA.checkInterval "AtCoder.Extra.WaveletMatrix.SegTree.prod (compressed y)" yl' yr' (VG.length yDictWm2d)++-- | \(O(\log^2 n)\) Returns the monoid product in \([l, r) \times [y_1, y_2)\). Returns `Nothing` for invalid+-- intervals.+{-# INLINE prodMaybe #-}+prodMaybe :: (VU.Unbox a, Monoid a, PrimMonad m) => WaveletMatrix2d (PrimState m) a -> Int -> Int -> Int -> Int -> m (Maybe a)+prodMaybe wm@WaveletMatrix2d {..} !xl !xr !yl !yr+  | not (ACIA.testInterval xl' xr' (VG.length xDict)) = pure Nothing+  | not (ACIA.testInterval yl' yr' (VG.length yDictWm2d)) = pure Nothing+  | xl' >= xr' || yl' >= yr' = pure $ Just mempty+  | otherwise = Just <$> unsafeProd wm xl' xr' yl' yr'+  where+    (!xDict, !_) = VU.unzip xyDictWm2d+    -- NOTE: clamping here!+    xl' = fromMaybe 0 $ bisectR 0 (VG.length xDict) $ (< xl) . VG.unsafeIndex xDict+    xr' = fromMaybe (VG.length xDict) $ bisectR 0 (VG.length xDict) $ (< xr) . VG.unsafeIndex xDict+    yl' = fromMaybe 0 $ bisectR 0 (VG.length yDictWm2d) $ (< yl) . VG.unsafeIndex yDictWm2d+    yr' = fromMaybe (VG.length yDictWm2d) $ bisectR 0 (VG.length yDictWm2d) $ (< yr) . VG.unsafeIndex yDictWm2d++-- | \(O(\log^2 n)\) Return the monoid product of all of the points in the wavelet matrix.+{-# INLINE allProd #-}+allProd :: (HasCallStack, VU.Unbox a, Monoid a, PrimMonad m) => WaveletMatrix2d (PrimState m) a -> m a+allProd WaveletMatrix2d {..} = do+  -- ST.allProd (V.last segTreesWm2d)+  ST.allProd (V.head segTreesWm2d)++-- | \(O(\log^2 n)\) The input is compressed indices.+{-# INLINE unsafeProd #-}+unsafeProd :: (VU.Unbox a, Monoid a, PrimMonad m) => WaveletMatrix2d (PrimState m) a -> Int -> Int -> Int -> Int -> m a+unsafeProd wm xl' xr' yl' yr' = do+  sR <- prodLT wm xl' xr' yr'+  sL <- prodLT wm xl' xr' yl'+  pure $! sR <> invWm2d wm sL++-- | \(O(\log^2 n)\)+{-# INLINE prodLT #-}+prodLT :: (Monoid a, VU.Unbox a, PrimMonad m) => WaveletMatrix2d (PrimState m) a -> Int -> Int -> Int -> m a+prodLT WaveletMatrix2d {..} !l_ !r_ yUpper = do+  (!res, !_, !_) <- do+    V.ifoldM'+      ( \(!acc, !l, !r) !iRow (!bits, !seg) -> do+          let !l0 = BV.rank0 bits l+              !r0 = BV.rank0 bits r+          -- REMARK: The function cannot handle the case yUpper = N = 2^i. See the constructor for+          -- how it's handled and note that l_ and r_ are compressed indices.+          if testBit yUpper (Rwm.heightRwm rawWmWm2d - 1 - iRow)+            then do+              !acc' <- (acc <>) <$> ST.prod seg l0 r0+              let !l' = l + Rwm.nZerosRwm rawWmWm2d VG.! iRow - l0+              let !r' = r + Rwm.nZerosRwm rawWmWm2d VG.! iRow - r0+              pure (acc', l', r')+            else do+              pure (acc, l0, r0)+      )+      (mempty, l_, r_)+      $ V.zip (Rwm.bitsRwm rawWmWm2d) segTreesWm2d+  pure res++-- -- | \(O(\log n)\) Restore the original \(x\) coordinate from a compressed one. Access to unknown+-- -- points are undefined.+-- {-# INLINE indexX #-}+-- indexX :: (HasCallStack) => WaveletMatrix2d s a -> Int -> Int+-- indexX WaveletMatrix2d {xyDictWm2d} x = maybe err (VG.unsafeIndex xDict) $ lowerBound xDict x+--   where+--     (!xDict, !_) = VU.unzip xyDictWm2d+--     err = error $ "AtCoder.Extra.WaveletMatirx.SegTree.indexX: cannot index x (`" ++ show x ++ "`)"++-- -- | \(O(\log n)\) Restore the original \(y\) coordinate from a compressed one. Access to unknown+-- -- points are undefined.+-- {-# INLINE indexY #-}+-- indexY :: (HasCallStack) => WaveletMatrix2d s a -> Int -> Int+-- indexY WaveletMatrix2d {yDictWm2d} y = maybe err (VG.unsafeIndex yDictWm2d) $ lowerBound yDictWm2d y+--   where+--     err = error $ "AtCoder.Extra.WaveletMatirx.SegTree.indexY: cannot index y (`" ++ show y ++ "`)"++-- -- | \(O(\log n)\) Restore the original \((x, y)\) coordinates from a compressed one. Access to+-- -- unknown points are undefined.+-- {-# INLINE indexXY #-}+-- indexXY :: (HasCallStack) => WaveletMatrix2d s a -> Int -> Int -> (Int, Int)+-- indexXY WaveletMatrix2d {xyDictWm2d} x y = maybe err (VG.unsafeIndex xyDictWm2d) $ lowerBound xyDictWm2d (x, y)+--   where+--     err = error $ "AtCoder.Extra.WaveletMatirx.SegTree.indexXY: cannot index (x, y) `" ++ show (x, y) ++ "`"++-- {-# INLINE assocsWith #-}+-- assocsWith :: WaveletMatrix -> (Int -> Int) -> [(Int, Int)]+-- assocsWith WaveletMatrix {..} l_ r_ f
src/AtCoder/FenwickTree.hs view
@@ -1,13 +1,13 @@ {-# LANGUAGE RecordWildCards #-} --- | Fenwick tree, also known as binary index tree. Given an array of length \(n\), it processes the--- following queries in \(O(\log n)\) time.+-- | A Fenwick tree, also known as binary indexed tree. Given an array of length \(n\), it processes+-- the following queries in \(O(\log n)\) time. -- -- - Updating an element -- - Calculating the sum of the elements of an interval -- -- ==== __Example__--- You can create a `FenwickTree` with `new`:+-- Create a `FenwickTree` with `new`: -- -- >>> import AtCoder.FenwickTree qualified as FT -- >>> ft <- FT.new @_ @Int 4 -- [0, 0, 0, 0]@@ -24,7 +24,7 @@ -- >>> FT.sum ft 0 3 -- 6 ----- You can create a `FenwickTree` with initial values using `build`:+-- Create a `FenwickTree` with initial values using `build`: -- -- >>> ft <- FT.build @_ @Int $ VU.fromList [3, 0, 3, 0] -- >>> FT.add ft 1 2          -- [3, 2, 3, 0]@@ -40,7 +40,7 @@     new,     build, -    -- * Modifying the Fenwick tree+    -- * Adding     add,      -- * Accessor@@ -60,7 +60,7 @@ import GHC.Stack (HasCallStack) import Prelude hiding (sum) --- | Fenwick tree.+-- | A Fenwick tree. -- -- @since 1.0.0.0 data FenwickTree s a = FenwickTree@@ -122,7 +122,7 @@       VGM.modify dataFt (+ x) (p - 1)       loop $! p + (p .&. (-p)) --- | \(O(\log n)\) Calculates the sum in half-open range @[0, r)@.+-- | \(O(\log n)\) Calculates the sum in a half-open interval @[0, r)@. -- -- @since 1.0.0.0 {-# INLINE prefixSum #-}@@ -135,7 +135,7 @@           dx <- VGM.read dataFt (r - 1)           inner (acc + dx) (r - r .&. (-r)) --- | Calculates the sum in half-open range \([l, r)\).+-- | Calculates the sum in a half-open interval \([l, r)\). -- -- ==== Constraints -- - \(0 \leq l \leq r \leq n\)@@ -150,8 +150,8 @@   | not (ACIA.testInterval l r nFt) = ACIA.errorInterval "AtCoder.FenwickTree.sum" l r nFt   | otherwise = unsafeSum ft l r --- | Total version of `sum`. Calculates the sum in half-open range \([l, r)\). It returns `Nothing`--- if the interval is invalid.+-- | Total variant of `sum`. Calculates the sum in a half-open interval \([l, r)\). It returns+-- `Nothing` if the interval is invalid. -- -- ==== Complexity -- - \(O(\log n)\)
src/AtCoder/Internal/Assert.hs view
@@ -73,7 +73,7 @@ testIndex :: (HasCallStack) => Int -> Int -> Bool testIndex i n = 0 <= i && i < n --- | \(O(1)\) Tests weather \([l, r)\) is a valid interval in \([0, n)\).+-- | \(O(1)\) Tests whether \([l, r)\) is a valid interval in \([0, n)\). -- -- @since 1.0.0.0 {-# INLINE testInterval #-}
src/AtCoder/Internal/Barrett.hs view
@@ -1,7 +1,7 @@ {-# LANGUAGE NamedFieldPuns #-} {-# LANGUAGE RecordWildCards #-} --- | Fast modular multiplication for `Word32` by barrett reduction.+-- | Fast modular multiplication for `Word32` using barrett reduction. -- Reference: https://en.wikipedia.org/wiki/Barrett_reduction -- -- ==== __Example__@@ -16,10 +16,10 @@ module AtCoder.Internal.Barrett   ( -- * Barrett     Barrett,-    -- * Constructors+    -- * Constructor     new32,     new64,-    -- * Accessors+    -- * Accessor     umod,     -- * Barrett reduction     mulMod,@@ -29,7 +29,7 @@ import Data.WideWord.Word128 (Word128 (..)) import Data.Word (Word32, Word64) --- | Fast modular multiplication by barrett reduction.+-- | Fast modular multiplication using barrett reduction. -- Reference: https://en.wikipedia.org/wiki/Barrett_reduction -- -- @since 1.0.0.0@@ -44,14 +44,14 @@       Show     ) --- | Creates barret reduction for modulus \(m\) from a `Word32` value.+-- | Creates a `Barrett` for a modulus value \(m\) of type `Word32` value. -- -- @since 1.0.0.0 {-# INLINE new32 #-} new32 :: Word32 -> Barrett new32 m = Barrett m $ maxBound @Word64 `div` (fromIntegral m :: Word64) + 1 --- | Creates barret reduction for modulus \(m\) from a `Word64` value.+-- | Creates a `Barrett` for a modulus value \(m\) of type `Word64` value. -- -- @since 1.0.0.0 {-# INLINE new64 #-}
src/AtCoder/Internal/Buffer.hs view
@@ -1,7 +1,6 @@ {-# LANGUAGE RecordWildCards #-} --- | Pushable vector with fixed size capacity. Stack. Internally it tracks the number of elements--- in the vector.+-- | A pushable vector with fixed capacity \(n\). Internally, it tracks the number of elements. -- -- ==== __Example__ -- Create a buffer with capacity @4@:@@ -54,25 +53,21 @@     new,     build, -    -- * Push/pop-    pushBack,-    popBack,+    -- * Metadata+    capacity,+    length,+    null, -    -- * Inspection+    -- * Reading     back,--    -- * Accessing individual elements     read,++    -- * Modifications+    pushBack,+    popBack,     write,     modify,     modifyM,--    -- * Accesssors-    capacity,-    length,-    null,--    -- * Clearing     clear,      -- * Conversions@@ -89,7 +84,7 @@ import GHC.Stack (HasCallStack) import Prelude hiding (length, null, read) --- | Pushable vector with fixed size capacity. Stack.+-- | A pushable vector with fixed capacity \(n\). Internally, it tracks the number of elements. -- -- @since 1.0.0.0 data Buffer s a = Buffer@@ -117,30 +112,28 @@   vecB <- VU.thaw xs   pure Buffer {..} --- | \(O(1)\) Appends an element to the back.+-- | \(O(1)\) Returns the array size. -- -- @since 1.0.0.0-{-# INLINE pushBack #-}-pushBack :: (HasCallStack, PrimMonad m, VU.Unbox a) => Buffer (PrimState m) a -> a -> m ()-pushBack Buffer {..} e = do-  len <- VGM.read lenB 0-  VGM.write vecB len e-  VGM.write lenB 0 (len + 1)+{-# INLINE capacity #-}+capacity :: (VU.Unbox a) => Buffer s a -> Int+capacity = VUM.length . vecB --- | \(O(1)\) Removes the last element from the buffer and returns it, or `Nothing` if it is empty.+-- | \(O(1)\) Returns the number of elements in the buffer. -- -- @since 1.0.0.0-{-# INLINE popBack #-}-popBack :: (PrimMonad m, VU.Unbox a) => Buffer (PrimState m) a -> m (Maybe a)-popBack Buffer {..} = do-  len <- VGM.read lenB 0-  if len == 0-    then pure Nothing-    else do-      x <- VGM.read vecB (len - 1)-      VGM.write lenB 0 (len - 1)-      pure $ Just x+{-# INLINE length #-}+length :: (PrimMonad m, VU.Unbox a) => Buffer (PrimState m) a -> m Int+length Buffer {..} = do+  VGM.read lenB 0 +-- | \(O(1)\) Returns `True` if the buffer is empty.+--+-- @since 1.0.0.0+{-# INLINE null #-}+null :: (PrimMonad m, VU.Unbox a) => Buffer (PrimState m) a -> m Bool+null = (<$>) (== 0) . length+ -- | \(O(1)\) Returns the last value in the buffer, or `Nothing` if it is empty. -- -- @since 1.0.0.0@@ -165,8 +158,32 @@   let !_ = ACIA.checkIndex "AtCoder.Internal.Buffer.read" i len   VGM.read vecB i +-- | \(O(1)\) Appends an element to the back.+--+-- @since 1.0.0.0+{-# INLINE pushBack #-}+pushBack :: (HasCallStack, PrimMonad m, VU.Unbox a) => Buffer (PrimState m) a -> a -> m ()+pushBack Buffer {..} e = do+  len <- VGM.read lenB 0+  VGM.write vecB len e+  VGM.write lenB 0 (len + 1)++-- | \(O(1)\) Removes the last element from the buffer and returns it, or `Nothing` if it is empty.+--+-- @since 1.0.0.0+{-# INLINE popBack #-}+popBack :: (PrimMonad m, VU.Unbox a) => Buffer (PrimState m) a -> m (Maybe a)+popBack Buffer {..} = do+  len <- VGM.read lenB 0+  if len == 0+    then pure Nothing+    else do+      x <- VGM.read vecB (len - 1)+      VGM.write lenB 0 (len - 1)+      pure $ Just x+ -- | \(O(1)\) Writes to the element at the given position. Will throw an exception if the index is--- out of range.+-- out of bounds. -- -- @since 1.0.0.0 {-# INLINE write #-}@@ -177,7 +194,7 @@   VGM.write vecB i e  -- | \(O(1)\) Writes to the element at the given position. Will throw an exception if the index is--- out of range.+-- out of bounds. -- -- @since 1.0.0.0 {-# INLINE modify #-}@@ -188,7 +205,7 @@   VGM.modify vecB f i  -- | \(O(1)\) Writes to the element at the given position. Will throw an exception if the index is--- out of range.+-- out of bounds. -- -- @since 1.0.0.0 {-# INLINE modifyM #-}@@ -197,28 +214,6 @@   len <- VGM.read lenB 0   let !_ = ACIA.checkIndex "AtCoder.Internal.Buffer.modifyM" i len   VGM.modifyM vecB f i---- | \(O(1)\) Returns the array size.------ @since 1.0.0.0-{-# INLINE capacity #-}-capacity :: (VU.Unbox a) => Buffer s a -> Int-capacity = VUM.length . vecB---- | \(O(1)\) Returns the number of elements in the buffer.------ @since 1.0.0.0-{-# INLINE length #-}-length :: (PrimMonad m, VU.Unbox a) => Buffer (PrimState m) a -> m Int-length Buffer {..} = do-  VGM.read lenB 0---- | \(O(1)\) Returns `True` if the buffer is empty.------ @since 1.0.0.0-{-# INLINE null #-}-null :: (PrimMonad m, VU.Unbox a) => Buffer (PrimState m) a -> m Bool-null = (<$>) (== 0) . length  -- | \(O(1)\) Sets the `length` to zero. --
src/AtCoder/Internal/Convolution.hs view
@@ -55,7 +55,7 @@       Show     ) --- | \(O(\log m)\) Creates `FftInfo`.+-- | \(O(\log m)\) Creates an `FftInfo`. -- -- @since 1.0.0.0 {-# INLINE newInfo #-}
src/AtCoder/Internal/Csr.hs view
@@ -1,9 +1,10 @@ {-# LANGUAGE RecordWildCards #-} --- | Immutable Compresed Sparse Row.+-- | Immutable Compresed Sparse Row. It is re-exported from the @AtCoder.Extra.Graph@ module with+-- additional functionalities. -- -- ==== __Example__--- Create a `Csr` without edge weights using `build`:+-- Create a `Csr` without edge weights using `build'` and retrieve the edges with `adj`: -- -- >>> import AtCoder.Internal.Csr qualified as C -- >>> let csr = build' 3 $ VU.fromList @(Int, Int) [(0, 1), (0, 2), (0, 3), (1, 2), (2, 3)]@@ -16,7 +17,7 @@ -- >>> csr `C.adj` 2 -- [3] ----- Create a `Csr` with edge weights with `build` and retrieve edge with `edgeW`:+-- Create a `Csr` with edge weights using `build` and retrieve the edges with `adjW`: -- -- >>> import AtCoder.Internal.Csr qualified as C -- >>> let csr = build 3 $ VU.fromList @(Int, Int, Int) [(0, 1, 101), (0, 2, 102), (0, 3, 103), (1, 2, 112), (2, 3, 123)]@@ -32,10 +33,13 @@ -- @since 1.0.0.0 module AtCoder.Internal.Csr   ( -- * Compressed sparse row-    Csr,+    Csr (..),+     -- * Constructor     build,     build',+    build1,+     -- * Accessors     adj,     adjW,@@ -55,8 +59,25 @@ -- -- @since 1.0.0.0 data Csr w = Csr-  { startCsr :: !(VU.Vector Int),+  { -- | The number of vertices.+    --+    -- @since 1.1.0.0+    nCsr :: {-# UNPACK #-} !Int,+    -- | The number of edges.+    --+    -- @since 1.1.0.0+    mCsr :: {-# UNPACK #-} !Int,+    -- | Starting indices.+    --+    -- @since 1.1.0.0+    startCsr :: !(VU.Vector Int),+    -- | Adjacent vertices.+    --+    -- @since 1.1.0.0     adjCsr :: !(VU.Vector Int),+    -- | Edge weights.+    --+    -- @since 1.1.0.0     wCsr :: !(VU.Vector w)   }   deriving@@ -66,25 +87,26 @@       Show     ) --- | \(O(n + m)\) Creates `Csr`.+-- | \(O(n + m)\) Creates a `Csr`. -- -- @since 1.0.0.0 {-# INLINE build #-} build :: (HasCallStack, VU.Unbox w) => Int -> VU.Vector (Int, Int, w) -> Csr w-build n edges = runST $ do-  start <- VUM.replicate (n + 1) (0 :: Int)+build nCsr edges = runST $ do+  let mCsr = VU.length edges+  start <- VUM.replicate (nCsr + 1) (0 :: Int)    let (!froms, !_, !_) = VU.unzip3 edges   VU.forM_ froms $ \from -> do     VGM.modify start (+ 1) (from + 1) -  for_ [1 .. n] $ \i -> do+  for_ [1 .. nCsr] $ \i -> do     prev <- VGM.read start (i - 1)     VGM.modify start (+ prev) i    edgeAdj <- VUM.unsafeNew (VU.length edges)   edgeW <- VUM.unsafeNew (VU.length edges)-  counter <- VUM.unsafeNew n+  counter <- VUM.unsafeNew nCsr   VUM.unsafeCopy counter $ VUM.init start   VU.forM_ edges $ \(!from, !to, !w) -> do     c <- VGM.read counter from@@ -97,7 +119,7 @@   wCsr <- VU.unsafeFreeze edgeW   pure Csr {..} --- | \(O(n + m)\) Creates `Csr` with no weight.+-- | \(O(n + m)\) Creates a `Csr` with no edge weight. -- -- @since 1.0.0.0 {-# INLINE build' #-}@@ -106,17 +128,26 @@   where     (!us, !vs) = VU.unzip edges --- | \(O(1)\) Returns adjacent vertices.+-- | \(O(n + m)\) Creates a `Csr` with @1@ as edge weights. --+-- @since 1.1.0.0+{-# INLINE build1 #-}+build1 :: (HasCallStack) => Int -> VU.Vector (Int, Int) -> Csr Int+build1 n edges = build n $ VU.zip3 us vs (VU.replicate (VU.length us) (1 :: Int))+ where+    (!us, !vs) = VU.unzip edges++-- | \(O(1)\) Returns the adjacent vertices.+-- -- @since 1.0.0.0 {-# INLINE adj #-}-adj :: (HasCallStack, VU.Unbox w) => Csr w -> Int -> VU.Vector Int+adj :: (HasCallStack) => Csr w -> Int -> VU.Vector Int adj Csr {..} i =   let il = startCsr VG.! i       ir = startCsr VG.! (i + 1)    in VU.slice il (ir - il) adjCsr --- | \(O(1)\) Returns adjacent vertices with weights.+-- | \(O(1)\) Returns the adjacent vertices with weights. -- -- @since 1.0.0.0 {-# INLINE adjW #-}@@ -126,11 +157,11 @@       ir = startCsr VG.! (i + 1)    in VU.zip (VU.slice il (ir - il) adjCsr) (VU.slice il (ir - il) wCsr) --- | \(O(1)\) Returns a vector of @(edgeId, adjacentVertex)@.+-- | \(O(n)\) Returns a vector of @(edgeId, adjacentVertex)@. -- -- @since 1.0.0.0 {-# INLINE eAdj #-}-eAdj :: (HasCallStack, VU.Unbox w) => Csr w -> Int -> VU.Vector (Int, Int)+eAdj :: (HasCallStack) => Csr w -> Int -> VU.Vector (Int, Int) eAdj Csr {..} i =   let il = startCsr VG.! i       ir = startCsr VG.! (i + 1)
src/AtCoder/Internal/GrowVec.hs view
@@ -39,32 +39,32 @@ -- -- @since 1.0.0.0 module AtCoder.Internal.GrowVec-  ( -- * Growable vector+  ( -- * GrowVec     GrowVec (vecGV), -    -- * Constructions--    -- ** Initialization+    -- * Constructors     new,     build,--    -- ** Reserving     reserve, -    -- * Accessing individual elements+    -- * Metadata+    length,+    capacity,+    null,++    -- * Readings     read,++    -- * Modifications++    -- ** Writing     write, -    -- * Modifying the buffer+    -- ** Push/pop     pushBack,     popBack,     popBack_, -    -- * Accessors-    length,-    capacity,-    null,-     -- * Conversion     freeze,     unsafeFreeze,@@ -91,7 +91,7 @@     vecGV :: !(MutVar s (VUM.MVector s a))   } --- | \(O(n)\) Creates `GrowVec` with initial capacity \(n\).+-- | \(O(n)\) Creates a `GrowVec` with initial capacity \(n\). -- -- @since 1.0.0.0 {-# INLINE new #-}@@ -101,7 +101,7 @@   vecGV <- newMutVar =<< VUM.unsafeNew n   pure GrowVec {..} --- | \(O(n)\) Creates `GrowVec` with initial values.+-- | \(O(n)\) Creates a `GrowVec` with initial values. -- -- @since 1.0.0.0 {-# INLINE build #-}@@ -122,6 +122,30 @@     newVec <- VUM.unsafeGrow vec (len - VUM.length vec)     writeMutVar vecGV newVec +-- | \(O(1)\) Returns the number of elements in the vector.+--+-- @since 1.0.0.0+{-# INLINE length #-}+length :: (PrimMonad m, VU.Unbox a) => GrowVec (PrimState m) a -> m Int+length GrowVec {posGV} = do+  VGM.unsafeRead posGV 0++-- | \(O(1)\) Returns the capacity of the internal the vector.+--+-- @since 1.0.0.0+{-# INLINE capacity #-}+capacity :: (PrimMonad m, VU.Unbox a) => GrowVec (PrimState m) a -> m Int+capacity GrowVec {vecGV} = do+  vec <- readMutVar vecGV+  pure $ VUM.length vec++-- | \(O(1)\) Returns `True` if the vector is empty.+--+-- @since 1.0.0.0+{-# INLINE null #-}+null :: (PrimMonad m, VU.Unbox a) => GrowVec (PrimState m) a -> m Bool+null = (<$>) (== 0) . length+ -- | \(O(1)\) Yields the element at the given position. Will throw an exception if the index is out -- of range. --@@ -185,7 +209,7 @@       vec <- readMutVar vecGV       Just <$> VGM.read vec (pos - 1) --- | \(O(1)\) `popBack` with return value discarded.+-- | \(O(1)\) `popBack` with the return value discarded. -- -- @since 1.0.0.0 {-# INLINE popBack_ #-}@@ -193,30 +217,6 @@ popBack_ GrowVec {..} = do   pos <- VGM.unsafeRead posGV 0   VGM.unsafeWrite posGV 0 $ max 0 $ pos - 1---- | \(O(1)\) Returns the number of elements in the vector.------ @since 1.0.0.0-{-# INLINE length #-}-length :: (PrimMonad m, VU.Unbox a) => GrowVec (PrimState m) a -> m Int-length GrowVec {posGV} = do-  VGM.unsafeRead posGV 0---- | \(O(1)\) Returns the capacity of the internal the vector.------ @since 1.0.0.0-{-# INLINE capacity #-}-capacity :: (PrimMonad m, VU.Unbox a) => GrowVec (PrimState m) a -> m Int-capacity GrowVec {vecGV} = do-  vec <- readMutVar vecGV-  pure $ VUM.length vec---- | \(O(1)\) Returns `True` if the vector is empty.------ @since 1.0.0.0-{-# INLINE null #-}-null :: (PrimMonad m, VU.Unbox a) => GrowVec (PrimState m) a -> m Bool-null = (<$>) (== 0) . length  -- | \(O(n)\) Yields an immutable copy of the mutable vector. --
src/AtCoder/Internal/Math.hs view
@@ -64,7 +64,16 @@ -- -- @since 1.0.0.0 {-# INLINE powMod #-}-powMod :: (HasCallStack) => Int -> Int -> Int -> Int+powMod ::+  (HasCallStack) =>+  -- | \(x\)+  Int ->+  -- | \(n\)+  Int ->+  -- | \(m\)+  Int ->+  -- | \(x^n \bmod m\)+  Int powMod x n0 m0   | m0 == 1 = 0   | otherwise = fromIntegral $ inner n0 1 $ fromIntegral (x `mod` m0)@@ -81,6 +90,13 @@  -- | M. Forisek and J. Jancina, Fast Primality Testing for Integers That Fit into a Machine Word --+-- ==== Constraints+-- - \(n < 4759123141 (2^{32} < 4759123141)\), otherwise the return value can lie+--   ([Wikipedia](https://en.wikipedia.org/wiki/Miller%E2%80%93Rabin_primality_test#Testing_against_small_sets_of_bases)).+--+-- ==== Complexity+-- - \(O(k \log^3 n)\), \(k = 3\)+-- -- @since 1.0.0.0 {-# INLINE isPrime #-} isPrime :: Int -> Bool@@ -100,7 +116,7 @@       | t == n - 1 || y == 1 || y == n - 1 = not $ y /= n - 1 && even t       | otherwise = inner (t .<<. 1) (y * y `mod` n) --- | Returns \((g, x)\) such that \(g = \gcd(a, b), \mathrm{xa} = g(\bmod b), 0 \le x \le b/g\).+-- | Returns \((g, x)\) such that \(g = \gcd(a, b), \mathrm{xa} \equiv g \pmod b, 0 \le x \le b/g\). -- -- ==== Constraints -- - \(1 \le b\) (not asserted)@@ -128,7 +144,7 @@               !m0' = m0 - m1 * u            in inner t s' m1 m0' --- | Returns primitive root.+-- | Returns the primitive root of the given `Int`. -- -- @since 1.0.0.0 {-# INLINE primitiveRoot #-}
src/AtCoder/Internal/MinHeap.hs view
@@ -34,22 +34,22 @@   ( -- * Heap     Heap, -    -- * Constructor+    -- * Constructors     new, -    -- * Accessors+    -- * Metadata     capacity,     length,     null, -    -- * Accessors+    -- * Reset     clear, -    -- * Modifying the heap+    -- * Push/pop/peek     push,-    peek,     pop,     pop_,+    peek,   ) where @@ -81,7 +81,7 @@     dataBH :: !(VUM.MVector s a)   } --- | \(O(n)\) Creates `Heap` with capacity \(n\).+-- | \(O(n)\) Creates a `Heap` with capacity \(n\). -- -- @since 1.0.0.0 {-# INLINE new #-}@@ -136,17 +136,6 @@           siftUp iParent   siftUp i0 --- | \(O(1)\) Returns the smallest value in the heap, or `Nothing` if it is empty.------ @since 1.0.0.0-{-# INLINE peek #-}-peek :: (VU.Unbox a, PrimMonad m) => Heap (PrimState m) a -> m (Maybe a)-peek heap = do-  isNull <- null heap-  if isNull-    then pure Nothing-    else Just <$> VGM.read (dataBH heap) 0- -- | \(O(\log n)\) Removes the last element from the heap and returns it, or `Nothing` if it is -- empty. --@@ -189,7 +178,7 @@       siftDown 0       pure $ Just root --- | \(O(\log n)\) `pop` with return value discarded.+-- | \(O(\log n)\) `pop` with the return value discarded. -- -- @since 1.0.0.0 {-# INLINE pop_ #-}@@ -197,3 +186,14 @@ pop_ heap = do   _ <- pop heap   pure ()++-- | \(O(1)\) Returns the smallest value in the heap, or `Nothing` if it is empty.+--+-- @since 1.0.0.0+{-# INLINE peek #-}+peek :: (VU.Unbox a, PrimMonad m) => Heap (PrimState m) a -> m (Maybe a)+peek heap = do+  isNull <- null heap+  if isNull+    then pure Nothing+    else Just <$> VGM.read (dataBH heap) 0
src/AtCoder/Internal/Queue.hs view
@@ -1,6 +1,6 @@ {-# LANGUAGE RecordWildCards #-} --- | Fixed-sized queue. Internally it has \(l, r\) pair of valid element bounds.+-- | Fixed-sized queue. Internally it has an \([l, r)\) pair of valid element bounds. -- -- ==== __Example__ -- >>> import AtCoder.Internal.Queue qualified as Q@@ -43,18 +43,20 @@     -- * Constructor     new, -    -- * Modifying the queue+    -- * Metadata+    capacity,+    length,+    null,++    -- * Modifications++    -- ** Push/pop     pushBack,     pushFront,     popFront,     popFront_, -    -- * Accessors-    capacity,-    length,-    null,--    -- * Clearing+    -- ** Reset     clear,      -- * Conversions@@ -70,7 +72,7 @@ import GHC.Stack (HasCallStack) import Prelude hiding (length, null) --- | Fixed-sized queue. Internally it has \([l, r)\) pair of valid element bounds.+-- | Fixed-sized queue. Internally it has an \([l, r)\) pair of valid element bounds. -- -- @since 1.0.0.0 data Queue s a = Queue@@ -79,7 +81,7 @@     vecQ :: !(VUM.MVector s a)   } --- | \(O(n)\) Creates `Queue` with capacity \(n\).+-- | \(O(n)\) Creates a `Queue` with capacity \(n\). -- -- @since 1.0.0.0 {-# INLINE new #-}@@ -89,6 +91,30 @@   vecQ <- VUM.unsafeNew n   pure Queue {..} +-- | \(O(1)\) Returns the array size.+--+-- @since 1.0.0.0+{-# INLINE capacity #-}+capacity :: (VU.Unbox a) => Queue s a -> Int+capacity = VUM.length . vecQ++-- | \(O(1)\) Returns the number of elements in the queue.+--+-- @since 1.0.0.0+{-# INLINE length #-}+length :: (PrimMonad m, VU.Unbox a) => Queue (PrimState m) a -> m Int+length Queue {..} = do+  l <- VGM.unsafeRead posQ 0+  r <- VGM.unsafeRead posQ 1+  pure $ r - l++-- | \(O(1)\) Returns `True` if the buffer is empty.+--+-- @since 1.0.0.0+{-# INLINE null #-}+null :: (PrimMonad m, VU.Unbox a) => Queue (PrimState m) a -> m Bool+null = (<$>) (== 0) . length+ -- | \(O(1)\) Appends an element to the back. Will throw an exception if the index is out of range. -- -- @since 1.0.0.0@@ -136,7 +162,7 @@       VGM.unsafeWrite posQ 0 (l + 1)       pure $ Just x --- | \(O(1)\) `popFront` with return value discarded.+-- | \(O(1)\) `popFront` with the return value discarded. -- -- @since 1.0.0.0 {-# INLINE popFront_ #-}@@ -144,30 +170,6 @@ popFront_ que = do   _ <- popFront que   pure ()---- | \(O(1)\) Returns the array size.------ @since 1.0.0.0-{-# INLINE capacity #-}-capacity :: (VU.Unbox a) => Queue s a -> Int-capacity = VUM.length . vecQ---- | \(O(1)\) Returns the number of elements in the queue.------ @since 1.0.0.0-{-# INLINE length #-}-length :: (PrimMonad m, VU.Unbox a) => Queue (PrimState m) a -> m Int-length Queue {..} = do-  l <- VGM.unsafeRead posQ 0-  r <- VGM.unsafeRead posQ 1-  pure $ r - l---- | \(O(1)\) Returns `True` if the buffer is empty.------ @since 1.0.0.0-{-# INLINE null #-}-null :: (PrimMonad m, VU.Unbox a) => Queue (PrimState m) a -> m Bool-null = (<$>) (== 0) . length  -- | \(O(1)\) Sets the `length` to zero. --
src/AtCoder/Internal/Scc.hs view
@@ -8,15 +8,19 @@   ( -- * Internal SCC     SccGraph (nScc), -    -- * Constructor+    -- * Constructors     new, -    -- * Modifying the graph+    -- * Adding edges     addEdge,      -- * SCC calculation     sccIds,     scc,++    -- ** (Extra API) CSR API+    sccIdsCsr,+    sccCsr   ) where @@ -25,6 +29,7 @@ import Control.Monad (unless, when) import Control.Monad.Fix (fix) import Control.Monad.Primitive (PrimMonad, PrimState)+import Control.Monad.ST (runST) import Data.Foldable (for_) import Data.Maybe (fromJust) import Data.Vector qualified as V@@ -44,7 +49,7 @@     edgesScc :: !(ACIGV.GrowVec s (Int, Int))   } --- | \(O(n)\) Creates `SccGraph` of \(n\) vertices.+-- | \(O(n)\) Creates a `SccGraph` of \(n\) vertices. -- -- @since 1.0.0.0 {-# INLINE new #-}@@ -67,19 +72,47 @@ {-# INLINE sccIds #-} sccIds :: (PrimMonad m) => SccGraph (PrimState m) -> m (Int, VU.Vector Int) sccIds SccGraph {..} = do+  csr <- ACICSR.build' nScc <$> ACIGV.unsafeFreeze edgesScc+  pure $ sccIdsCsr csr++-- | \(O(n + m)\) Returns the strongly connected components.+--+-- @since 1.0.0.0+{-# INLINE scc #-}+scc :: (PrimMonad m) => SccGraph (PrimState m) -> m (V.Vector (VU.Vector Int))+scc g = do+  (!groupNum, !ids) <- sccIds g+  let counts = VU.create $ do+        vec <- VUM.replicate groupNum (0 :: Int)+        VU.forM_ ids $ \x -> do+          VGM.modify vec (+ 1) x+        pure vec+  groups <- V.mapM VUM.unsafeNew $ VU.convert counts+  is <- VUM.replicate groupNum (0 :: Int)+  VU.iforM_ ids $ \v sccId -> do+    i <- VGM.read is sccId+    VGM.write is sccId $ i + 1+    VGM.write (groups VG.! sccId) i v+  V.mapM VU.unsafeFreeze groups++-- | \(O(n + m)\) API) Returns a pair of @(# of scc, scc id)@.+--+-- @since 1.1.0.0+{-# INLINE sccIdsCsr #-}+sccIdsCsr :: ACICSR.Csr w -> (Int, VU.Vector Int)+sccIdsCsr g@ACICSR.Csr {..} = runST $ do   -- see also the Wikipedia: https://en.wikipedia.org/wiki/Tarjan%27s_strongly_connected_components_algorithm#The_algorithm_in_pseudocode-  g <- ACICSR.build' nScc <$> ACIGV.unsafeFreeze edgesScc   -- next SCC ID   groupNum <- VUM.replicate 1 (0 :: Int)   -- stack of vertices-  visited <- ACIGV.new nScc+  visited <- ACIGV.new nCsr   -- vertex -> low-link: the smallest index of any node on the stack known to be reachable from   -- v through v's DFS subtree, including v itself.-  low <- VUM.replicate nScc (0 :: Int)+  low <- VUM.replicate nCsr (0 :: Int)   -- vertex -> order of the visit (0, 1, ..)-  ord <- VUM.replicate nScc (-1 :: Int)+  ord <- VUM.replicate nCsr (-1 :: Int)   -- vertex -> scc id-  ids <- VUM.replicate nScc (0 :: Int)+  ids <- VUM.replicate nCsr (0 :: Int)    let dfs v ord0 = do         VGM.write low v ord0@@ -112,7 +145,7 @@           sccId <- VGM.unsafeRead groupNum 0           fix $ \loop -> do             u <- fromJust <$> ACIGV.popBack visited-            VGM.write ord u nScc+            VGM.write ord u nCsr             VGM.write ids u sccId             unless (u == v) loop           VGM.unsafeWrite groupNum 0 $ sccId + 1@@ -126,12 +159,12 @@           else pure curOrd     )     (0 :: Int)-    (VU.generate nScc id)+    (VU.generate nCsr id)    num <- VGM.unsafeRead groupNum 0   -- The SCCs are reverse topologically sorted, e.g., [0, 1] <- [2] <- [3]   -- Now reverse the SCC IDs so that they will be topologically sorted: [3] -> [2] -> [0, 1]-  for_ [0 .. nScc - 1] $ \i -> do+  for_ [0 .. nCsr - 1] $ \i -> do     VGM.modify ids ((num - 1) -) i    ids' <- VU.unsafeFreeze ids@@ -139,16 +172,10 @@  -- | \(O(n + m)\) Returns the strongly connected components. ----- @since 1.0.0.0-{-# INLINE scc #-}-scc :: (PrimMonad m) => SccGraph (PrimState m) -> m (V.Vector (VU.Vector Int))-scc g = do-  (!groupNum, !ids) <- sccIds g-  let counts = VU.create $ do-        vec <- VUM.replicate groupNum (0 :: Int)-        VU.forM_ ids $ \x -> do-          VGM.modify vec (+ 1) x-        pure vec+-- @since 1.1.0.0+{-# INLINE sccCsr #-}+sccCsr :: ACICSR.Csr w -> V.Vector (VU.Vector Int)+sccCsr g = runST $ do   groups <- V.mapM VUM.unsafeNew $ VU.convert counts   is <- VUM.replicate groupNum (0 :: Int)   VU.iforM_ ids $ \v sccId -> do@@ -156,3 +183,10 @@     VGM.write is sccId $ i + 1     VGM.write (groups VG.! sccId) i v   V.mapM VU.unsafeFreeze groups+  where+    (!groupNum, !ids) = sccIdsCsr g+    counts = VU.create $ do+      vec <- VUM.replicate groupNum (0 :: Int)+      VU.forM_ ids $ \x -> do+        VGM.modify vec (+ 1) x+      pure vec
src/AtCoder/Internal/String.hs view
@@ -20,7 +20,7 @@ import Data.Vector.Unboxed.Mutable qualified as VUM import GHC.Stack (HasCallStack) --- TODO: remove `HasCallStack` when we're 100% sure the input is guarded+-- TODO: remove `HasCallStack`?  -- | \(O(n^2)\) Internal implementation of suffix array creation (naive). --@@ -88,7 +88,18 @@ -- -- @since 1.0.0.0 {-# INLINE saIsImpl #-}-saIsImpl :: (HasCallStack) => Int -> Int -> VU.Vector Int -> Int -> VU.Vector Int+saIsImpl ::+  (HasCallStack) =>+  -- | naive threshould+  Int ->+  -- | doubling threshould+  Int ->+  -- | string+  VU.Vector Int ->+  -- | upper bounds+  Int ->+  -- | suffix array+  VU.Vector Int saIsImpl naiveThreshold doublingThreshold s upper = VU.create $ do   let n = VU.length s   let !ls = VU.create $ do@@ -247,7 +258,14 @@ -- -- @since 1.0.0.0 {-# INLINE saIs #-}-saIs :: (HasCallStack) => VU.Vector Int -> Int -> VU.Vector Int+saIs ::+  (HasCallStack) =>+  -- | string+  VU.Vector Int ->+  -- | upper bounds+  Int ->+  -- | suffix array+  VU.Vector Int saIs = saIsManual 10 40  -- | \(O(n)\) Internal implementation of suffix array creation (suffix array induced sorting).@@ -259,7 +277,18 @@ -- -- @since 1.0.0.0 {-# INLINE saIsManual #-}-saIsManual :: (HasCallStack) => Int -> Int -> VU.Vector Int -> Int -> VU.Vector Int+saIsManual ::+  (HasCallStack) =>+  -- | naive threshold+  Int ->+  -- | doubling threshold+  Int ->+  -- | string+  VU.Vector Int ->+  -- | upper bounds+  Int ->+  -- | suffix array+  VU.Vector Int saIsManual naiveThreshold doublingThreshold s upper   | n == 0 = VU.empty   | n == 1 = VU.singleton 0
src/AtCoder/LazySegTree.hs view
@@ -1,6 +1,6 @@ {-# LANGUAGE RecordWildCards #-} --- | Lazily propagted segment tree. It is the data structure for the pair of a [monoid](https://en.wikipedia.org/wiki/Monoid)+-- | A lazily propagted segment tree. It is the data structure for the pair of a [monoid](https://en.wikipedia.org/wiki/Monoid) -- \((S, \cdot: S \times S \to S, e \in S)\) and a set \(F\) of \(S \to S\) mappings that satisfies -- the following properties. --@@ -51,7 +51,7 @@ -- >>> LST.allProd seg -- Sum {getSum = 24} ----- Run binary search in \(O(\log n\) time complexity:+-- Run binary search: -- -- >>> LST.maxRight seg 0 (<= (Sum 10)) -- sum [0, 2) = 7 <= 10 -- 2@@ -59,8 +59,7 @@ -- >>> LST.minLeft seg 4 (<= (Sum 10)) -- sum [3, 4) = 10 <= 10 -- 3 ----- Inspect all the values in \(O(n \log n)\) with `freeze` or `unsafeFreeze`. Note that they--- propagete all the applied actions:+-- Inspect all the values in \(O(n \log n)\) with `freeze` or `unsafeFreeze`: -- -- >>> VU.map getSum <$> LST.freeze seg -- [2,5,7,10]@@ -69,14 +68,14 @@ -- -- - `prod` returns \(a_l \cdot a_{l + 1} \cdot .. \cdot a_{r - 1}\). If you need \(a_{r - 1} \cdot a_{r - 2} \cdot .. \cdot a_{l}\), -- wrap your monoid in `Data.Monoid.Dual`.--- - If you ever need to store boxed types to `LazySegTree`, wrap it in 'vector:Data.Vector.Unboxed.DoNotUnboxStrict'+-- - If you ever need to store boxed types to `LazySegTree`, wrap it in @Data.Vector.Unboxed.DoNotUnboxStrict@ -- or the like. -- -- ==== Major changes from the original @ac-library@ -- - The API is based on `Monoid` and `SegAct`, not the functions @op@, @e@, @mapping@, -- @composition@ and @id@. -- - @get@ and @set@ are renamed to `read` and `write`.--- - `modify`, `modifyM`, `freeze` and `unsafeFreeze` are added.+-- - `modify`, `modifyM`, `exchange`, `freeze` and `unsafeFreeze` are added. -- -- @since 1.0.0.0 module AtCoder.LazySegTree@@ -88,10 +87,11 @@     new,     build, -    -- * Accessing individual elements+    -- * Accessing elements     write,     modify,     modifyM,+    exchange,     read,      -- * Products@@ -134,17 +134,19 @@ -- | Typeclass reprentation of the `LazySegTree` properties. User can implement either `segAct` or -- `segActWithLength`. ----- Instances should satisfy the follwing:+-- Instances should satisfy the follwing properties: -- -- [Left monoid action] @'segAct' (f2 '<>' f1) x = 'segAct' f2 ('segAct' f1 x)@ -- [Identity map] @`segAct` `mempty` x = x@ -- [Endomorphism] @'segAct' f (x1 '<>' x2) = ('segAct' f x1) '<>' ('segAct' f x2)@ ----- If you implement `segActWithLength`, satisfy one more propety:+-- If you implement `SegAct` via `segActWithLength`, satisfy one more propety: -- -- [Linear left monoid action] @'segActWithLength' len f a = 'Data.Semigroup.stimes' len ('segAct' f a) a@. ----- Note that in `SegAct` instances, new semigroup values are always given from the left: @new '<>' old@.+-- ==== Invariant+-- In `SegAct` instances, new semigroup values are always given from the left: @new '<>' old@. The+-- order is important for non-commutative monoid implementations. -- -- ==== __Example instance__ -- Take `AtCoder.Extra.Monoid.Affine1` as an example of type \(F\).@@ -287,7 +289,7 @@   segActWithLength :: Int -> f -> a -> a   segActWithLength _ = segAct --- | Lazy segment tree defined around `SegAct`.+-- | A lazily propagated segment tree defined around `SegAct`. -- -- @since 1.0.0.0 data LazySegTree s f a = LazySegTree@@ -408,6 +410,27 @@   for_ [1 .. logLst] $ \i -> do     update self $ p' .>>. i +-- | (Extra API) Sets \(p\)-th value of the array to \(x\) and returns the old value.+--+-- ==== Constraints+-- - \(0 \leq p \lt n\)+--+-- ==== Complexity+-- - \(O(\log n)\)+--+-- @since 1.1.0.0+{-# INLINE exchange #-}+exchange :: (HasCallStack, PrimMonad m, SegAct f a, VU.Unbox f, Monoid a, VU.Unbox a) => LazySegTree (PrimState m) f a -> Int -> a -> m a+exchange self@LazySegTree {..} p x = do+  let !_ = ACIA.checkIndex "AtCoder.LazySegTree.exchange" p nLst+  let p' = p + sizeLst+  for_ [logLst, logLst - 1 .. 1] $ \i -> do+    push self $ p' .>>. i+  res <- VGM.exchange dLst p' x+  for_ [1 .. logLst] $ \i -> do+    update self $ p' .>>. i+  pure res+ -- | Returns \(p\)-th value of the array. -- -- ==== Constraints@@ -443,8 +466,8 @@   | l0 == r0 = pure mempty   | otherwise = unsafeProd self l0 r0 --- | Total version of `prod`. Returns the product of \([a[l], ..., a[r - 1]]\), assuming the--- properties of the monoid. It returns `Just` `mempty` if \(l = r\). It returns `Nothing` if the+-- | Total variant of `prod`. Returns the product of \([a[l], ..., a[r - 1]]\), assuming the+-- properties of the monoid. Returns `Just` `mempty` if \(l = r\). It returns `Nothing` if the -- interval is invalid. -- -- ==== Complexity@@ -494,7 +517,7 @@ allProd :: (PrimMonad m, Monoid a, VU.Unbox a) => LazySegTree (PrimState m) f a -> m a allProd LazySegTree {..} = VGM.read dLst 1 --- | Applies @segAct f@ to an index @p@.+-- | Applies @segAct f@ to an index \(p\). -- -- ==== Constraints -- - \(0 \leq p \lt n\)@@ -517,7 +540,7 @@   for_ [1 .. logLst] $ \i -> do     update self $ p' .>>. i --- | Applies @segAct f@ to an interval @[l, r)@.+-- | Applies @segAct f@ to an interval \([l, r)\). -- -- ==== Constraints -- - \(0 \leq l \leq r \leq n\)@@ -577,7 +600,7 @@ minLeft :: (HasCallStack, PrimMonad m, SegAct f a, VU.Unbox f, Monoid a, VU.Unbox a) => LazySegTree (PrimState m) f a -> Int -> (a -> Bool) -> m Int minLeft seg r0 g = minLeftM seg r0 (pure . g) --- | Monadic version of `minLeft`.+-- | Monadic variant of `minLeft`. -- -- ==== Constraints --@@ -652,7 +675,7 @@ maxRight :: (HasCallStack, PrimMonad m, SegAct f a, VU.Unbox f, Monoid a, VU.Unbox a) => LazySegTree (PrimState m) f a -> Int -> (a -> Bool) -> m Int maxRight seg l0 g = maxRightM seg l0 (pure . g) --- | Monadic version of `maxRight`.+-- | Monadic variant of `maxRight`. -- -- ==== Constraints --
src/AtCoder/Math.hs view
@@ -5,6 +5,7 @@ -- @since 1.0.0.0 module AtCoder.Math   ( -- * Modulus operations+     -- These functions are internally used for `AtCoder.ModInt`.     powMod,     invMod,@@ -42,7 +43,14 @@ -- -- @since 1.0.0.0 {-# INLINE invMod #-}-invMod :: (HasCallStack) => Int -> Int -> Int+invMod ::+  (HasCallStack) =>+  -- | \(x\)+  Int ->+  -- | \(m\)+  Int ->+  -- | \(x^{-1} \bmod m\)+  Int invMod x m =   let !_ = ACIA.runtimeAssert (1 <= m) $ "AtCoder.Math.invMod: given invalid `m` less than 1: " ++ show m       (!z1, !z2) = ACIM.invGcd (fromIntegral x) (fromIntegral m)@@ -66,7 +74,7 @@ -- ==== Complexity -- - \(O(n \log{\mathrm{lcm}(m[i])})\) ----- ==== Example+-- ==== __Example__ -- `crt` calculates \(y\) such that \(y \equiv r_i \pmod m_i, \forall i \in \lbrace 0,1,\cdots, n - 1 \rbrace\): -- -- >>> import Data.Vector.Unboxed qualified as VU@@ -127,7 +135,7 @@ -- ==== Complexity -- - \(O(\log m)\) ----- ==== Example+-- ==== __Example__ -- `floorSum` calculates the number of points surrounded by a line -- \(y = \frac {a \times x + b} {m} \) and \(x, y\) axes in \(O(\log m)\) time: --@@ -150,7 +158,18 @@ -- -- @since 1.0.0.0 {-# INLINE floorSum #-}-floorSum :: (HasCallStack) => Int -> Int -> Int -> Int -> Int+floorSum ::+  (HasCallStack) =>+  -- | \(n\)+  Int ->+  -- | \(m\)+  Int ->+  -- | \(a\)+  Int ->+  -- | \(b\)+  Int ->+  -- | \(\sum\limits_{i = 0}^{n - 1} \left\lfloor \frac{a \times i + b}{m} \right\rfloor\)+  Int floorSum n m a b = ACIM.floorSumUnsigned n m a' b' - da - db   where     !_ = ACIA.runtimeAssert (0 <= n && n < bit 32) $ "AtCoder.Math.floorSum: given invalid `n` (`" ++ show n ++ "`)"
src/AtCoder/MaxFlow.hs view
@@ -21,7 +21,7 @@ -- 1 -- -- Get the minimum cut with `minCut`. In this case, removing the second edge makes the minimum cut--- (note that the edge capacity (\(1\)) = max flow):+-- (note that the edge capacity \(1\) = max flow): -- -- >>> MF.minCut g 0 -- returns a Bit vector. `1` (`Bit True`) is on the `s` side. -- [1,1,0]@@ -116,7 +116,18 @@ -- -- @since 1.0.0.0 {-# INLINE addEdge #-}-addEdge :: (HasCallStack, PrimMonad m, Num cap, Ord cap, VU.Unbox cap) => MfGraph (PrimState m) cap -> Int -> Int -> cap -> m Int+addEdge ::+  (HasCallStack, PrimMonad m, Num cap, Ord cap, VU.Unbox cap) =>+  -- | Graph+  MfGraph (PrimState m) cap ->+  -- | from+  Int ->+  -- | to+  Int ->+  -- | cap+  cap ->+  -- | Edge index+  m Int addEdge MfGraph {..} from to cap = do   let !_ = ACIA.checkCustom "AtCoder.MaxFlow.addEdge" "`from` vertex" from "the number of vertices" nG   let !_ = ACIA.checkCustom "AtCoder.MaxFlow.addEdge" "`to` vertex" to "the number of vertices" nG@@ -131,7 +142,7 @@   ACIGV.pushBack (gG VG.! to) (from, iEdge, 0)   pure m --- | `addEdge` with return value discarded.+-- | `addEdge` with the return value discarded. -- -- ==== Constraints -- - \(0 \leq \mathrm{from}, \mathrm{to} \lt n\)@@ -142,7 +153,17 @@ -- -- @since 1.0.0.0 {-# INLINE addEdge_ #-}-addEdge_ :: (HasCallStack, PrimMonad m, Num cap, Ord cap, VU.Unbox cap) => MfGraph (PrimState m) cap -> Int -> Int -> cap -> m ()+addEdge_ ::+  (HasCallStack, PrimMonad m, Num cap, Ord cap, VU.Unbox cap) =>+  -- | Graph+  MfGraph (PrimState m) cap ->+  -- | from+  Int ->+  -- | to+  Int ->+  -- | cap+  cap ->+  m () addEdge_ graph from to cap = do   _ <- addEdge graph from to cap   pure ()@@ -161,11 +182,22 @@ -- -- @since 1.0.0.0 {-# INLINE flow #-}-flow :: (HasCallStack, PrimMonad m, Num cap, Ord cap, VU.Unbox cap) => MfGraph (PrimState m) cap -> Int -> Int -> cap -> m cap+flow ::+  (HasCallStack, PrimMonad m, Num cap, Ord cap, VU.Unbox cap) =>+  -- | Graph+  MfGraph (PrimState m) cap ->+  -- | Source @s@+  Int ->+  -- | Sink @t@+  Int ->+  -- | Flow limit+  cap ->+  -- | Max flow+  m cap flow MfGraph {..} s t flowLimit = do   let !_ = ACIA.checkCustom "AtCoder.MaxFlow.flow" "`source` vertex" s "the number of vertices" nG   let !_ = ACIA.checkCustom "AtCoder.MaxFlow.flow" "`sink` vertex" t "the number of vertices" nG-  let !_ = ACIA.runtimeAssert (s /= t) $ "AtCoder.MaxFlow.flow: `source` and `sink` vertex have to be distinct: `" ++ show s ++ "`"+  let !_ = ACIA.runtimeAssert (s /= t) $ "AtCoder.MaxFlow.flow: `source` and `sink` vertex must be distinct: `" ++ show s ++ "`"    level <- VUM.unsafeNew nG   que <- ACIQ.new nG@@ -253,7 +285,16 @@ -- -- @since 1.0.0.0 {-# INLINE maxFlow #-}-maxFlow :: (HasCallStack, PrimMonad m, Num cap, Ord cap, Bounded cap, VU.Unbox cap) => MfGraph (PrimState m) cap -> Int -> Int -> m cap+maxFlow ::+  (HasCallStack, PrimMonad m, Num cap, Ord cap, Bounded cap, VU.Unbox cap) =>+  -- | Graph+  MfGraph (PrimState m) cap ->+  -- | Source @s@+  Int ->+  -- | Sink @t@+  Int ->+  -- | Max flow+  m cap maxFlow graph s t = flow graph s t maxBound  -- | Returns a vector of length \(n\), such that the \(i\)-th element is `True` if and only if there@@ -265,7 +306,14 @@ -- -- @since 1.0.0.0 {-# INLINE minCut #-}-minCut :: (PrimMonad m, Num cap, Ord cap, VU.Unbox cap) => MfGraph (PrimState m) cap -> Int -> m (VU.Vector Bit)+minCut ::+  (PrimMonad m, Num cap, Ord cap, VU.Unbox cap) =>+  -- | Graph+  MfGraph (PrimState m) cap ->+  -- | Source @s@+  Int ->+  -- | Minimum cut+  m (VU.Vector Bit) minCut MfGraph {..} s = do   visited <- VUM.replicate nG $ Bit False   que <- ACIQ.new nG -- we could use a growable queue here@@ -296,7 +344,14 @@ -- -- @since 1.0.0.0 {-# INLINE getEdge #-}-getEdge :: (HasCallStack, PrimMonad m, Num cap, Ord cap, VU.Unbox cap) => MfGraph (PrimState m) cap -> Int -> m (Int, Int, cap, cap)+getEdge ::+  (HasCallStack, PrimMonad m, Num cap, Ord cap, VU.Unbox cap) =>+  -- | Graph+  MfGraph (PrimState m) cap ->+  -- | Vertex+  Int ->+  -- | Tuple of @(from, to, cap, flow)@+  m (Int, Int, cap, cap) getEdge MfGraph {..} i = do   m <- ACIGV.length posG   let !_ = ACIA.checkEdge "AtCoder.MaxFlow.getEdge" i m@@ -313,13 +368,18 @@ -- -- @since 1.0.0.0 {-# INLINE edges #-}-edges :: (PrimMonad m, Num cap, Ord cap, VU.Unbox cap) => MfGraph (PrimState m) cap -> m (VU.Vector (Int, Int, cap, cap))+edges ::+  (PrimMonad m, Num cap, Ord cap, VU.Unbox cap) =>+  -- | Graph+  MfGraph (PrimState m) cap ->+  -- | Vector of @(from, to, cap, flow)@+  m (VU.Vector (Int, Int, cap, cap)) edges g@MfGraph {posG} = do   len <- ACIGV.length posG   VU.generateM len (getEdge g)  -- | \(O(1)\) Changes the capacity and the flow amount of the $i$-th edge to @newCap@ and--- @newFlow@, respectively. It doesn't change the capacity or the flow amount of other edges.+-- @newFlow@, respectively. It oes not change the capacity or the flow amount of other edges. -- -- ==== Constraints -- - \(0 \leq \mathrm{newflow} \leq \mathrm{newcap}\)@@ -329,7 +389,17 @@ -- -- @since 1.0.0.0 {-# INLINE changeEdge #-}-changeEdge :: (HasCallStack, PrimMonad m, Num cap, Ord cap, VU.Unbox cap) => MfGraph (PrimState m) cap -> Int -> cap -> cap -> m ()+changeEdge ::+  (HasCallStack, PrimMonad m, Num cap, Ord cap, VU.Unbox cap) =>+  -- | Graph+  MfGraph (PrimState m) cap ->+  -- | Edge index+  Int ->+  -- | New capacity+  cap ->+  -- | New flow+  cap ->+  m () changeEdge MfGraph {..} i newCap newFlow = do   m <- ACIGV.length posG   let !_ = ACIA.checkEdge "AtCoder.MaxFlow.changeEdge" i m
src/AtCoder/MinCostFlow.hs view
@@ -110,11 +110,17 @@ {-# INLINE addEdge #-} addEdge ::   (HasCallStack, PrimMonad m, Num cap, Ord cap, VU.Unbox cap, Num cost, Ord cost, VU.Unbox cost) =>+  -- | Graph   McfGraph (PrimState m) cap cost ->+  -- | from   Int ->+  -- | to   Int ->+  -- | capacity   cap ->+  -- | cost   cost ->+  -- | Edge index   m Int addEdge McfGraph {..} from to cap cost = do   let !_ = ACIA.checkCustom "AtCoder.MinCostFlow.addEdge" "`from` vertex" from "the number of vertices" nG@@ -125,7 +131,7 @@   ACIGV.pushBack edgesG (from, to, cap, 0, cost)   pure m --- | `addEdge` with return value discarded.+-- | `addEdge` with the return value discarded. -- -- ==== Constraints -- - \(0 \leq \mathrm{from}, \mathrm{to} \lt n\)@@ -138,10 +144,15 @@ {-# INLINE addEdge_ #-} addEdge_ ::   (HasCallStack, PrimMonad m, Num cap, Ord cap, VU.Unbox cap, Num cost, Ord cost, VU.Unbox cost) =>+  -- | Graph   McfGraph (PrimState m) cap cost ->+  -- | from   Int ->+  -- | to   Int ->+  -- | capacity   cap ->+  -- | cost   cost ->   m () addEdge_ graph from to cap cost = do@@ -161,10 +172,15 @@ {-# INLINE flow #-} flow ::   (HasCallStack, PrimMonad m, Integral cap, Ord cap, VU.Unbox cap, Num cost, Ord cost, Bounded cost, VU.Unbox cost) =>+  -- | Graph   McfGraph (PrimState m) cap cost ->+  -- | Fource @s@   Int ->+  -- | Sink @t@   Int ->+  -- | Flow limit   cap ->+  -- | Tuple of @(cap, cost@)   m (cap, cost) flow graph s t flowLimit = do   res <- slope graph s t flowLimit@@ -182,9 +198,13 @@ {-# INLINE maxFlow #-} maxFlow ::   (HasCallStack, PrimMonad m, Integral cap, Ord cap, Bounded cap, VU.Unbox cap, Num cost, Ord cost, Bounded cost, VU.Unbox cost) =>+  -- | Graph   McfGraph (PrimState m) cap cost ->+  -- | Source @s@   Int ->+  -- | Sink @t@   Int ->+  -- | Tuple of @(cap, cost@)   m (cap, cost) maxFlow graph s t = do   res <- slope graph s t maxBound@@ -216,15 +236,20 @@ {-# INLINE slope #-} slope ::   (HasCallStack, PrimMonad m, Integral cap, Ord cap, VU.Unbox cap, Num cost, Ord cost, Bounded cost, VU.Unbox cost) =>+  -- | Graph   McfGraph (PrimState m) cap cost ->+  -- | Source @s@   Int ->+  -- | Sink @t@   Int ->+  -- | Flow limit   cap ->+  -- | Vector of @(cap, cost)@   m (VU.Vector (cap, cost)) slope McfGraph {..} s t flowLimit = do   let !_ = ACIA.checkCustom "AtCoder.MinCostFlow.slope" "`source` vertex" s "the number of vertices" nG   let !_ = ACIA.checkCustom "AtCoder.MinCostFlow.slope" "`sink` vertex" t "the number of vertices" nG-  let !_ = ACIA.runtimeAssert (s /= t) "AtCoder.MinCostFlow.slope: `source` and `sink` vertex have to be distict"+  let !_ = ACIA.runtimeAssert (s /= t) "AtCoder.MinCostFlow.slope: `source` and `sink` vertex must be distict"    edges_@(VU.V_5 _ _ _ caps _ _) <- ACIGV.unsafeFreeze edgesG   (!edgeIdx, !g) <- ACIMCSR.build nG edges_@@ -292,8 +317,8 @@                   cap <- VGM.read capCsr $ start + di                    unless (cap == 0) $ do-                    -- \|-dual[e.to] + dual[v]| <= (n-1)C-                    -- cost <= C - -(n-1)C + 0 = nC+                    -- - |-dual[e.to] + dual[v]| <= (n-1)C+                    -- - cost <= C - -(n-1)C + 0 = nC                     cost' <- do                       dualTo <- VGM.read duals to                       pure $! cost - dualTo + dualV@@ -368,8 +393,11 @@ {-# INLINE getEdge #-} getEdge ::   (HasCallStack, PrimMonad m, Num cap, Ord cap, VU.Unbox cap, Num cost, Ord cost, VU.Unbox cost) =>+  -- | Graph   McfGraph (PrimState m) cap cost ->+  -- | Edge index   Int ->+  -- | Tuple of @(from, to, cap, flow, cost)@   m (Int, Int, cap, cap, cost) getEdge McfGraph {..} i = do   m <- ACIGV.length edgesG@@ -386,7 +414,9 @@ {-# INLINE edges #-} edges ::   (HasCallStack, PrimMonad m, Num cap, Ord cap, VU.Unbox cap, Num cost, Ord cost, VU.Unbox cost) =>+  -- | Graph   McfGraph (PrimState m) cap cost ->+  -- | Vector of @(from, to, cap, flow, cost)@   m (VU.Vector (Int, Int, cap, cap, cost)) edges McfGraph {..} = do   ACIGV.freeze edgesG@@ -401,7 +431,9 @@ {-# INLINE unsafeEdges #-} unsafeEdges ::   (HasCallStack, PrimMonad m, Num cap, Ord cap, VU.Unbox cap, Num cost, Ord cost, VU.Unbox cost) =>+  -- | Graph   McfGraph (PrimState m) cap cost ->+  -- | Vector of @(from, to, cap, flow, cost)@   m (VU.Vector (Int, Int, cap, cap, cost)) unsafeEdges McfGraph {..} = do   ACIGV.unsafeFreeze edgesG
src/AtCoder/ModInt.hs view
@@ -1,11 +1,11 @@ {-# LANGUAGE MagicHash #-} {-# LANGUAGE TypeFamilies #-} --- | It is the struct that treats the modular arithmetic. All the remaining parts of AC Library+-- | It is the structure that treats the modular arithmetic. All the remaining parts of AC Library -- works without modint, so you don't necessarily read this to use the remaining parts. ----- For most of the problems, it is sufficient to use `ModInt998244353`, `ModInt1000000007`, which--- can be used as follows.+-- ==== __Example__+-- It is often convenient to define a type alias of `ModInt` for a specific modulus value: -- -- >>> import AtCoder.ModInt qualified as M -- >>> type Mint = M.ModInt998244353@@ -13,7 +13,11 @@ -- >>> modInt 1000000000 -- 1755647 --+-- >>> modInt 1000000000 / modInt 3+-- 666081451+-- -- ==== Major changes from the original @ac-library@+-- - @StaticModInt@ is renamed to `ModInt`. -- - @DynamicModInt@ is removed. -- -- @since 1.0.0.0@@ -82,14 +86,14 @@   -- @since 1.0.0.0   isPrimeModulus :: Proxy# a -> Bool -  -- | Returns the primitive root of the modulus value. Note that the default implementation is-  -- slow.+  -- | Returns the primitive root of the modulus value. Note that the default implementation is slow+  -- and the value should be hard-coded.   --   -- @since 1.0.0.0   {-# INLINE primitiveRootModulus #-}   primitiveRootModulus :: Proxy# a -> Int   -- we could use `AllowAmbigousTypes` or `Tagged` newtype, but `Proxy#` wasn't so slow.-  -- not sure about `x^n` case though..+  -- not sure about the case of `x^n` though..   primitiveRootModulus _ = ACIM.primitiveRoot $ fromIntegral (natVal' (proxy# @a))  -- | \(2^{24} - 1\).@@ -119,7 +123,7 @@   {-# INLINE primitiveRootModulus #-}   primitiveRootModulus _ = 11 --- | \(119 \times 2^{23} + 1\). It is often used in contest problems+-- | \(119 \times 2^{23} + 1\). It is often used in contest problems. -- -- @since 1.0.0.0 instance Modulus 998244353 where@@ -146,17 +150,13 @@   {-# INLINE primitiveRootModulus #-}   primitiveRootModulus _ = 7 --- | `ModInt` with modulus value @998244353@.------ @since 1.0.0.0+-- | @since 1.0.0.0 type ModInt998244353 = ModInt 998244353 --- | `ModInt` with modulus value @1000000007@.------ @since 1.0.0.0+-- | @since 1.0.0.0 type ModInt1000000007 = ModInt 1000000007 --- | Retrieves `Int` from `KnownNat`.+-- | Retrieves the `Int` value from a `KnownNat`. -- -- >>> import Data.Proxy (Proxy(..)) -- >>> modVal (Proxy @42)@@ -167,7 +167,7 @@ modVal :: forall a. (KnownNat a) => Proxy a -> Int modVal p = fromIntegral $ natVal p --- | Retrieves `Int` from `KnownNat`.+-- | Retrieves the `Int` value from a `KnownNat`. -- -- >>> :set -XMagicHash -- >>> import GHC.Exts (proxy#)@@ -179,28 +179,28 @@ modVal# :: forall a. (KnownNat a) => Proxy# a -> Int modVal# p = fromIntegral $ natVal' p --- | Creates `ModInt` from an `Int` value taking mod.+-- | Creates a `ModInt` from an `Int` value taking the mod. -- -- @since 1.0.0.0 {-# INLINE new #-} new :: forall a. (KnownNat a) => Int -> ModInt a new v = ModInt . fromIntegral $ v `mod` fromIntegral (natVal' (proxy# @a)) --- | Creates `ModInt` from a `Word32` value taking mod.+-- | Creates a `ModInt` from a `Word32` value taking the mod. -- -- @since 1.0.0.0 {-# INLINE new32 #-} new32 :: forall a. (KnownNat a) => Word32 -> ModInt a new32 v = ModInt $ v `mod` fromIntegral (natVal' (proxy# @a)) --- | Creates `ModInt` from a `Word64` value taking mod.+-- | Creates a `ModInt` from a `Word64` value taking the mod. -- -- @since 1.0.0.0 {-# INLINE new64 #-} new64 :: forall a. (KnownNat a) => Word64 -> ModInt a new64 v = ModInt . fromIntegral $ v `mod` fromIntegral (natVal' (proxy# @a)) --- | Creates `ModInt` without taking mod. It is the function for constant-factor speedup.+-- | Creates `ModInt` without taking the mod. It is the function for constant-factor speedup. -- -- ==== Constraints -- - \(0 \leq x \lt \mathrm{mod}\) (not asserted at runtime)@@ -210,20 +210,23 @@ unsafeNew :: (KnownNat a) => Word32 -> ModInt a unsafeNew = ModInt --- | `Word32` value that treats the modula arithmetic.-newtype ModInt a = ModInt {unModInt :: Word32}+-- | `Word32` value that treats the modular arithmetic.+newtype ModInt a = ModInt+  { -- | @since 1.0.0.0+    unModInt :: Word32+  }   deriving-    ( -- @since 1.0.0.0+    ( -- | @since 1.0.0.0       P.Prim     )   deriving newtype-    ( -- @since 1.0.0.0+    ( -- | @since 1.0.0.0       Eq,-      -- @since 1.0.0.0+      -- | @since 1.0.0.0       Ord,-      -- @since 1.0.0.0+      -- | @since 1.0.0.0       Read,-      -- @since 1.0.0.0+      -- | @since 1.0.0.0       Show     ) @@ -322,10 +325,10 @@           !_ = ACIA.runtimeAssert (eg1 == 1) "AtCoder.ModInt.inv: `x^(-1) mod m` cannot be calculated when `gcd x modulus /= 1`"        in fromIntegral eg2 --- | -- @since 1.0.0.0+-- | @since 1.0.0.0 deriving newtype instance (KnownNat p) => Real (ModInt p) --- | -- @since 1.0.0.0+-- | @since 1.0.0.0 instance (KnownNat p) => Num (ModInt p) where   {-# INLINE (+) #-}   (ModInt !x1) + (ModInt !x2)@@ -355,45 +358,45 @@   {-# INLINE fromInteger #-}   fromInteger = ModInt . fromInteger . (`mod` fromIntegral (natVal' (proxy# @p))) --- | -- @since 1.0.0.0+-- | @since 1.0.0.0 instance (KnownNat p) => Bounded (ModInt p) where   {-# INLINE minBound #-}   minBound = ModInt 0   {-# INLINE maxBound #-}   maxBound = ModInt $! fromIntegral (natVal' (proxy# @p)) - 1 --- | -- @since 1.0.0.0+-- | @since 1.0.0.0 instance (KnownNat p) => Enum (ModInt p) where   {-# INLINE toEnum #-}   toEnum = new   {-# INLINE fromEnum #-}   fromEnum = fromIntegral . unModInt --- | -- @since 1.0.0.0+-- | @since 1.0.0.0 instance (Modulus p) => Integral (ModInt p) where   {-# INLINE quotRem #-}   quotRem x y = (x / y, x - x / y * y)   {-# INLINE toInteger #-}   toInteger = coerce (toInteger @Word32) --- | -- @since 1.0.0.0+-- | @since 1.0.0.0 instance (Modulus p) => Fractional (ModInt p) where   {-# INLINE recip #-}   recip = inv   {-# INLINE fromRational #-}   fromRational q = fromInteger (numerator q) / fromInteger (denominator q) --- | -- @since 1.0.0.0+-- | @since 1.0.0.0 newtype instance VU.MVector s (ModInt a) = MV_ModInt (VU.MVector s Word32) --- | -- @since 1.0.0.0+-- | @since 1.0.0.0 newtype instance VU.Vector (ModInt a) = V_ModInt (VU.Vector Word32) --- | -- @since 1.0.0.0+-- | @since 1.0.0.0 deriving newtype instance VGM.MVector VU.MVector (ModInt a) --- | -- @since 1.0.0.0+-- | @since 1.0.0.0 deriving newtype instance VG.Vector VU.Vector (ModInt a) --- | -- @since 1.0.0.0+-- | @since 1.0.0.0 instance VU.Unbox (ModInt a)
src/AtCoder/Scc.hs view
@@ -1,16 +1,22 @@ -- | It calculates the strongly connected components of directed graphs. ----- ==== Example+-- ==== __Example__+-- Create a `SccGraph`:+-- -- >>> import AtCoder.Scc qualified as Scc -- >>> gr <- Scc.new 4     -- 0    1    2    3 -- >>> Scc.nScc gr -- 4 --+-- Add edges and get SCC of the graph:+-- -- >>> Scc.addEdge gr 0 1  -- 0 -> 1    2    3 -- >>> Scc.addEdge gr 1 0  -- 0 == 1    2    3 -- >>> Scc.addEdge gr 1 2  -- 0 == 1 -> 2    3 -- >>> Scc.scc gr -- [[3],[0,1],[2]]+--+-- See also the @scc@ function in @AtCoder.Extra.Graph@ module that computes SCC for a CSR. -- -- @since 1.0.0.0 module AtCoder.Scc (SccGraph, nScc, new, addEdge, scc) where
src/AtCoder/SegTree.hs view
@@ -21,6 +21,7 @@ -- Create a `SegTree` of @'Sum' Int@: -- -- >>> import AtCoder.SegTree qualified as ST+-- >>> import Data.Vector.Unboxed qualified as VU -- >>> import Data.Monoid (Sum(..)) -- >>> seg <- ST.new @_ @(Sum Int) 4 --@@ -57,13 +58,13 @@ -- -- - `prod` returns \(a_l \cdot a_{l + 1} \cdot .. \cdot a_{r - 1}\). If you need \(a_{r - 1} \cdot a_{r - 2} \cdot .. \cdot a_{l}\), -- wrap your monoid in `Data.Monoid.Dual`.--- - If you ever need to store boxed types to `LazySegTree`, wrap it in 'vector:Data.Vector.Unboxed.DoNotUnboxStrict'+-- - If you ever need to store boxed types to `LazySegTree`, wrap it in @Data.Vector.Unboxed.DoNotUnboxStrict@ -- or the like. -- -- ==== Major changes from the original @ac-library@--- - The implementation is `Monoid` based.+-- - The implementation is `Monoid` based, not function objects. -- - @get@ and @set@ are renamed to `read` and `write`.--- - `modify`, `modifyM`, `freeze` and `unsafeFreeze` are added.+-- - `modify`, `modifyM`, `exchange`, `freeze` and `unsafeFreeze` are added. -- -- @since 1.0.0.0 module AtCoder.SegTree@@ -74,10 +75,11 @@     new,     build, -    -- * Accessing individual elements+    -- * Accessing elements     write,     modify,     modifyM,+    exchange,     read,      -- * Products@@ -145,7 +147,7 @@ new :: (HasCallStack, PrimMonad m, Monoid a, VU.Unbox a) => Int -> m (SegTree (PrimState m) a) new nSt   | nSt >= 0 = build $ VU.replicate nSt mempty-  | otherwise = error $ "new: given negative size (`" ++ show nSt ++ "`)"+  | otherwise = error $ "AtCoder.SegTree.new: given negative size (`" ++ show nSt ++ "`)"  -- | Creates an array with initial values. --@@ -218,6 +220,25 @@   for_ [1 .. logSt] $ \i -> do     update self ((p + sizeSt) .>>. i) +-- | (Extra API) Writes \(p\)-th value of the array to \(x\) and returns the old value.+--+-- ==== Constraints+-- - \(0 \leq p \lt n\)+--+-- ==== Complexity+-- - \(O(\log n)\)+--+-- @since 1.1.0.0+{-# INLINE exchange #-}+exchange :: (HasCallStack, PrimMonad m, Monoid a, VU.Unbox a) => SegTree (PrimState m) a -> Int -> a -> m a+exchange self@SegTree {..} p x = do+  let !_ = ACIA.checkIndex "AtCoder.SegTree.exchange" p nSt+  ret <- VGM.exchange dSt (p + sizeSt) x+  VGM.write dSt (p + sizeSt) x+  for_ [1 .. logSt] $ \i -> do+    update self ((p + sizeSt) .>>. i)+  pure ret+ -- | Returns \(p\)-th value of the array. -- -- ==== Constraints@@ -249,8 +270,8 @@   | ACIA.testInterval l0 r0 nSt = unsafeProd self l0 r0   | otherwise = ACIA.errorInterval "AtCoder.SegTree.prod" l0 r0 nSt --- | Total version of `prod`. Returns \(a[l] \cdot ... \cdot a[r - 1]\), assuming the properties of--- the monoid. It returns `Just` `mempty` if \(l = r\). It return `Nothing` if the interval is+-- | Total variant of `prod`. Returns \(a[l] \cdot ... \cdot a[r - 1]\), assuming the properties of+-- the monoid. It returns `Just` `mempty` if \(l = r\). Returns `Nothing` if the interval is -- invalid. -- -- ==== Complexity@@ -315,10 +336,19 @@ -- -- @since 1.0.0.0 {-# INLINE minLeft #-}-minLeft :: (HasCallStack, PrimMonad m, Monoid a, VU.Unbox a) => SegTree (PrimState m) a -> Int -> (a -> Bool) -> m Int+minLeft ::+  (HasCallStack, PrimMonad m, Monoid a, VU.Unbox a) =>+  -- | The segment tree+  SegTree (PrimState m) a ->+  -- | \(r\)+  Int ->+  -- | \(p\): user prediate+  (a -> Bool) ->+  -- | \(l\): \(p\) holds for \([l, r)\)+  m Int minLeft seg r0 f = minLeftM seg r0 (pure . f) --- | Monadic version of `minLeft`.+-- | Monadic variant of `minLeft`. -- -- ==== Constraints --@@ -332,7 +362,16 @@ -- -- @since 1.0.0.0 {-# INLINE minLeftM #-}-minLeftM :: (HasCallStack, PrimMonad m, Monoid a, VU.Unbox a) => SegTree (PrimState m) a -> Int -> (a -> m Bool) -> m Int+minLeftM ::+  (HasCallStack, PrimMonad m, Monoid a, VU.Unbox a) =>+  -- | The segment tree+  SegTree (PrimState m) a ->+  -- | \(r\)+  Int ->+  -- | \(p\): user prediate+  (a -> m Bool) ->+  -- | \(l\): \(p\) holds for \([l, r)\)+  m Int minLeftM SegTree {..} r0 f = do   b <- f mempty   let !_ = ACIA.runtimeAssert b "AtCoder.SegTree.minLeftM: `f empty` returned `False`"@@ -385,10 +424,19 @@ -- -- @since 1.0.0.0 {-# INLINE maxRight #-}-maxRight :: (HasCallStack, PrimMonad m, Monoid a, VU.Unbox a) => SegTree (PrimState m) a -> Int -> (a -> Bool) -> m Int+maxRight ::+  (HasCallStack, PrimMonad m, Monoid a, VU.Unbox a) =>+  -- | The segment tree+  SegTree (PrimState m) a ->+  -- | \(l\)+  Int ->+  -- | \(p\): user prediate+  (a -> Bool) ->+  -- | \(r\): \(p\) holds for \([l, r)\)+  m Int maxRight seg l0 f = maxRightM seg l0 (pure . f) --- | Moandic version of `maxRight`.+-- | Moandic variant of `maxRight`. -- -- ==== Constraints -- - if \(f\) is called with the same argument, it returns the same value, i.e., \(f\) has no side effect.@@ -400,7 +448,16 @@ -- -- @since 1.0.0.0 {-# INLINE maxRightM #-}-maxRightM :: (HasCallStack, PrimMonad m, Monoid a, VU.Unbox a) => SegTree (PrimState m) a -> Int -> (a -> m Bool) -> m Int+maxRightM ::+  (HasCallStack, PrimMonad m, Monoid a, VU.Unbox a) =>+  -- | The segment tree+  SegTree (PrimState m) a ->+  -- | \(l\)+  Int ->+  -- | \(p\): user prediate+  (a -> m Bool) ->+  -- | \(r\): \(p\) holds for \([l, r)\)+  m Int maxRightM SegTree {..} l0 f = do   b <- f mempty   let !_ = ACIA.runtimeAssert b "AtCoder.SegTree.maxRightM: `f mempty` returned `False`"
src/AtCoder/String.hs view
@@ -1,9 +1,9 @@ -- | It contains string algorithms. ----- Let @s@ be a string. We denote the substring of @s@ between \(a\)-th and \(b - 1\)-th character--- by @s[a..b)@.+-- Let \(s\) be a string. We denote the substring of \(s\) between \(a\)-th and \(b - 1\)-th+-- character by \(s[a..b)\). ----- ==== Examples+-- ==== __Examples__ -- -- ===== Suffix Array and LCP Array --@@ -32,9 +32,9 @@     -- * LCP array     lcpArray,     lcpArrayBS,-    zAlgorithm,      -- * Z algorithm+    zAlgorithm,     zAlgorithmBS,   ) where@@ -55,9 +55,9 @@  -- | Calculates suffix array for a `Int` vector. ----- Given a string @s@ of length \(n\), it returns the suffix array of @s@. Here, the suffix array--- @sa@ of @s@ is a permutation of \(0, \cdots, n-1\) such that @s[sa[i]..n) < s[sa[i+1]..n)@ holds--- for all \(i = 0,1, \cdots ,n-2\).+-- Given a string \(s\) of length \(n\), it returns the suffix array of \(s\). Here, the suffix array+-- \(\mathrm{sa}\) of \(s\) is a permutation of \(0, \cdots, n-1\) such that \(s[\mathrm{sa}[i]..n) < s[\mathrm{sa}[i+1]..n)\)+-- holds for all \(i = 0,1, \cdots ,n-2\). -- -- ==== Constraints -- - \(0 \leq n\)@@ -65,7 +65,7 @@ -- - \(0 \leq x \leq \mathrm{upper}\) for all elements \(x\) of \(s\). -- -- ==== Complexity--- - (3) \(O(n + \mathrm{upper})\)-time+-- - \(O(n + \mathrm{upper})\)-time -- -- @since 1.0.0.0 {-# INLINE suffixArray #-}@@ -81,7 +81,7 @@ -- - \(0 \leq n\) -- -- ==== Complexity--- - (1) \(O(n)\)-time+-- - \(O(n)\)-time -- -- @since 1.0.0.0 {-# INLINE suffixArrayBS #-}@@ -97,7 +97,8 @@ -- - \(0 \leq n\) -- -- ==== Complexity--- - (2) \(O(n \log n)\)-time, \(O(n)\)-space+-- - \(O(n \log n)\)-time+-- - \(O(n)\)-space -- -- @since 1.0.0.0 {-# INLINE suffixArrayOrd #-}@@ -124,12 +125,12 @@         (upper_,) <$> VU.unsafeFreeze vec    in ACIS.saIs s2 upper --- | Given a string @s@ of length \(n\), it returns the LCP array of @s@. Here, the LCP array of--- @s@ is the array of length \(n-1\), such that the \(i\)-th element is the length of the LCP--- (Longest Common Prefix) of @s[sa[i]..n)@ and @s[sa[i+1]..n)@+-- | Given a string \(s\) of length \(n\), it returns the LCP array of \(s\). Here, the LCP array of+-- \(s\) is the array of length \(n-1\), such that the \(i\)-th element is the length of the LCP+-- (Longest Common Prefix) of \(s[\mathrm{sa}[i]..n)\) and \(s[\mathrm{sa}[i+1]..n)\). -- -- ==== Constraints--- - The second argument is the suffix array of @s@.+-- - The second argument is the suffix array of \(s\). -- - \(1 \leq n\) -- -- ==== Complexity@@ -137,7 +138,14 @@ -- -- @since 1.0.0.0 {-# INLINE lcpArray #-}-lcpArray :: (HasCallStack, Ord a, VU.Unbox a) => VU.Vector a -> VU.Vector Int -> VU.Vector Int+lcpArray ::+  (HasCallStack, Ord a, VU.Unbox a) =>+  -- | A vector representing a string+  VU.Vector a ->+  -- | Suffix array+  VU.Vector Int ->+  -- | LCP array+  VU.Vector Int lcpArray s sa =   let n = VU.length s       !_ = ACIA.runtimeAssert (n >= 1) "AtCoder.String.lcpArray: given empty input"@@ -167,10 +175,10 @@           rnk         pure lcp --- | @ByteString@ verison of `lcpArray`.+-- | @ByteString@ variant of `lcpArray`. -- -- ==== Constraints--- - The second argument is the suffix array of @s@.+-- - The second argument is the suffix array of \(s\). -- - \(1 \leq n\) -- -- ==== Complexity@@ -178,17 +186,25 @@ -- -- @since 1.0.0.0 {-# INLINE lcpArrayBS #-}-lcpArrayBS :: (HasCallStack) => BS.ByteString -> VU.Vector Int -> VU.Vector Int+lcpArrayBS ::+  (HasCallStack) =>+  -- | String+  BS.ByteString ->+  -- | Suffix array+  VU.Vector Int ->+  -- | LCP array+  VU.Vector Int lcpArrayBS s sa =   let n = BS.length s       s2 = VU.map ord . VU.fromListN n $ BS.unpack s    in lcpArray s2 sa  -- | Given a `Ord` vector of length \(n\), it returns the array of length \(n\), such that the--- \(i\)-th element is the length of the LCP (Longest Common Prefix) of @s[0..n)@ and @s[i..n)@.+-- \(i\)-th element is the length of the LCP (Longest Common Prefix) of \(s[0..n)\) and \(s[i..n)\). -- -- ==== Constraints -- - \(n \leq n\)+-- -- ==== Complexity -- - \(O(n)\) --@@ -227,10 +243,11 @@     n = VU.length s  -- | Given a string of length \(n\), it returns the array of length \(n\), such that the \(i\)-th--- element is the length of the LCP (Longest Common Prefix) of @s[0..n)@ and @s[i..n)@.+-- element is the length of the LCP (Longest Common Prefix) of \(s[0..n)\) and \(s[i..n)\). -- -- ==== Constraints -- - \(n \leq n\)+-- -- ==== Complexity -- - \(O(n)\) --
src/AtCoder/TwoSat.hs view
@@ -8,7 +8,7 @@ -- -- it decides whether there is a truth assignment that satisfies all clauses. ----- ==== Example+-- ==== __Example__ -- >>> import AtCoder.TwoSat qualified as TS -- >>> import Data.Bit (Bit(..)) -- >>> ts <- TS.new 1
test/Main.hs view
@@ -4,8 +4,20 @@ import Test.Tasty.Ingredients.Rerun import Tests.Convolution qualified import Tests.Dsu qualified+import Tests.Extra.Bisect qualified+import Tests.Extra.HashMap qualified+import Tests.Extra.IntMap qualified+import Tests.Extra.IntSet qualified+import Tests.Extra.IntervalMap qualified import Tests.Extra.Math qualified import Tests.Extra.Monoid qualified+import Tests.Extra.MultiSet qualified+import Tests.Extra.Semigroup.Matrix qualified+import Tests.Extra.Semigroup.Permutation qualified+import Tests.Extra.WaveletMatrix qualified+import Tests.Extra.WaveletMatrix.BitVector qualified+import Tests.Extra.WaveletMatrix.Raw qualified+import Tests.Extra.WaveletMatrix2d qualified import Tests.FenwickTree qualified import Tests.Internal.Bit qualified import Tests.Internal.Buffer qualified@@ -31,8 +43,23 @@     . testGroup "toplevel"     $ [ testGroup "Convolution" Tests.Convolution.tests,         testGroup "Dsu" Tests.Dsu.tests,-        testGroup "Extra.Math" Tests.Extra.Math.tests,-        testGroup "Extra.Monoid" Tests.Extra.Monoid.tests,+        testGroup+          "Extra"+          [ testGroup "Bisect" Tests.Extra.Bisect.tests,+            testGroup "HashMap" Tests.Extra.HashMap.tests,+            testGroup "IntervalMap" Tests.Extra.IntervalMap.tests,+            testGroup "IntMap" Tests.Extra.IntMap.tests,+            testGroup "IntSet" Tests.Extra.IntSet.tests,+            testGroup "Math" Tests.Extra.Math.tests,+            testGroup "Monoid" Tests.Extra.Monoid.tests,+            testGroup "MultiSet" Tests.Extra.MultiSet.tests,+            testGroup "Semigroup.Matrix" Tests.Extra.Semigroup.Matrix.tests,+            testGroup "Semigroup.Permutation" Tests.Extra.Semigroup.Permutation.tests,+            testGroup "WaveletMatrix" Tests.Extra.WaveletMatrix.tests,+            testGroup "WaveletMatrix.BitVector" Tests.Extra.WaveletMatrix.BitVector.tests,+            testGroup "WaveletMatrix.Raw" Tests.Extra.WaveletMatrix.Raw.tests,+            testGroup "WaveletMatrix2d" Tests.Extra.WaveletMatrix2d.tests+          ],         testGroup "FenwickTree" Tests.FenwickTree.tests,         testGroup           "Internal"
+ test/Tests/Extra/Bisect.hs view
@@ -0,0 +1,114 @@+module Tests.Extra.Bisect where++import AtCoder.Extra.Bisect+import Data.List qualified as L+import Data.Vector.Generic qualified as VG+import Data.Vector.Unboxed qualified as VU+import Test.Tasty+import Test.Tasty.QuickCheck as QC++-- | Takes half-open interval [l, r).+naivePartition :: Int -> Int -> (Int -> Bool) -> VU.Vector Int -> (Maybe Int, Maybe Int)+naivePartition l r p xs+  | l >= r = (Nothing, Nothing)+  | otherwise = case (VU.null ls, VU.null rs) of+      (True, True) -> error "unreachable"+      (False, True) -> (Just l', Nothing)+      (True, False) -> (Nothing, Just r')+      _ -> (Just l', Just r')+  where+    xs' = VU.take (r - l) . VU.drop l $ xs+    (!ls, !rs) = VU.partition p xs'+    l' = l + VU.length ls - 1+    r' = l' + 1++naiveLowerBound :: VU.Vector Int -> Int -> Maybe Int+naiveLowerBound xs = naiveLowerBoundIn 0 (VU.length xs) xs++naiveLowerBoundIn :: Int -> Int -> VU.Vector Int -> Int -> Maybe Int+naiveLowerBoundIn l r xs target = case naivePartition l r (< target) xs of+  (!_, Just i) -> Just i+  _ -> Nothing++naiveUpperBound :: VU.Vector Int -> Int -> Maybe Int+naiveUpperBound xs = naiveUpperBoundIn 0 (VU.length xs) xs++naiveUpperBoundIn :: Int -> Int -> VU.Vector Int -> Int -> Maybe Int+naiveUpperBoundIn l r xs target = case naivePartition l r (<= target) xs of+  (!_, Just i) -> Just i+  _ -> Nothing++boundsQueryGen :: Gen (Int, Int, VU.Vector Int)+boundsQueryGen = do+  n <- QC.chooseInt (1, 100)+  p <- QC.chooseInt (-25, 25)+  xs <- VU.fromList . L.sort <$> QC.vectorOf n (QC.chooseInt (-20, 20))+  pure (n, p, xs)++bisectQueryGen :: Gen (Int, Int, VU.Vector Int, [(Int, Int)])+bisectQueryGen = do+  n <- QC.chooseInt (1, 100)+  p <- QC.chooseInt (-25, 25)+  xs <- VU.fromList . L.sort <$> QC.vectorOf n (QC.chooseInt (-20, 20))+  let lrs = [(l, r) | l <- [0 .. n], r <- [l .. n]]+  pure (n, p, xs, lrs)++prop_lowerBound :: TestTree+prop_lowerBound = QC.testProperty "lowerBound" $ do+  (!_, !target, !xs) <- boundsQueryGen+  pure $ naiveLowerBound xs target QC.=== lowerBound xs target++prop_lowerBoundIn :: TestTree+prop_lowerBoundIn = QC.testProperty "lowerBoundIn" $ do+  (!_, !target, !xs, !lrs) <- bisectQueryGen+  pure . QC.conjoin $+    map+      ( \(!l, !r) ->+          naiveLowerBoundIn l r xs target == lowerBoundIn l r xs target+      )+      lrs++prop_upperBound :: TestTree+prop_upperBound = QC.testProperty "upperBound" $ do+  (!_, !target, !xs) <- boundsQueryGen+  pure $ naiveUpperBound xs target QC.=== upperBound xs target++prop_upperBoundIn :: TestTree+prop_upperBoundIn = QC.testProperty "upperBoundIn" $ do+  (!_, !target, !xs, !lrs) <- bisectQueryGen+  pure . QC.conjoin $+    map+      ( \(!l, !r) ->+          naiveUpperBoundIn l r xs target == upperBoundIn l r xs target+      )+      lrs++prop_bisectL :: TestTree+prop_bisectL = QC.testProperty "bisectL" $ do+  (!_, !boundary, !xs, !lrs) <- bisectQueryGen+  pure . QC.conjoin $+    map+      ( \(!l, !r) ->+          fst (naivePartition l r (<= boundary) xs) == bisectL l r (\i -> xs VG.! i <= boundary)+      )+      lrs++prop_bisectR :: TestTree+prop_bisectR = QC.testProperty "bisectR" $ do+  (!_, !boundary, !xs, !lrs) <- bisectQueryGen+  pure . QC.conjoin $+    map+      ( \(!l, !r) ->+          snd (naivePartition l r (<= boundary) xs) == bisectR l r (\i -> xs VG.! i <= boundary)+      )+      lrs++tests :: [TestTree]+tests =+  [ prop_lowerBound,+    prop_upperBound,+    prop_lowerBoundIn,+    prop_upperBoundIn,+    prop_bisectL,+    prop_bisectR+  ]
+ test/Tests/Extra/Graph.hs view
@@ -0,0 +1,52 @@+module Tests.Extra.Graph where++import AtCoder.Extra.Graph qualified as Gr+import AtCoder.Internal.Buffer qualified as B+import Control.Monad (unless)+import Control.Monad.Fix (fix)+import Control.Monad.ST (runST)+import Data.List qualified as L+import Data.Vector.Generic qualified as VG+import Data.Vector.Unboxed qualified as VU+import Data.Vector.Unboxed.Mutable qualified as VUM+import Test.Tasty+import Test.Tasty.QuickCheck as QC++genDag :: Int -> QC.Gen (Gr.Csr ())+genDag n = do+  edges <- VU.fromList <$> QC.sublistOf [(u, v) | u <- [0 .. n - 1], v <- [u + 1 .. n - 1]]+  verts <- VU.fromList <$> QC.shuffle [0 .. n - 1]+  pure $ Gr.build n $ VU.map (\(!u, !v) -> (verts VG.! u, verts VG.! v, ())) edges++dfs :: Int -> (Int -> VU.Vector Int) -> Int -> VU.Vector Int+dfs n gr u0 = runST $ do+  buf <- B.new n+  vis <- VUM.replicate n False+  flip fix u0 $ \loop u -> do+    VU.forM_ (gr u) $ \v -> do+      b <- VUM.read vis v+      unless b $ do+        B.pushBack buf v+        loop v+  B.unsafeFreeze buf++testTopSort :: Int -> Gr.Csr () -> VU.Vector Int -> Bool+testTopSort n gr vs = and+    [ VU.notElem v (dfs n (gr `Gr.adj`) u)+      | u <- (vs VG.!) <$> [0 .. n - 1],+        v <- (vs VG.!) <$> [u + 1 .. n - 1]+    ]++-- | Tests lexicographically smallest topological ordering.+prop_topSort :: QC.Gen QC.Property+prop_topSort = do+  n <- QC.chooseInt (1, 8)+  dag <- genDag n+  let vs = Gr.topSort n (dag `Gr.adj`)+  let perms = map (VU.fromListN n) $ L.permutations [0 .. n - 1]+  pure $ vs QC.=== head (filter (testTopSort n dag) perms)++tests :: [TestTree]+tests =+  [ QC.testProperty "topSort" prop_topSort+  ]
+ test/Tests/Extra/HashMap.hs view
@@ -0,0 +1,171 @@+{-# LANGUAGE RecordWildCards #-}++module Tests.Extra.HashMap where++import AtCoder.Extra.HashMap qualified as HM+import Control.Monad (foldM_)+import Control.Monad.Primitive (PrimMonad, PrimState)+import Control.Monad.ST (RealWorld)+import Data.HashMap.Strict qualified as HMR -- R: referencial implementation+import Data.Vector.Algorithms.Intro qualified as VAI+import Data.Vector.Unboxed qualified as VU+import System.IO.Unsafe (unsafePerformIO)+import Test.Hspec+import Test.QuickCheck.Monadic as QCM+import Test.Tasty+import Test.Tasty.Hspec+import Test.Tasty.QuickCheck as QC++spec_invalid :: IO TestTree+spec_invalid = testSpec "capacity limit" $ do+  it "throws error 1" $ do+    hm <- HM.new @_ @Int 1+    HM.insert hm 0 0+    HM.insert hm 0 1+    HM.insert hm 1 2 `shouldThrow` anyException++  it "throws error 2" $ do+    hm <- HM.new @_ @Int 2+    HM.insert hm 0 0+    HM.insert hm 1 1+    HM.insert hm 1 2+    HM.insert hm 2 2 `shouldThrow` anyException++data Init = Init+  { capacity :: {-# UNPACK #-} !Int,+    ref0 :: !(HMR.HashMap Int Int),+    hmM :: !(IO (HM.HashMap RealWorld Int))+  }++instance Show Init where+  show Init {..} = show (capacity, ref0)++instance QC.Arbitrary Init where+  arbitrary = do+    capacity <- QC.chooseInt (1, 10)+    pure $ Init capacity HMR.empty (HM.new capacity)++data Query+  = Size+  | Member Int+  | NotMember Int+  | Lookup Int+  | Insert Int Int+  | InsertWithAdd Int Int+  | Exchange Int Int+  | ModifyAdd Int Int+  | Clear+  deriving (Show)++instance QC.Arbitrary Query where+  arbitrary = do+    a <- QC.chooseInt (1, 100)+    if a == 1+      then pure Clear+      else+        QC.oneof+          [ pure Size,+            Member <$> keyGen,+            NotMember <$> keyGen,+            Lookup <$> keyGen,+            Insert <$> keyGen <*> valGen,+            InsertWithAdd <$> keyGen <*> valGen,+            Exchange <$> keyGen <*> valGen,+            ModifyAdd <$> keyGen <*> valGen+          ]+    where+      keyGen = QC.chooseInt (-5, 5)+      valGen = QC.chooseInt (-10, 10)++-- | Arbitrary return type for the `Query` result.+data Result+  = None+  | B Bool+  | I Int+  | M (Maybe Int)+  deriving (Show, Eq)++-- | containers. (referencial implementation)+handleRef :: HMR.HashMap Int Int -> Query -> (HMR.HashMap Int Int, Result)+handleRef hm q = case q of+  Size -> (hm, I $ HMR.size hm)+  Member k -> (hm, B $ HMR.member k hm)+  NotMember k -> (hm, B . not $ HMR.member k hm)+  Lookup k -> (hm, M $ HMR.lookup k hm)+  Insert k v -> (HMR.insert k v hm, None)+  InsertWithAdd k v -> (HMR.insertWith (+) k v hm, None)+  Exchange k v -> (HMR.insert k v hm, M $ HMR.lookup k hm)+  ModifyAdd k v -> (HMR.adjust (+ v) k hm, None)+  -- Delete k -> (HMR.delete k hm, HMR.lookup k hm)+  Clear -> (HMR.empty, None)++-- | ac-library-hs.+handleAcl :: (PrimMonad m) => HM.HashMap (PrimState m) Int -> Query -> m Result+handleAcl hm q = case q of+  Size -> I <$> HM.size hm+  Member k -> B <$> HM.member hm k+  NotMember k -> B <$> HM.notMember hm k+  Lookup k -> M <$> HM.lookup hm k+  Insert k v -> do+    HM.insert hm k v+    pure None+  InsertWithAdd k v -> do+    HM.insertWith hm (+) k v+    pure None+  Exchange k v -> M <$> HM.exchange hm k v+  ModifyAdd k v -> do+    HM.modify hm (+ v) k+    pure None+  -- Delete k -> HM.delete hm k+  Clear -> do+    HM.clear hm+    pure None++-- | Ensures the capacity limit.+passQuery :: Int -> HMR.HashMap Int Int -> Query -> Bool+passQuery limit is (Insert k _) = HMR.member k is || HMR.size is < limit+passQuery limit is (InsertWithAdd k _) = HMR.member k is || HMR.size is < limit+passQuery limit is (Exchange k _) = HMR.member k is || HMR.size is < limit+passQuery _ _ _ = True++prop_randomTest :: Init -> QC.Property+prop_randomTest Init {..} = QCM.monadicIO $ do+  hm <- QCM.run hmM+  q <- QCM.pick $ QC.chooseInt (1, 5 * capacity)+  qs <- QCM.pick $ QC.vectorOf q (QC.arbitrary @Query)+  foldM_+    ( \ref query -> do+        if passQuery capacity ref query+          then do+            let (!ref', !expected) = handleRef ref query+            res <- QCM.run $ handleAcl hm query+            QCM.assertWith (expected == res) $ show (query, expected, res)++            -- check the map contents:+            let assocsE = VU.modify (VAI.sortBy compare) . VU.fromList $ HMR.toList ref'+            assocs <- QCM.run $ VU.modify (VAI.sortBy compare) <$> HM.unsafeAssocs hm+            QCM.assertWith (assocsE == assocs) $ show ("- assocs", assocsE, assocs)++            let keysE = VU.modify (VAI.sortBy compare) . VU.fromList $ HMR.keys ref'+            keys <- QCM.run $ VU.modify (VAI.sortBy compare) <$> HM.unsafeKeys hm+            QCM.assertWith (keysE == keys) $ show ("- keys", keysE, keys)++            let elemsE = VU.modify (VAI.sortBy compare) . VU.fromList $ HMR.elems ref'+            elems <- QCM.run $ VU.modify (VAI.sortBy compare) <$> HM.unsafeElems hm+            QCM.assertWith (elemsE == elems) $ show ("- elems", elemsE, elems)++            let sizeE = HMR.size ref'+            size <- QCM.run $ HM.size hm+            QCM.assertWith (sizeE == size) $ show ("- size", sizeE, size)++            pure ref'+          else pure ref+    )+    ref0+    qs++tests :: [TestTree]+tests =+  [ unsafePerformIO spec_invalid,+    QC.testProperty "random test" prop_randomTest+  ]
+ test/Tests/Extra/IntMap.hs view
@@ -0,0 +1,176 @@+{-# LANGUAGE RecordWildCards #-}++module Tests.Extra.IntMap where++import AtCoder.Extra.IntMap qualified as IM+import Control.Monad (foldM_)+import Control.Monad.Primitive (PrimMonad, PrimState)+import Control.Monad.ST (RealWorld)+import Data.Map.Strict qualified as IMR -- R: referencial implementation+import Data.Vector.Unboxed qualified as VU+import GHC.Stack (HasCallStack)+import Test.QuickCheck.Monadic as QCM+import Test.Tasty+import Test.Tasty.QuickCheck as QC++data Init = Init+  { n :: {-# UNPACK #-} !Int,+    ref0 :: !(IMR.Map Int Int),+    imM :: !(IO (IM.IntMap RealWorld Int))+  }++instance Show Init where+  show Init {..} = show (n, ref0)++instance QC.Arbitrary Init where+  arbitrary = do+    n <- QC.chooseInt (1, 10)+    pure $ Init n IMR.empty (IM.new n)++data Query+  = Size+  | Member Int+  | NotMember Int+  | Null+  | Lookup Int+  | Insert Int Int+  | InsertWithAdd Int Int+  | Delete Int+  | Delete_ Int+  | LookupGE Int+  | LookupGT Int+  | LookupLE Int+  | LookupLT Int+  | LookupMin+  | LookupMax+  | DeleteMin+  | DeleteMax+  deriving (Show)++-- | Arbitrary return type for the `Query` result.+data Result+  = None+  | B Bool+  | I Int+  | M (Maybe Int)+  | KV (Maybe (Int, Int))+  | XS (VU.Vector Int)+  | KVS (VU.Vector (Int, Int))+  deriving (Show, Eq)++queryGen :: Int -> QC.Gen Query+queryGen n = do+  QC.oneof+    [ pure Size,+      Member <$> lookupKeyGen,+      NotMember <$> lookupKeyGen,+      pure Null,+      Lookup <$> lookupKeyGen,+      -- insert is partial function+      Insert <$> insertKeyGen <*> valGen,+      InsertWithAdd <$> insertKeyGen <*> valGen,+      Delete <$> lookupKeyGen,+      Delete_ <$> lookupKeyGen,+      LookupGE <$> lookupKeyGen,+      LookupGT <$> lookupKeyGen,+      LookupLE <$> lookupKeyGen,+      LookupLT <$> lookupKeyGen,+      pure LookupMin,+      pure LookupMax+    ]+  where+    -- for total functions+    lookupKeyGen = QC.chooseInt (-1, n)+    -- for partial functions+    insertKeyGen = QC.chooseInt (0, n - 1)+    valGen = QC.chooseInt (-10, 10)++-- | containers. (referencial implementation)+handleRef :: IMR.Map Int Int -> Query -> (IMR.Map Int Int, Result)+handleRef im q = case q of+  Size -> (im, I $ IMR.size im)+  Member k -> (im, B $ IMR.member k im)+  NotMember k -> (im, B . not $ IMR.member k im)+  Null -> (im, B $ IMR.null im)+  Lookup k -> (im, M $ IMR.lookup k im)+  Insert k v -> (IMR.insert k v im, None)+  InsertWithAdd k v -> (IMR.insertWith (+) k v im, None)+  Delete k -> (IMR.delete k im, B $ IMR.member k im)+  Delete_ k -> (IMR.delete k im, None)+  LookupGE k -> (im, KV (IMR.lookupGE k im))+  LookupGT k -> (im, KV (IMR.lookupGT k im))+  LookupLE k -> (im, KV (IMR.lookupLE k im))+  LookupLT k -> (im, KV (IMR.lookupLT k im))+  LookupMin -> (im, KV (IMR.lookupMin im))+  LookupMax -> (im, KV (IMR.lookupMax im))+  DeleteMin -> wrapKV IMR.deleteFindMin+  DeleteMax -> wrapKV IMR.deleteFindMax+  where+    wrapKV f+      | IMR.null im = (im, KV Nothing)+      | otherwise = let (!kv, !im') = f im in (im', KV (Just kv))++-- | ac-library-hs.+handleAcl :: (HasCallStack, PrimMonad m) => IM.IntMap (PrimState m) Int -> Query -> m Result+handleAcl im q = case q of+  Size -> I <$> IM.size im+  Member k -> B <$> IM.member im k+  NotMember k -> B <$> IM.notMember im k+  Null -> B <$> IM.null im+  Lookup k -> M <$> IM.lookup im k+  Insert k v -> do+    IM.insert im k v+    pure None+  InsertWithAdd k v -> do+    IM.insertWith im (+) k v+    pure None+  Delete k -> B <$> IM.delete im k+  Delete_ k -> do+    IM.delete_ im k+    pure None+  LookupGE k -> KV <$> IM.lookupGE im k+  LookupGT k -> KV <$> IM.lookupGT im k+  LookupLE k -> KV <$> IM.lookupLE im k+  LookupLT k -> KV <$> IM.lookupLT im k+  LookupMin -> KV <$> IM.lookupMin im+  LookupMax -> KV <$> IM.lookupMax im+  DeleteMin -> KV <$> IM.deleteMin im+  DeleteMax -> KV <$> IM.deleteMax im++prop_randomTest :: Init -> QC.Property+prop_randomTest Init {..} = QCM.monadicIO $ do+  im <- QCM.run imM+  q <- QCM.pick $ QC.chooseInt (1, 5 * n)+  qs <- QCM.pick $ QC.vectorOf q (queryGen n)+  foldM_+    ( \ref query -> do+        let (!ref', !expected) = handleRef ref query+        res <- QCM.run $ handleAcl im query+        QCM.assertWith (expected == res) $ show (query, expected, res)++        -- check the map contents:+        let assocsE = VU.fromList $ IMR.assocs ref'+        assocs <- QCM.run $ IM.assocs im+        QCM.assertWith (assocsE == assocs) $ show ("- assocs", assocsE, assocs)++        let keysE = VU.fromList $ IMR.keys ref'+        keys <- QCM.run $ IM.keys im+        QCM.assertWith (keysE == keys) $ show ("- keys", keysE, keys)++        let elemsE = VU.fromList $ IMR.elems ref'+        elems <- QCM.run $ IM.elems im+        QCM.assertWith (elemsE == elems) $ show ("- elems", elemsE, elems)++        let sizeE = IMR.size ref'+        size <- QCM.run $ IM.size im+        QCM.assertWith (sizeE == size) $ show ("- size", sizeE, size)++        pure ref'+    )+    ref0+    qs++tests :: [TestTree]+tests =+  [ QC.testProperty "randomTest" prop_randomTest+  ]
+ test/Tests/Extra/IntSet.hs view
@@ -0,0 +1,150 @@+{-# LANGUAGE RecordWildCards #-}++module Tests.Extra.IntSet where++import AtCoder.Extra.IntSet qualified as IS+import Control.Monad (foldM_)+import Control.Monad.Primitive (PrimMonad, PrimState)+import Control.Monad.ST (RealWorld)+import Data.Set qualified as ISR -- R: referencial implementation+import Data.Vector.Unboxed qualified as VU+import GHC.Stack (HasCallStack)+import Test.QuickCheck.Monadic as QCM+import Test.Tasty+import Test.Tasty.QuickCheck as QC++data Init = Init+  { n :: {-# UNPACK #-} !Int,+    ref0 :: !(ISR.Set Int),+    isM :: !(IO (IS.IntSet RealWorld))+  }++instance Show Init where+  show Init {..} = show (n, ref0)++instance QC.Arbitrary Init where+  arbitrary = do+    n <- QC.chooseInt (1, 10)+    pure $ Init n ISR.empty (IS.new n)++data Query+  = Member Int+  | NotMember Int+  | Null+  | Insert Int+  | Delete Int+  | Delete_ Int+  | LookupGE Int+  | LookupGT Int+  | LookupLE Int+  | LookupLT Int+  | LookupMin+  | LookupMax+  | DeleteMin+  | DeleteMax+  deriving (Show)++-- | Arbitrary return type for the `Query` result.+data Result+  = None+  | B Bool+  | I Int+  | M (Maybe Int)+  deriving (Show, Eq)++queryGen :: Int -> QC.Gen Query+queryGen n = do+  QC.oneof+    [ Member <$> lookupKeyGen,+      NotMember <$> lookupKeyGen,+      pure Null,+      -- insert is partial function+      Insert <$> insertKeyGen,+      Delete <$> lookupKeyGen,+      Delete_ <$> lookupKeyGen,+      LookupGE <$> lookupKeyGen,+      LookupGT <$> lookupKeyGen,+      LookupLE <$> lookupKeyGen,+      LookupLT <$> lookupKeyGen,+      pure LookupMin,+      pure LookupMax+    ]+  where+    -- for total functions+    lookupKeyGen = QC.chooseInt (-1, n)+    -- for partial functions+    insertKeyGen = QC.chooseInt (0, n - 1)++-- | containers. (referencial implementation)+handleRef :: ISR.Set Int -> Query -> (ISR.Set Int, Result)+handleRef is q = case q of+  Member k -> (is, B $ ISR.member k is)+  NotMember k -> (is, B . not $ ISR.member k is)+  Null -> (is, B $ ISR.null is)+  Insert k -> (ISR.insert k is, None)+  Delete k -> (ISR.delete k is, B $ ISR.member k is)+  Delete_ k -> (ISR.delete k is, None)+  LookupGE k -> (is, M (ISR.lookupGE k is))+  LookupGT k -> (is, M (ISR.lookupGT k is))+  LookupLE k -> (is, M (ISR.lookupLE k is))+  LookupLT k -> (is, M (ISR.lookupLT k is))+  LookupMin -> (is, M (ISR.lookupMin is))+  LookupMax -> (is, M (ISR.lookupMax is))+  DeleteMin -> wrapK ISR.deleteFindMin+  DeleteMax -> wrapK ISR.deleteFindMax+  where+    wrapK f+      | ISR.null is = (is, M Nothing)+      | otherwise = let (!kv, !is') = f is in (is', M (Just kv))++-- | ac-library-hs.+handleAcl :: (HasCallStack, PrimMonad m) => IS.IntSet (PrimState m) -> Query -> m Result+handleAcl is q = case q of+  Member k -> B <$> IS.member is k+  NotMember k -> B <$> IS.notMember is k+  Null -> B <$> IS.null is+  Insert k -> do+    IS.insert is k+    pure None+  Delete k -> B <$> IS.delete is k+  Delete_ k -> do+    IS.delete_ is k+    pure None+  LookupGE k -> M <$> IS.lookupGE is k+  LookupGT k -> M <$> IS.lookupGT is k+  LookupLE k -> M <$> IS.lookupLE is k+  LookupLT k -> M <$> IS.lookupLT is k+  LookupMin -> M <$> IS.lookupMin is+  LookupMax -> M <$> IS.lookupMax is+  DeleteMin -> M <$> IS.deleteMin is+  DeleteMax -> M <$> IS.deleteMax is++prop_randomTest :: Init -> QC.Property+prop_randomTest Init {..} = QCM.monadicIO $ do+  is <- QCM.run isM+  q <- QCM.pick $ QC.chooseInt (1, 5 * n)+  qs <- QCM.pick $ QC.vectorOf q (queryGen n)+  foldM_+    ( \ref query -> do+        let (!ref', !expected) = handleRef ref query+        res <- QCM.run $ handleAcl is query+        QCM.assertWith (expected == res) $ show (query, expected, res)++        -- check the set contents:+        let keysE = VU.fromList $ ISR.elems ref'+        keys <- QCM.run $ IS.keys is+        QCM.assertWith (keysE == keys) $ show ("- keys", keysE, keys)++        let sizeE = ISR.size ref'+        size <- QCM.run $ IS.size is+        QCM.assertWith (sizeE == size) $ show ("- size", sizeE, size)++        pure ref'+    )+    ref0+    qs++tests :: [TestTree]+tests =+  [ QC.testProperty "randomTest" prop_randomTest+  ]
+ test/Tests/Extra/IntervalMap.hs view
@@ -0,0 +1,209 @@+{-# LANGUAGE RecordWildCards #-}++module Tests.Extra.IntervalMap where++import AtCoder.Extra.IntervalMap qualified as ITM+import AtCoder.Internal.Buffer qualified as ACIB+import Control.Monad.Primitive (PrimMonad, PrimState)+import Control.Monad.ST (RealWorld, runST)+import Data.Foldable (for_)+import Data.List qualified as L+import Data.Map qualified as M+import Data.Primitive.MutVar+import Data.Vector.Generic.Mutable qualified as VGM+import Data.Vector.Unboxed qualified as VU+import Data.Vector.Unboxed.Mutable qualified as VUM+import Test.QuickCheck.Monadic as QCM+import Test.Tasty+import Test.Tasty.HUnit+import Test.Tasty.QuickCheck as QC+import Tests.Util (intervalGen)++-- | buildM should call onAdd and onDel correctly+prop_buildM :: QC.Gen QC.Property+prop_buildM = do+  n <- QC.chooseInt (1, 10)+  xs <- QC.vectorOf n (QC.chooseInt (-1, 1))++  let groups = VU.group $ VU.fromList xs+  let lens = L.scanl' (+) (0 :: Int) $ map VU.length groups+  let expected = VU.fromList $ L.zip3 lens (tail lens) (L.map VU.head groups)++  let res = runST $ do+        buf <- ACIB.new @_ @(Int, Int, Int) n+        _ <- ITM.buildM (VU.fromList xs) $ \l r x -> do+          ACIB.pushBack buf (l, r, x)+        ACIB.freeze buf++  pure $ res QC.=== expected++data Init = Init+  { n :: {-# UNPACK #-} !Int,+    refM :: !(IO (VUM.MVector RealWorld Int)),+    itmM :: !(IO (ITM.IntervalMap RealWorld Int))+  }++instance Show Init where+  show Init {..} = show ("Init", n)++instance QC.Arbitrary Init where+  arbitrary = do+    n <- QC.chooseInt (1, 20)+    pure $ Init n (VUM.replicate n undef) (ITM.new n)++data Query+  = Contains Int+  | Intersects (Int, Int)+  | Lookup (Int, Int)+  | -- | Read (Int, Int)+    ReadMaybe (Int, Int)+  | Insert (Int, Int) Int+  | Delete (Int, Int)+  | Overwrite (Int, Int) Int+  | Freeze+  | TestFreq+  deriving (Show)++-- | Arbitrary return type for the `Query` result.+data Result+  = None+  | B Bool+  | I Int+  | LRX (Maybe (Int, Int, Int))+  | M (Maybe Int)+  | XS (VU.Vector (Int, (Int, Int)))+  | -- | Counts (len * (len + 1) / 2) for each interval and sum them up.+    Freq (M.Map Int Int)+  deriving (Show, Eq)++queryGen :: Int -> QC.Gen Query+queryGen n = do+  QC.oneof+    [ Contains <$> keyGen,+      Intersects <$> intervalGen n,+      Lookup <$> intervalGen n,+      ReadMaybe <$> intervalGen n,+      Insert <$> intervalGen n <*> valGen,+      Delete <$> intervalGen n,+      Overwrite <$> intervalGen n <*> valGen,+      pure Freeze+      -- TestFreq is manually given+      -- pure TestFreq+    ]+  where+    keyGen = QC.chooseInt (0, n - 1)+    valGen = QC.chooseInt (-20, 20)++undef :: Int+undef = minBound `div` 2++-- | Half-open intervals.+toIntervals :: (PrimMonad m) => VUM.MVector (PrimState m) Int -> m (VU.Vector (Int, Int, Int))+toIntervals vec = do+  vec' <- VU.freeze vec+  let groups = VU.group vec'+  let lens = L.scanl' (+) (0 :: Int) $ map VU.length groups+  let intervals = zipWith (\xs l -> (l, l + VU.length xs, VU.head xs)) groups lens+  pure . VU.fromList $ filter (\(!_, !_, !x) -> x /= undef) intervals++-- | containers. (referencial implementation)+handleRef :: (PrimMonad m) => VUM.MVector (PrimState m) Int -> Query -> m Result+handleRef vec q = do+  intervals <- toIntervals vec+  case q of+    Contains i -> do+      pure . B $ VU.any (\(!l, !r, !_) -> l <= i && i < r) intervals+    Intersects (!l, !r)+      | l >= r -> pure $ B False+      | otherwise -> pure . B $ VU.any (\(!l', !r', !_) -> l' <= l && r <= r') intervals+    Lookup (!l, !r)+      | l >= r -> pure $ LRX Nothing+      | otherwise -> pure . LRX $ VU.find (\(!l', !r', !_) -> l' <= l && r <= r') intervals+    ReadMaybe (!l, !r)+      | l >= r -> pure $ M Nothing+      | otherwise -> pure $ maybe (M Nothing) (M . Just . (\(!_, !_, !x) -> x)) $ VU.find (\(!l', !r', !_) -> l' <= l && r <= r') intervals+    Insert (!l, !r) x -> do+      for_ [l .. r - 1] $ \i -> do+        VGM.write vec i x+      pure None+    Delete (!l, !r) -> do+      for_ [l .. r - 1] $ \i -> do+        VGM.write vec i undef+      pure None+    Overwrite (!l, !r) x+      | l >= r -> pure None+      | otherwise -> do+          let interval = VU.find (\(!l', !r', !_) -> l' <= l && r <= r') intervals+          case interval of+            Just (!l', !r', !_) -> do+              for_ [l' .. r' - 1] $ \i -> do+                VGM.write vec i x+            _ -> pure ()+          pure None+    Freeze -> pure . XS $ VU.map (\(!l, !r, !x) -> (l, (r, x))) intervals+    TestFreq -> pure . Freq . M.fromListWith (+) . VU.toList $ VU.map (\(!l, !r, !x) -> (x, (r - l) * ((r - l) + 1) `div` 2)) intervals++-- | ac-library-hs.+handleAcl :: (HasCallStack, PrimMonad m) => MutVar (PrimState m) (M.Map Int Int) -> ITM.IntervalMap (PrimState m) Int -> Query -> m Result+handleAcl freq itm q = case q of+  Contains i -> do+    B <$> ITM.contains itm i+  Intersects (!l, !r) -> do+    B <$> ITM.intersects itm l r+  Lookup (!l, !r) -> do+    LRX <$> ITM.lookup itm l r+  ReadMaybe (!l, !r) -> do+    M <$> ITM.readMaybe itm l r+  Insert (!l, !r) x -> do+    ITM.insertM itm l r x onAdd onDel+    pure None+  Delete (!l, !r) -> do+    ITM.deleteM itm l r onAdd onDel+    pure None+  Overwrite (!l, !r) x -> do+    ITM.overwriteM itm l r x onAdd onDel+    pure None+  Freeze -> do+    XS . VU.map (\(!l, (!r, !x)) -> (l, (r, x))) <$> ITM.freeze itm+  TestFreq -> Freq <$> readMutVar freq+  where+    onAdd l r x = do+      let len = r - l+      let delta = len * (len + 1) `div` 2+      modifyMutVar freq $ M.insertWith (+) x delta+    onDel l r x = modifyMutVar freq $ \m -> do+      let len = r - l+      let delta = len * (len + 1) `div` 2+      case M.lookup x m of+        Just n+          | n - delta == 0 -> M.delete x m+          | otherwise -> M.insert x (n - delta) m+        Nothing -> M.insert x delta m++prop_randomTest :: Init -> QC.Property+prop_randomTest Init {..} = QCM.monadicIO $ do+  ref <- QCM.run refM+  im <- QCM.run itmM+  freq <- QCM.run $ newMutVar M.empty+  q <- QCM.pick $ QC.chooseInt (1, 10 * n)+  qs <- QCM.pick $ QC.vectorOf q (queryGen n)+  for_ qs $ \query -> do+    expected <- QCM.run $ handleRef ref query+    res <- QCM.run $ handleAcl freq im query+    QCM.assertWith (expected == res) $ show (query, expected, res)++    -- always test Freq as an invariant+    expectedI <- QCM.run $ handleRef ref Freeze+    resI <- QCM.run $ handleAcl freq im Freeze+    QCM.assertWith (expectedI == resI) $ show (Freeze, expectedI, resI)++    -- always test Freq as an invariant+    expectedF <- QCM.run $ handleRef ref TestFreq+    resF <- QCM.run $ handleAcl freq im TestFreq+    QCM.assertWith (expectedF == resF) $ show (TestFreq, expectedF, resF)++tests :: [TestTree]+tests =+  [ QC.testProperty "buildM" prop_buildM,+    QC.testProperty "randomTest" prop_randomTest+  ]
test/Tests/Extra/Monoid.hs view
@@ -1,7 +1,11 @@ module Tests.Extra.Monoid (tests) where  import AtCoder.Extra.Monoid-import Data.Bit (Bit(..))+import AtCoder.Extra.Monoid.Affine1 qualified as A+import AtCoder.Extra.Monoid.Mat2x2 qualified as M+import AtCoder.Extra.Monoid.RollingHash (RollingHash (..))+import AtCoder.ModInt qualified as ModInt+import Data.Bit (Bit (..)) import Data.Proxy (Proxy (..)) import Data.Semigroup (Max (..), Min (..), Product (..), Sum (..), stimes) import Test.QuickCheck.Classes qualified as QCC@@ -71,10 +75,6 @@   arbitrary = RangeAdd <$> QC.arbitrary  -- orphan instance-instance (QC.Arbitrary a) => QC.Arbitrary (RangeAddId a) where-  arbitrary = RangeAddId <$> QC.arbitrary---- orphan instance instance (QC.Arbitrary a, Monoid a) => QC.Arbitrary (RangeSet a) where   arbitrary = do     b <- (== 1) <$> QC.chooseInt (1, 30)@@ -83,12 +83,19 @@       else pure mempty  -- orphan instance-instance (QC.Arbitrary a, Monoid a) => QC.Arbitrary (RangeSetId a) where+instance (QC.Arbitrary a) => QC.Arbitrary (Mat2x2 a) where+  arbitrary = Mat2x2 <$> QC.arbitrary++-- orphan instance+instance (QC.Arbitrary a) => QC.Arbitrary (V2 a) where+  arbitrary = V2 <$> QC.arbitrary++-- orphan instance+instance QC.Arbitrary (RollingHash b 998244353) where   arbitrary = do-    b <- (== 1) <$> QC.chooseInt (1, 30)-    if b-      then RangeSetId . (Bit True,) <$> QC.arbitrary-      else pure mempty+    hash <- QC.chooseInt (0, 998244353 - 1)+    next <- QC.chooseInt (0, 998244353 - 1)+    pure $ RollingHash hash next  -- orphan instance instance QC.Arbitrary (Max Int) where@@ -98,11 +105,53 @@ instance QC.Arbitrary (Min Int) where   arbitrary = Min <$> QC.arbitrary +-- orphan instance (TODO: move to common implementation)+instance QC.Arbitrary ModInt.ModInt998244353 where+  arbitrary = ModInt.new <$> QC.arbitrary++prop_affineZero :: Affine1 (Sum Int) -> QC.Property+prop_affineZero a =+  QC.conjoin+    [ A.zero <> a QC.=== A.zero,+      a <> A.zero QC.=== (\(A.Affine1 (!_, !b)) -> A.Affine1 (0, b)) a+    ]++prop_affineIdent :: Affine1 (Sum Int) -> QC.Property+prop_affineIdent a =+  QC.conjoin+    [ A.ident <> a QC.=== a,+      a <> A.ident QC.=== a+    ]++prop_mat2x2Zero :: Mat2x2 Int -> QC.Property+prop_mat2x2Zero a =+  QC.conjoin+    [ M.zero <> a QC.=== M.zero,+      a <> M.zero QC.=== M.zero+    ]++prop_mat2x2Ident :: Mat2x2 Int -> QC.Property+prop_mat2x2Ident a =+  QC.conjoin+    [ M.ident <> a QC.=== a,+      a <> M.ident QC.=== a+    ]++prop_mat2x2Inv :: Mat2x2 ModInt.ModInt998244353 -> QC.Property+prop_mat2x2Inv a =+  (M.det a /= 0 QC.==>) $+    QC.conjoin+      [ M.inv a <> a QC.=== M.ident,+        a <> M.inv a QC.=== M.ident+      ]+ tests :: [TestTree] tests =   [ testGroup       "Affine1"-      [ laws @(Affine1 (Sum Int))+      [ QC.testProperty "zero" prop_affineZero,+        QC.testProperty "ident" prop_affineIdent,+        laws @(Affine1 (Sum Int))           [ QCC.semigroupLaws,             QCC.monoidLaws,             QCC.semigroupMonoidLaws@@ -113,26 +162,28 @@       ],     testGroup       "RangeAdd"-      [ laws @(RangeAdd Int)+      [ laws @(RangeAdd (Sum Int))           [ QCC.semigroupLaws,             QCC.monoidLaws,             QCC.semigroupMonoidLaws           ],-        laws @(RangeAdd Int, Sum Int)+        laws @(RangeAdd (Sum Int), Sum Int)           [ segActLaw-          ]-      ],-    testGroup-      "RangeAddId"-      [ laws @(RangeAddId Int)+          ],+        laws @(RangeAdd (Max Int))           [ QCC.semigroupLaws,             QCC.monoidLaws,             QCC.semigroupMonoidLaws           ],-        laws @(RangeAddId Int, Max Int)+        laws @(RangeAdd (Max Int), Max Int)           [ segActLaw           ],-        laws @(RangeAddId Int, Min Int)+        laws @(RangeAdd (Min Int))+          [ QCC.semigroupLaws,+            QCC.monoidLaws,+            QCC.semigroupMonoidLaws+          ],+        laws @(RangeAdd (Min Int), Min Int)           [ segActLaw           ]       ],@@ -143,65 +194,62 @@             QCC.monoidLaws,             QCC.semigroupMonoidLaws           ],+        laws @(RangeSet (Sum Int), Sum Int)+          [ segActLaw+          ],         laws @(RangeSet (Product Int))           [ QCC.semigroupLaws,             QCC.monoidLaws,             QCC.semigroupMonoidLaws           ],+        laws @(RangeSet (Product Int), Product Int)+          [ segActLaw+          ],         laws @(RangeSet (Max Int))           [ QCC.semigroupLaws,             QCC.monoidLaws,             QCC.semigroupMonoidLaws           ],+        laws @(RangeSet (Max Int), Max Int)+          [ segActLaw+          ],         laws @(RangeSet (Min Int))           [ QCC.semigroupLaws,             QCC.monoidLaws,             QCC.semigroupMonoidLaws           ],-        laws @(RangeSet (Sum Int), Sum Int)-          [ segActLaw-          ],-        laws @(RangeSet (Product Int), Product Int)-          [ segActLaw-          ],-        laws @(RangeSet (Max Int), Max Int)-          [ segActLaw-          ],         laws @(RangeSet (Min Int), Min Int)           [ segActLaw           ]       ],     testGroup-      "RangeSetId"-      [ laws @(RangeSetId (Sum Int))+      "Mat2x2"+      [ QC.testProperty "zero" prop_mat2x2Zero,+        QC.testProperty "ident" prop_mat2x2Ident,+        QC.testProperty "inv" prop_mat2x2Inv,+        laws @(Mat2x2 Int)           [ QCC.semigroupLaws,-            QCC.idempotentSemigroupLaws,             QCC.monoidLaws,             QCC.semigroupMonoidLaws           ],-        laws @(RangeSetId (Product Int))+        laws @(Mat2x2 Int, V2 Int)+          [ segActLaw+          ]+      ],+    testGroup+      "V2"+      [ laws @(V2 Int)           [ QCC.semigroupLaws,-            QCC.idempotentSemigroupLaws,             QCC.monoidLaws,             QCC.semigroupMonoidLaws-          ],-        laws @(RangeSetId (Max Int))+          ]+      ],+    testGroup+      "RollingHash"+      [ laws @(RollingHash 100 998244353)           [ QCC.semigroupLaws,-            QCC.idempotentSemigroupLaws,             QCC.monoidLaws,             QCC.semigroupMonoidLaws-          ],-        laws @(RangeSetId (Min Int))-          [ QCC.semigroupLaws,-            QCC.idempotentSemigroupLaws,-            QCC.monoidLaws,-            QCC.semigroupMonoidLaws-          ],-        laws @(RangeSetId (Max Int), Max Int)-          [ segActLaw-          ],-        laws @(RangeSetId (Min Int), Min Int)-          [ segActLaw           ]       ]   ]
+ test/Tests/Extra/MultiSet.hs view
@@ -0,0 +1,218 @@+{-# LANGUAGE RecordWildCards #-}++module Tests.Extra.MultiSet (tests) where++import AtCoder.Extra.MultiSet qualified as MS+import Control.Monad (foldM_, when)+import Control.Monad.Primitive (PrimMonad, PrimState)+import Control.Monad.ST (RealWorld)+import Data.IntMap qualified as IM+import Data.IntSet qualified as IS+import Data.Vector.Algorithms.Intro qualified as VAI+import Data.Vector.Unboxed qualified as VU+import System.IO.Unsafe (unsafePerformIO)+import Test.Hspec+import Test.QuickCheck.Monadic as QCM+import Test.Tasty+import Test.Tasty.Hspec+import Test.Tasty.QuickCheck as QC++spec_invalid :: IO TestTree+spec_invalid = testSpec "capacity limit" $ do+  it "throws error 1" $ do+    ms <- MS.new @_ 1+    MS.inc ms 0+    MS.inc ms 0+    MS.inc ms 1 `shouldThrow` anyException++  it "throws error 2" $ do+    ms <- MS.new @_ 2+    MS.inc ms 0+    MS.inc ms 1+    MS.inc ms 2 `shouldThrow` anyException++  it "throws error 2" $ do+    ms <- MS.new @_ 2+    MS.inc ms 0+    MS.inc ms 1+    MS.delete ms 1+    MS.inc ms 2 `shouldThrow` anyException++data Init = Init+  { n :: {-# UNPACK #-} !Int,+    ref0 :: !(IM.IntMap Int),+    msM :: !(IO (MS.MultiSet RealWorld))+  }++instance Show Init where+  show Init {..} = show (n, ref0)++instance QC.Arbitrary Init where+  arbitrary = do+    n <- QC.chooseInt (1, 10)+    pure $ Init n IM.empty (MS.new n)++data Query+  = Member Int+  | NotMember Int+  | Lookup Int+  | Inc Int+  | -- Safe* are performed to not create negative count+    SafeDec Int+  | SafeAdd Int Int+  | SafeSub Int Int+  | Insert Int Int+  | Delete Int+  deriving (Show)++-- | Arbitrary return type for the `Query` result.+data Result+  = None+  | B Bool+  | I Int+  | M (Maybe Int)+  deriving (Show, Eq)++queryGen :: Int -> QC.Gen Query+queryGen n = do+  QC.oneof+    [ Member <$> keyGen,+      NotMember <$> keyGen,+      Lookup <$> keyGen,+      Inc <$> keyGen,+      SafeDec <$> keyGen,+      SafeAdd <$> keyGen <*> deltaGen,+      SafeSub <$> keyGen <*> deltaGen,+      Insert <$> keyGen <*> insertValGen,+      Delete <$> keyGen+    ]+  where+    keyGen = QC.chooseInt (-n, n)+    deltaGen = QC.chooseInt (-n, n)+    insertValGen = QC.chooseInt (1, n)++-- | containers. (referencial implementation)+handleRef :: IM.IntMap Int -> Query -> (IM.IntMap Int, Result)+handleRef im q = case q of+  Member key -> (im, B $ IM.member key im)+  NotMember key -> (im, B $ IM.notMember key im)+  Lookup key -> (im, M $ IM.lookup key im)+  Inc key -> (IM.insertWith (+) key 1 im, None)+  SafeDec key -> case IM.lookup key im of+    Just 1 -> (IM.delete key im, None)+    Just n -> (IM.insert key (n - 1) im, None)+    Nothing -> (im, None)+  SafeAdd key dx -> case IM.lookup key im of+    Just n | n + dx == 0 -> (IM.delete key im, None)+    Just n | n + dx > 0 -> (IM.insert key (n + dx) im, None)+    Nothing | dx > 0 -> (IM.insert key dx im, None)+    _ -> (im, None)+  SafeSub key dx -> case IM.lookup key im of+    Just n | n - dx == 0 -> (IM.delete key im, None)+    Just n | n - dx > 0 -> (IM.insert key (n - dx) im, None)+    Nothing | -dx > 0 -> (IM.insert key (-dx) im, None)+    _ -> (im, None)+  Insert key val -> (IM.insert key val im, None)+  Delete key -> (IM.delete key im, None)++-- | ac-library-hs.+handleAcl :: (HasCallStack, PrimMonad m) => MS.MultiSet (PrimState m) -> Query -> m Result+handleAcl ms q = case q of+  Member key -> B <$> MS.member ms key+  NotMember key -> B <$> MS.notMember ms key+  Lookup key -> M <$> MS.lookup ms key+  Inc key -> do+    MS.inc ms key+    pure None+  SafeDec key -> do+    b <- MS.member ms key+    when b $ do+      MS.dec ms key+    pure None+  SafeAdd key dx -> do+    MS.lookup ms key >>= \case+      Just n | n + dx >= 0 -> do+        MS.add ms key dx+      Nothing | dx >= 0 -> do+        MS.add ms key dx+      _ -> pure ()+    pure None+  SafeSub key dx -> do+    MS.lookup ms key >>= \case+      Just n | n - dx >= 0 -> do+        MS.sub ms key dx+      Nothing | -dx >= 0 -> do+        MS.sub ms key dx+      _ -> pure ()+    pure None+  Insert key val -> do+    MS.insert ms key val+    pure None+  Delete key -> do+    MS.delete ms key+    pure None++-- | Ensures the capacity limit.+passQuery :: Int -> IS.IntSet -> Query -> Bool+passQuery limit is (Inc k) = IS.member k is || IS.size is < limit+passQuery limit is (SafeAdd k dx) = IS.member k is || IS.size is < limit || dx <= 0+passQuery limit is (SafeSub k dx) = IS.member k is || IS.size is < limit || dx >= 0+passQuery limit is (Insert k _) = IS.member k is || IS.size is < limit+passQuery _ _ _ = True++-- | Records used keys.+recordKey :: IS.IntSet -> Query -> IS.IntSet+recordKey is (Inc k) = IS.insert k is+recordKey is (SafeAdd k dx) | dx > 0 = IS.insert k is+recordKey is (SafeSub k dx) | dx < 0 = IS.insert k is+recordKey is (Insert k _) = IS.insert k is+recordKey is _ = is++-- TODO: record used key++prop_randomTest :: Init -> QC.Property+prop_randomTest Init {..} = QCM.monadicIO $ do+  ms <- QCM.run msM+  q <- QCM.pick $ QC.chooseInt (1, 5 * n)+  qs <- QCM.pick $ QC.vectorOf q (queryGen n)++  foldM_+    ( \(!ref, !keys) query -> do+        if passQuery n keys query+          then do+            -- run the query+            let (!ref', !expected) = handleRef ref query+            res <- QCM.run $ handleAcl ms query+            QCM.assertWith (expected == res) $ show (query, expected, res)++            -- check the map contents:+            let assocsE = VU.modify (VAI.sortBy compare) (VU.fromList (IM.assocs ref'))+            assocs <- QCM.run $ VU.modify (VAI.sortBy compare) <$> MS.unsafeAssocs ms+            QCM.assertWith (assocsE == assocs) $ show ("- assocs", assocsE, assocs)++            let keysE = VU.modify (VAI.sortBy compare) (VU.fromList (IM.keys ref'))+            keys_ <- QCM.run $ VU.modify (VAI.sortBy compare) <$> MS.unsafeKeys ms+            QCM.assertWith (keysE == keys_) $ show ("- keys", keysE, keys_)++            let elemsE = VU.modify (VAI.sortBy compare) (VU.fromList (IM.elems ref'))+            elems <- QCM.run $ VU.modify (VAI.sortBy compare) <$> MS.unsafeElems ms+            QCM.assertWith (elemsE == elems) $ show ("- elems", elemsE, elems)++            let sizeE = IM.size ref'+            size <- QCM.run $ MS.size ms+            QCM.assertWith (sizeE == size) $ show ("- size", sizeE, size)++            pure (ref', recordKey keys query)+          else+            pure (ref, keys)+    )+    (ref0, IS.empty)+    qs++-- TODO: test invariant++tests :: [TestTree]+tests =+  [ unsafePerformIO spec_invalid,+    QC.testProperty "random test" prop_randomTest+  ]
+ test/Tests/Extra/Semigroup/Matrix.hs view
@@ -0,0 +1,43 @@+module Tests.Extra.Semigroup.Matrix (tests) where++import AtCoder.Extra.Semigroup.Matrix qualified as Mat+import AtCoder.ModInt qualified as M+import Data.Vector.Unboxed qualified as VU+import GHC.TypeNats (KnownNat)+import Test.QuickCheck.Classes qualified as QCC+import Test.Tasty+import Test.Tasty.QuickCheck qualified as QC+import Tests.Util (laws)++-- TODO: (const True) should be removed++-- orphan instance+instance (QC.Arbitrary a, VU.Unbox a) => QC.Arbitrary (Mat.Matrix a) where+  -- for simplicity, make a 33x33 matrix+  arbitrary = do+    let n = 33+    vec <- VU.fromList <$> QC.vectorOf (n * n) (QC.arbitrary @a)+    pure $ Mat.Matrix n n vec++-- orphan instance+instance (KnownNat p) => QC.Arbitrary (M.ModInt p) where+  arbitrary = M.new <$> QC.arbitrary++prop_mulToCol :: QC.Gen QC.Property+prop_mulToCol = do+  h <- QC.chooseInt (1, 16)+  w <- QC.chooseInt (1, 16)+  vec <- VU.fromList <$> QC.vectorOf (h * w) (QC.arbitrary @Int)+  let mat = Mat.new h w vec+  col <- VU.fromList <$> QC.vectorOf w (QC.arbitrary @Int)+  let lhs = Mat.mulToCol mat col+  let rhs = Mat.vecM $ Mat.mul mat (Mat.new w 1 col)+  pure  $ lhs QC.=== rhs++tests :: [TestTree]+tests =+  [ QC.testProperty "mulToCol" prop_mulToCol,+    laws @(Mat.Matrix (M.ModInt 998244353))+      [ QCC.semigroupLaws+      ]+  ]
+ test/Tests/Extra/Semigroup/Permutation.hs view
@@ -0,0 +1,71 @@+module Tests.Extra.Semigroup.Permutation (tests) where++import AtCoder.Extra.Semigroup.Permutation qualified as P+import Control.Exception (evaluate)+import Data.Vector.Unboxed qualified as VU+import System.IO.Unsafe (unsafePerformIO)+import Test.Hspec+import Test.QuickCheck.Classes qualified as QCC+import Test.Tasty+import Test.Tasty.Hspec+import Test.Tasty.QuickCheck as QC+import Tests.Util (laws)++spec_invalid :: IO TestTree+spec_invalid = testSpec "boundary check" $ do+  let !_ = P.new $ VU.fromList [0]+  let !_ = P.new $ VU.fromList [-1] -- -1 is allowed+  it "throws error 1" $ do+    evaluate (P.new (VU.fromList [1])) `shouldThrow` anyException+  it "throws error 2" $ do+    evaluate (P.new (VU.fromList [-2])) `shouldThrow` anyException++prop_ident :: P.Permutation -> QC.Property+prop_ident p =+  QC.conjoin+    [ p <> ident QC.=== p,+      ident <> p QC.=== p+    ]+  where+    ident = P.ident (P.length p)++prop_zero :: P.Permutation -> QC.Property+prop_zero p =+  QC.conjoin+    [ p <> zero QC.=== zero,+      zero <> p QC.=== zero+    ]+  where+    zero = P.zero (P.length p)++prop_identAct :: QC.Positive Int -> QC.Gen QC.Property+prop_identAct (QC.Positive len) = do+  let p = P.ident len+  i <- QC.chooseInt (0, len - 1)+  pure $ P.act p i QC.=== i++prop_zeroAct :: QC.Positive Int -> QC.Gen QC.Property+prop_zeroAct (QC.Positive len) = do+  let p = P.zero len+  i <- QC.chooseInt (0, len - 1)+  pure $ P.act p i QC.=== i++-- orphan instance+instance QC.Arbitrary P.Permutation where+  arbitrary = do+    let n = 33+    vec <- VU.fromList <$> QC.vectorOf n (QC.chooseInt (-1, n - 1))+    pure $ P.new vec++tests :: [TestTree]+tests =+  [ unsafePerformIO spec_invalid,+    QC.testProperty "ident" prop_ident,+    QC.testProperty "zero" prop_zero,+    QC.testProperty "identAct" prop_identAct,+    QC.testProperty "zeroAct" prop_zeroAct,+    laws+      @P.Permutation+      [ QCC.semigroupLaws+      ]+  ]
+ test/Tests/Extra/WaveletMatrix.hs view
@@ -0,0 +1,237 @@+{-# LANGUAGE RecordWildCards #-}++module Tests.Extra.WaveletMatrix (tests) where++import AtCoder.Extra.WaveletMatrix qualified as WM+import Data.IntMap qualified as IM+import Data.Ord (comparing)+import Data.Vector.Algorithms.Intro qualified as VAI+import Data.Vector.Unboxed qualified as VU+import Test.Hspec+import Test.Tasty+import Test.Tasty.HUnit+import Test.Tasty.QuickCheck as QC+import Tests.Util (intervalGen)++data Init = Init+  { capacity :: {-# UNPACK #-} !Int,+    xs :: !(VU.Vector Int),+    wm :: !WM.WaveletMatrix+  }++instance Show Init where+  show Init {..} = show ("Init", capacity, xs)++instance QC.Arbitrary Init where+  arbitrary = do+    QC.NonNegative n <- QC.arbitrary+    xs <- VU.fromListN n <$> QC.vectorOf n (QC.arbitrary @Int)+    pure $ Init n xs (WM.build xs)++data Query+  = Access !Int+  | KthSmallestIn !(Int, Int) !Int+  | IKthSmallestIn !(Int, Int) !Int+  | KthLargestIn !(Int, Int) !Int+  | IKthLargestIn !(Int, Int) !Int+  | RankBetween !(Int, Int) !(Int, Int)+  | Rank !(Int, Int) !Int+  | Select !Int+  | SelectIn !(Int, Int) !Int+  | SelectKth !Int !Int+  | SelectKthIn !(Int, Int) !Int !Int+  | LookupLE !(Int, Int) !Int+  | LookupLT !(Int, Int) !Int+  | LookupGE !(Int, Int) !Int+  | LookupGT !(Int, Int) !Int+  | AssocsIn !(Int, Int)+  | DescAssocsIn !(Int, Int)+  deriving (Show)++genQuery :: Int -> QC.Gen Query+genQuery n = do+  QC.oneof+    [ Access <$> QC.chooseInt (-1, n),+      KthSmallestIn <$> lr <*> exc,+      IKthSmallestIn <$> lr <*> exc,+      KthLargestIn <$> lr <*> exc,+      IKthLargestIn <$> lr <*> exc,+      RankBetween <$> lr <*> lr,+      Rank <$> lr <*> val,+      Select <$> val,+      SelectIn <$> lr <*> val,+      SelectKth <$> exc <*> val,+      SelectKthIn <$> lr <*> exc <*> val,+      LookupLE <$> lr <*> QC.chooseInt (-1, n),+      LookupLT <$> lr <*> QC.chooseInt (-1, n),+      LookupGE <$> lr <*> QC.chooseInt (-1, n),+      LookupGT <$> lr <*> QC.chooseInt (-1, n),+      AssocsIn <$> lr,+      DescAssocsIn <$> lr+    ]+  where+    exc = QC.chooseInt (0, n)+    lr = intervalGen n+    val = QC.chooseInt (-n, n)++-- | Arbitrary return type for the `Query` result.+data Result+  = I {-# UNPACK #-} !Int+  | M !(Maybe Int)+  | M2 !(Maybe (Int, Int))+  | Assocs [(Int, Int)]+  deriving (Show, Eq)++-- | containers. (referencial implementation)+handleRef :: VU.Vector Int -> Query -> Result+handleRef xs q = case q of+  Access i -> M $ xs VU.!? i+  KthSmallestIn (!l, !r) k -> M $ snd <$> ikthSmallestIn l r k+  IKthSmallestIn (!l, !r) k -> M2 $ ikthSmallestIn l r k+  KthLargestIn (!l, !r) k -> M $ snd <$> ikthLargestIn l r k+  IKthLargestIn (!l, !r) k -> M2 $ ikthLargestIn l r k+  RankBetween (!l, !r) (!xl, !xr) -> rankBetween l r xl xr+  Rank (!l, !r) x -> rankBetween l r x (x + 1)+  Select x -> M $ selectKthIn 0 n 0 x+  SelectIn (!l, !r) x -> M $ selectKthIn l r 0 x+  SelectKth k x -> M $ selectKthIn 0 n k x+  SelectKthIn (!l, !r) k x -> M $ selectKthIn l r k x+  LookupLE (!l, !r) x -> max_ . VU.filter (<= x) . VU.take (r - l) $ VU.drop l xs+  LookupLT (!l, !r) x -> max_ . VU.filter (< x) . VU.take (r - l) $ VU.drop l xs+  LookupGE (!l, !r) x -> min_ . VU.filter (>= x) . VU.take (r - l) $ VU.drop l xs+  LookupGT (!l, !r) x -> min_ . VU.filter (> x) . VU.take (r - l) $ VU.drop l xs+  AssocsIn (!l, !r) -> Assocs . IM.assocs . IM.fromListWith (+) . VU.toList . VU.map (,1) . VU.take (r - l) $ VU.drop l xs+  DescAssocsIn (!l, !r) -> Assocs . reverse . IM.assocs . IM.fromListWith (+) . VU.toList . VU.map (,1) . VU.take (r - l) $ VU.drop l xs+  where+    n = VU.length xs+    max_ ys+      | VU.null ys = M Nothing+      | otherwise = M $ Just $ VU.maximum ys+    min_ ys+      | VU.null ys = M Nothing+      | otherwise = M $ Just $ VU.minimum ys+    ikthSmallestIn l r k =+      (VU.!? k)+        . VU.modify (VAI.sortBy (comparing (\(!i, !x) -> (x, i))))+        . VU.take (r - l)+        . VU.drop l+        . VU.indexed+        $ xs+    ikthLargestIn l r k = ikthSmallestIn l r ((r - l) - (k + 1))+    rankBetween l r xl xr =+      I+        . VU.length+        . VU.filter (\x -> xl <= x && x < xr)+        . VU.take (r - l)+        . VU.drop l+        $ xs+    selectKthIn l r k x =+      (fst <$>)+        . (VU.!? k)+        . VU.filter ((== x) . snd)+        . VU.take (r - l)+        . VU.drop l+        . VU.indexed+        $ xs++handleAcl :: WM.WaveletMatrix -> Query -> Result+handleAcl wm q = case q of+  Access i -> M $ WM.access wm i+  KthSmallestIn (!l, !r) k -> M $ WM.kthSmallestIn wm l r k+  IKthSmallestIn (!l, !r) k -> M2 $ WM.ikthSmallestIn wm l r k+  KthLargestIn (!l, !r) k -> M $ WM.kthLargestIn wm l r k+  IKthLargestIn (!l, !r) k -> M2 $ WM.ikthLargestIn wm l r k+  RankBetween (!l, !r) (!xl, !xr) -> I $ WM.rankBetween wm l r xl xr+  Rank (!l, !r) x -> I $ WM.rankBetween wm l r x (x + 1)+  Select x -> M $ WM.select wm x+  SelectIn (!l, !r) x -> M $ WM.selectIn wm l r x+  SelectKth k x -> M $ WM.selectKth wm k x+  SelectKthIn (!l, !r) k x -> M $ WM.selectKthIn wm l r k x+  LookupLE (!l, !r) x -> M $ WM.lookupLE wm l r x+  LookupLT (!l, !r) x -> M $ WM.lookupLT wm l r x+  LookupGE (!l, !r) x -> M $ WM.lookupGE wm l r x+  LookupGT (!l, !r) x -> M $ WM.lookupGT wm l r x+  AssocsIn (!l, !r) -> Assocs $ WM.assocsIn wm l r+  DescAssocsIn (!l, !r) -> Assocs $ WM.descAssocsIn wm l r++prop_randomTest :: Init -> QC.Gen QC.Property+prop_randomTest Init {..} = do+  qs <- QC.vectorOf capacity (genQuery capacity)+  pure . QC.conjoin $+    map+      ( \q ->+          QC.counterexample (show q) $+            handleRef xs q QC.=== handleAcl wm q+      )+      qs++unit_boundary :: TestTree+unit_boundary = testCase "boundary" $ do+  let n = 5+  let wm = WM.build $ VU.fromList [0, 10, 20, 10, 0]++  let try :: (HasCallStack, Eq a, Show a) => (WM.WaveletMatrix -> Int -> Int -> Int -> Maybe a) -> Int -> IO ()+      try f x = do+        (@?= Nothing) $ f wm (-1) 0 x+        (@?= Nothing) $ f wm 20 (20 + 1) x++  let k = 0+  try WM.kthSmallestIn k+  try WM.ikthSmallestIn k+  try WM.kthLargestIn k+  try WM.ikthLargestIn k++-- try WM.unsafeKthSmallestIn+-- try WM.unsafeIKthSmallestIn+-- try WM.unsafeKthLargestIn+-- try WM.unsafeIKthLargestIn++  let tryRank :: (HasCallStack) => (WM.WaveletMatrix -> Int -> Int -> Int -> Int) -> Int -> IO ()+      tryRank f x = do+        -- out of range+        (@?= 0) $ f wm (-1) 0 x+        (@?= 0) $ f wm n (n + 1) x+        -- reverse+        (@?= 0) $ f wm 1 0 x+        (@?= 0) $ f wm n (n - 1) x+        (@?= 0) $ f wm n 0 x+        -- out of range and reverse+        (@?= 0) $ f wm 0 (-1) x+        (@?= 0) $ f wm (n + 1) n x++  let tryRankBetween :: (HasCallStack) => (WM.WaveletMatrix -> Int -> Int -> Int -> Int -> Int) -> Int -> Int -> IO ()+      tryRankBetween f xl xr = do+        -- out of range+        (@?= 0) $ f wm (-1) 0 xl xr+        (@?= 0) $ f wm n (n + 1) xl xr+        -- reverse+        (@?= 0) $ f wm 1 0 xl xr+        (@?= 0) $ f wm n (n - 1) xl xr+        (@?= 0) $ f wm n 0 xl xr+        -- out of range and reverse+        (@?= 0) $ f wm 0 (-1) xl xr+        (@?= 0) $ f wm (n + 1) n xl xr++  tryRankBetween WM.rankBetween (-1) 1+  tryRank WM.rank 0+  tryRank WM.rank 1+  tryRank WM.rank (-1)++-- TODO: test ++-- (@?= Nothing) $ WM.select wm+-- (@?= Nothing) $ WM.selectKth wm+-- (@?= Nothing) $ WM.selectKthIn wm++-- (@?= Nothing) $ WM.lookupLE wm+-- (@?= Nothing) $ WM.lookupLT wm+-- (@?= Nothing) $ WM.lookupGE wm+-- (@?= Nothing) $ WM.lookupGT wm+-- (@?= Nothing) $ WM.assocsIn wm+-- (@?= Nothing) $ WM.descAssocsIn wm++tests :: [TestTree]+tests =+  [ unit_boundary,+    QC.testProperty "random test" prop_randomTest+  ]
+ test/Tests/Extra/WaveletMatrix/BitVector.hs view
@@ -0,0 +1,84 @@+{-# LANGUAGE RecordWildCards #-}++module Tests.Extra.WaveletMatrix.BitVector where++import AtCoder.Extra.WaveletMatrix.BitVector qualified as BV+import Data.Bit (Bit (..))+import Data.Vector.Unboxed qualified as VU+import Test.Tasty+import Test.Tasty.QuickCheck as QC+import Tests.Util (intervalGen)++data Init = Init+  { capacity :: {-# UNPACK #-} !Int,+    ref :: !(VU.Vector Bool),+    bv :: !BV.BitVector+  }+  deriving (Eq, Show)++instance QC.Arbitrary Init where+  arbitrary = do+    QC.Positive capacity <- QC.arbitrary+    bs <- QC.vectorOf capacity (QC.arbitrary @Bool)+    pure $ Init capacity (VU.fromList bs) (BV.build (VU.fromList (map Bit bs)))++data Query+  = Rank0 {-# UNPACK #-} !Int+  | Rank1 {-# UNPACK #-} !Int+  | Select0 {-# UNPACK #-} !Int+  | Select1 {-# UNPACK #-} !Int+  | SelectKth0 {-# UNPACK #-} !(Int, Int) !Int+  | SelectKth1 {-# UNPACK #-} !(Int, Int) !Int+  deriving (Show)++genQuery :: Int -> QC.Gen Query+genQuery n = do+  QC.oneof+    [ Rank0 <$> QC.chooseInt (0, n),+      Rank1 <$> QC.chooseInt (0, n),+      Select0 <$> QC.chooseInt (0, n),+      Select1 <$> QC.chooseInt (0, n),+      SelectKth0 <$> intervalGen n <*> QC.chooseInt (0, n),+      SelectKth1 <$> intervalGen n <*> QC.chooseInt (0, n)+    ]++-- | Arbitrary return type for the `Query` result.+data Result+  = I {-# UNPACK #-} !Int+  | M !(Maybe Int)+  deriving (Show, Eq)++-- | containers. (referencial implementation)+handleRef :: VU.Vector Bool -> Query -> Result+handleRef xs q = case q of+  Rank0 k -> I . VU.length . VU.filter not $ VU.take k xs+  Rank1 k -> I . VU.length . VU.filter id $ VU.take k xs+  Select0 k -> M . (fst <$>) . (VU.!? k) . VU.filter (not . snd) $ VU.indexed xs+  Select1 k -> M . (fst <$>) . (VU.!? k) . VU.filter snd $ VU.indexed xs+  SelectKth0 (!l, !r) k -> M . (fst <$>) . (VU.!? k) . VU.filter (not . snd) . VU.take (r - l) . VU.drop l $ VU.indexed xs+  SelectKth1 (!l, !r) k -> M . (fst <$>) . (VU.!? k) . VU.filter snd . VU.take (r - l) . VU.drop l $ VU.indexed xs++handleAcl :: BV.BitVector -> Query -> Result+handleAcl bv q = case q of+  Rank0 k -> I $ BV.rank0 bv k+  Rank1 k -> I $ BV.rank1 bv k+  Select0 k -> M $ BV.select0 bv k+  Select1 k -> M $ BV.select1 bv k+  SelectKth0 (!l, !r) k -> M $ BV.selectKthIn0 bv l r k+  SelectKth1 (!l, !r) k -> M $ BV.selectKthIn1 bv l r k++prop_randomTest :: Init -> QC.Gen QC.Property+prop_randomTest Init {..} = do+  qs <- QC.vectorOf capacity (genQuery capacity)+  pure . QC.conjoin $+    map+      ( \q ->+          QC.counterexample (show q) $+            handleRef ref q QC.=== handleAcl bv q+      )+      qs++tests :: [TestTree]+tests =+  [ QC.testProperty "random test" prop_randomTest+  ]
+ test/Tests/Extra/WaveletMatrix/Raw.hs view
@@ -0,0 +1,271 @@+{-# LANGUAGE RecordWildCards #-}++module Tests.Extra.WaveletMatrix.Raw (tests) where++import AtCoder.Extra.Bisect (lowerBound)+import AtCoder.Extra.WaveletMatrix.Raw qualified as WM+import Control.Exception (evaluate)+import Data.IntMap qualified as IM+import Data.Maybe (fromJust)+import Data.Ord (comparing)+import Data.Vector.Algorithms.Intro qualified as VAI+import Data.Vector.Unboxed qualified as VU+import System.IO.Unsafe (unsafePerformIO)+import Test.Hspec+import Test.Tasty+import Test.Tasty.HUnit+import Test.Tasty.Hspec+import Test.Tasty.QuickCheck as QC+import Tests.Util (intervalGen)++compress :: VU.Vector Int -> VU.Vector Int+compress xs =+  let dict = VU.uniq $ VU.modify VAI.sort xs+   in VU.map (fromJust . lowerBound dict) xs++data Init = Init+  { capacity :: {-# UNPACK #-} !Int,+    xs :: !(VU.Vector Int),+    wm :: !WM.RawWaveletMatrix+  }+  deriving (Eq, Show)++instance QC.Arbitrary Init where+  arbitrary = do+    QC.NonNegative n <- QC.arbitrary+    xs <- compress . VU.fromListN n <$> QC.vectorOf n (QC.arbitrary @Int)+    pure $ Init n xs (WM.build n xs)++data Query+  = Access !Int+  | KthSmallestIn !(Int, Int) !Int+  | IKthSmallestIn !(Int, Int) !Int+  | KthLargestIn !(Int, Int) !Int+  | IKthLargestIn !(Int, Int) !Int+  | UnsafeKthSmallestIn !(Int, Int) !Int+  | UnsafeIKthSmallestIn !(Int, Int) !Int+  | UnsafeKthLargestIn !(Int, Int) !Int+  | UnsafeIKthLargestIn !(Int, Int) !Int+  | RankLT !(Int, Int) !Int+  | RankBetween !(Int, Int) !(Int, Int)+  | Rank !(Int, Int) !Int+  | Select !Int+  | SelectKth !Int !Int+  | SelectKthIn !(Int, Int) !Int !Int+  | LookupLE !(Int, Int) !Int+  | LookupLT !(Int, Int) !Int+  | LookupGE !(Int, Int) !Int+  | LookupGT !(Int, Int) !Int+  | AssocsIn !(Int, Int)+  | DescAssocsIn !(Int, Int)+  deriving (Show)++genQuery :: Int -> QC.Gen Query+genQuery n = do+  QC.oneof+    [ Access <$> QC.chooseInt (-1, n),+      KthSmallestIn <$> lr <*> exc,+      IKthSmallestIn <$> lr <*> exc,+      KthLargestIn <$> lr <*> exc,+      IKthLargestIn <$> lr <*> exc,+      UnsafeKthSmallestIn <$> lr <*> inc,+      UnsafeIKthSmallestIn <$> lr <*> inc,+      UnsafeKthLargestIn <$> lr <*> inc,+      UnsafeIKthLargestIn <$> lr <*> inc,+      RankLT <$> lr <*> val,+      RankBetween <$> lr <*> lr,+      Rank <$> lr <*> val,+      Select <$> val,+      SelectKth <$> exc <*> val,+      SelectKthIn <$> lr <*> exc <*> val,+      LookupLE <$> lr <*> QC.chooseInt (-1, n),+      LookupLT <$> lr <*> QC.chooseInt (-1, n),+      LookupGE <$> lr <*> QC.chooseInt (-1, n),+      LookupGT <$> lr <*> QC.chooseInt (-1, n),+      AssocsIn <$> lr,+      DescAssocsIn <$> lr+    ]+  where+    inc = QC.chooseInt (0, n - 1)+    exc = QC.chooseInt (0, n)+    lr = intervalGen n+    val = QC.chooseInt (-n, n)++-- | Arbitrary return type for the `Query` result.+data Result+  = I {-# UNPACK #-} !Int+  | M !(Maybe Int)+  | M2 !(Maybe (Int, Int))+  | Assocs [(Int, Int)]+  deriving (Show, Eq)++-- | containers. (referencial implementation)+handleRef :: VU.Vector Int -> Query -> Result+handleRef xs q = case q of+  Access i -> M $ xs VU.!? i+  KthSmallestIn (!l, !r) k -> M $ snd <$> ikthSmallestIn l r k+  IKthSmallestIn (!l, !r) k -> M2 $ ikthSmallestIn l r k+  KthLargestIn (!l, !r) k -> M $ snd <$> ikthLargestIn l r k+  IKthLargestIn (!l, !r) k -> M2 $ ikthLargestIn l r k+  UnsafeKthSmallestIn (!l, !r) k -> M $ snd <$> ikthSmallestIn l r k+  UnsafeIKthSmallestIn (!l, !r) k -> M2 $ ikthSmallestIn l r k+  UnsafeKthLargestIn (!l, !r) k -> M $ snd <$> ikthLargestIn l r k+  UnsafeIKthLargestIn (!l, !r) k -> M2 $ ikthLargestIn l r k+  RankLT (!l, !r) xr -> rankBetween l r (minBound `div` 2) xr+  RankBetween (!l, !r) (!xl, !xr) -> rankBetween l r xl xr+  Rank (!l, !r) x -> rankBetween l r x (x + 1)+  Select x -> M $ selectKthIn 0 n 0 x+  SelectKth k x -> M $ selectKthIn 0 n k x+  SelectKthIn (!l, !r) k x -> M $ selectKthIn l r k x+  LookupLE (!l, !r) x -> max_ . VU.filter (<= x) . VU.take (r - l) $ VU.drop l xs+  LookupLT (!l, !r) x -> max_ . VU.filter (< x) . VU.take (r - l) $ VU.drop l xs+  LookupGE (!l, !r) x -> min_ . VU.filter (>= x) . VU.take (r - l) $ VU.drop l xs+  LookupGT (!l, !r) x -> min_ . VU.filter (> x) . VU.take (r - l) $ VU.drop l xs+  AssocsIn (!l, !r) -> Assocs . IM.assocs . IM.fromListWith (+) . VU.toList . VU.map (,1) . VU.take (r - l) $ VU.drop l xs+  DescAssocsIn (!l, !r) -> Assocs . reverse . IM.assocs . IM.fromListWith (+) . VU.toList . VU.map (,1) . VU.take (r - l) $ VU.drop l xs+  where+    n = VU.length xs+    max_ ys+      | VU.null ys = M Nothing+      | otherwise = M $ Just $ VU.maximum ys+    min_ ys+      | VU.null ys = M Nothing+      | otherwise = M $ Just $ VU.minimum ys+    ikthSmallestIn l r k =+      (VU.!? k)+        . VU.modify (VAI.sortBy (comparing (\(!i, !x) -> (x, i))))+        . VU.take (r - l)+        . VU.drop l+        . VU.indexed+        $ xs+    ikthLargestIn l r k = ikthSmallestIn l r ((r - l) - (k + 1))+    rankBetween l r xl xr =+      I+        . VU.length+        . VU.filter (\x -> xl <= x && x < xr)+        . VU.take (r - l)+        . VU.drop l+        $ xs+    selectKthIn l r k x =+      (fst <$>)+        . (VU.!? k)+        . VU.filter ((== x) . snd)+        . VU.take (r - l)+        . VU.drop l+        . VU.indexed+        $ xs++handleAcl :: WM.RawWaveletMatrix -> Query -> Result+handleAcl wm q = case q of+  Access i -> M $ WM.access wm i+  KthSmallestIn (!l, !r) k -> M $ WM.kthSmallestIn wm l r k+  IKthSmallestIn (!l, !r) k -> M2 $ WM.ikthSmallestIn wm l r k+  KthLargestIn (!l, !r) k -> M $ WM.kthLargestIn wm l r k+  IKthLargestIn (!l, !r) k -> M2 $ WM.ikthLargestIn wm l r k+  UnsafeKthSmallestIn (!l, !r) k -> M $ WM.kthSmallestIn wm l r k+  UnsafeIKthSmallestIn (!l, !r) k -> M2 $ WM.ikthSmallestIn wm l r k+  UnsafeKthLargestIn (!l, !r) k -> M $ WM.kthLargestIn wm l r k+  UnsafeIKthLargestIn (!l, !r) k -> M2 $ WM.ikthLargestIn wm l r k+  RankLT (!l, !r) xr -> I $ WM.rankLT wm l r xr+  RankBetween (!l, !r) (!xl, !xr) -> I $ WM.rankBetween wm l r xl xr+  Rank (!l, !r) x -> I $ WM.rank wm l r x+  Select x -> M $ WM.select wm x+  SelectKth k x -> M $ WM.selectKth wm k x+  SelectKthIn (!l, !r) k x -> M $ WM.selectKthIn wm l r k x+  LookupLE (!l, !r) x -> M $ WM.lookupLE wm l r x+  LookupLT (!l, !r) x -> M $ WM.lookupLT wm l r x+  LookupGE (!l, !r) x -> M $ WM.lookupGE wm l r x+  LookupGT (!l, !r) x -> M $ WM.lookupGT wm l r x+  AssocsIn (!l, !r) -> Assocs $ WM.assocsIn wm l r+  DescAssocsIn (!l, !r) -> Assocs $ WM.descAssocsIn wm l r++prop_randomTest :: Init -> QC.Gen QC.Property+prop_randomTest Init {..} = do+  qs <- QC.vectorOf capacity (genQuery capacity)+  pure . QC.conjoin $+    map+      ( \q ->+          QC.counterexample (show q) $+            handleRef xs q QC.=== handleAcl wm q+      )+      qs++unit_boundary :: TestTree+unit_boundary = testCase "boundary" $ do+  let n = 5+  let wm = WM.build 3 $ VU.fromList [0, 1, 2, 1, 0]++  let try :: (HasCallStack, Eq a, Show a) => (WM.RawWaveletMatrix -> Int -> Int -> Int -> Maybe a) -> Int -> IO ()+      try f x = do+        (@?= Nothing) $ f wm (-1) 0 x+        (@?= Nothing) $ f wm n (n + 1) x++  let k = 0+  try WM.kthSmallestIn k+  try WM.ikthSmallestIn k+  try WM.kthLargestIn k+  try WM.ikthLargestIn k++-- try WM.unsafeKthSmallestIn+-- try WM.unsafeIKthSmallestIn+-- try WM.unsafeKthLargestIn+-- try WM.unsafeIKthLargestIn++  let tryRank :: (HasCallStack) => (WM.RawWaveletMatrix -> Int -> Int -> Int -> Int) -> Int -> IO ()+      tryRank f x = do+        -- out of range+        (@?= 0) $ f wm (-1) 0 x+        (@?= 0) $ f wm n (n + 1) x+        -- reverse+        (@?= 0) $ f wm 1 0 x+        (@?= 0) $ f wm n (n - 1) x+        (@?= 0) $ f wm n 0 x+        -- out of range and reverse+        (@?= 0) $ f wm 0 (-1) x+        (@?= 0) $ f wm (n + 1) n x++  let tryRankBetween :: (HasCallStack) => (WM.RawWaveletMatrix -> Int -> Int -> Int -> Int -> Int) -> Int -> Int -> IO ()+      tryRankBetween f xl xr = do+        -- out of range+        (@?= 0) $ f wm (-1) 0 xl xr+        (@?= 0) $ f wm n (n + 1) xl xr+        -- reverse+        (@?= 0) $ f wm 1 0 xl xr+        (@?= 0) $ f wm n (n - 1) xl xr+        (@?= 0) $ f wm n 0 xl xr+        -- out of range and reverse+        (@?= 0) $ f wm 0 (-1) xl xr+        (@?= 0) $ f wm (n + 1) n xl xr++  tryRank WM.rankLT 0+  tryRank WM.rankLT 1+  tryRank WM.rankLT (-1)+  tryRankBetween WM.rankBetween (-1) 1+  tryRank WM.rank 0+  tryRank WM.rank 1+  tryRank WM.rank (-1)++-- TODO: test ++-- (@?= Nothing) $ WM.select wm+-- (@?= Nothing) $ WM.selectKth wm+-- (@?= Nothing) $ WM.selectKthIn wm++-- (@?= Nothing) $ WM.lookupLE wm+-- (@?= Nothing) $ WM.lookupLT wm+-- (@?= Nothing) $ WM.lookupGE wm+-- (@?= Nothing) $ WM.lookupGT wm+-- (@?= Nothing) $ WM.assocsIn wm+-- (@?= Nothing) $ WM.descAssocsIn wm++spec_invalid :: IO TestTree+spec_invalid = testSpec "boundary check" $ do+  it "throws error 1" $ do+    evaluate (WM.build (-1) (VU.singleton 1)) `shouldThrow` anyException++tests :: [TestTree]+tests =+  [ unit_boundary,+    unsafePerformIO spec_invalid,+    QC.testProperty "random test" prop_randomTest+  ]
+ test/Tests/Extra/WaveletMatrix2d.hs view
@@ -0,0 +1,119 @@+{-# LANGUAGE RecordWildCards #-}++module Tests.Extra.WaveletMatrix2d (tests) where++import AtCoder.Extra.WaveletMatrix2d qualified as WM+import Control.Monad (foldM_)+import Control.Monad.Primitive (PrimMonad, PrimState)+import Control.Monad.ST (RealWorld)+import Data.List qualified as L+import Data.Map qualified as M+import Data.Maybe (fromMaybe)+import Data.Ord (comparing)+import Data.Semigroup (Sum (..))+import Data.Vector.Algorithms.Intro qualified as VAI+import Data.Vector.Unboxed qualified as VU+import Test.Hspec+import Test.QuickCheck.Monadic as QCM+import Test.Tasty+import Test.Tasty.HUnit+import Test.Tasty.QuickCheck as QC+import Tests.Util (intervalGen)++data Init = Init+  { capacity :: {-# UNPACK #-} !Int,+    map0 :: !(M.Map (Int, Int) (Sum Int)),+    wmM :: !(IO (WM.WaveletMatrix2d RealWorld (Sum Int)))+  }++instance Show Init where+  show Init {..} = show ("Init", capacity, map0)++instance QC.Arbitrary Init where+  arbitrary = do+    QC.NonNegative n <- QC.arbitrary+    let yxs = VU.fromList [(x, y) | x <- [-16 .. 16], y <- [-16 .. 16]]+    pure $ Init n M.empty (WM.new negate yxs)++data Query+  = Read !(Int, Int)+  | Write !(Int, Int) !Int+  | ModifyAdd !Int !(Int, Int)+  | Prod !(Int, Int) !(Int, Int)+  | ProdMaybe !(Int, Int) !(Int, Int)+  | AllProd+  deriving (Show)++genQuery :: Int -> QC.Gen Query+genQuery n = do+  QC.oneof+    [ Read <$> lr,+      Write <$> lr <*> val,+      ModifyAdd <$> val <*> lr,+      Prod <$> lr <*> lr,+      ProdMaybe <$> lr <*> lr,+      pure AllProd+    ]+  where+    lr = (\(!x, !y) -> (x - 16, y - 16)) <$> intervalGen 32+    val = QC.arbitrary @Int++-- | Arbitrary return type for the `Query` result.+data Result+  = None+  | S !(Sum Int)+  | MS !(Maybe (Sum Int))+  deriving (Show, Eq)++-- | containers. (referencial implementation)+handleRef :: M.Map (Int, Int) (Sum Int) -> Query -> (Result, M.Map (Int, Int) (Sum Int))+handleRef map q = case q of+  Read (!x, !y) -> (S . fromMaybe mempty $ M.lookup (x, y) map, map)+  Write (!x, !y) v -> (None, M.insert (x, y) (Sum v) map)+  ModifyAdd w (!x, !y) -> (None, M.insertWith (+) (x, y) (Sum w) map)+  Prod (!x1, !x2) (!y1, !y2) -> (S $ prod x1 x2 y1 y2, map)+  ProdMaybe (!x1, !x2) (!y1, !y2) -> (MS . Just $ prod x1 x2 y1 y2, map)+  AllProd -> (S $ L.foldl' (<>) mempty (M.elems map), map)+  where+    prod x1 x2 y1 y2 =+      L.foldl' (<>) (mempty :: Sum Int)+        . (snd <$>)+        . filter (\((!x, !y), !_) -> x1 <= x && x < x2 && y1 <= y && y < y2)+        $ M.assocs map++handleAcl :: (PrimMonad m) => WM.WaveletMatrix2d (PrimState m) (Sum Int) -> Query -> m Result+handleAcl wm q = case q of+  Read (!x, !y) -> do+    S <$> WM.read wm (x, y)+  Write (!x, !y) v -> do+    WM.write wm (x, y) $ Sum v+    pure None+  ModifyAdd w (!x, !y) -> do+    WM.modify wm (+ Sum w) (x, y)+    pure None+  Prod (!x1, !x2) (!y1, !y2) -> do+    S <$> WM.prod wm x1 x2 y1 y2+  ProdMaybe (!x1, !x2) (!y1, !y2) -> do+    MS <$> WM.prodMaybe wm x1 x2 y1 y2+  AllProd -> do+    S <$> WM.allProd wm++prop_randomTest :: Init -> QC.Property+prop_randomTest Init {..} = QCM.monadicIO $ do+  wm <- QCM.run wmM+  qs <- QCM.pick $ QC.vectorOf capacity (genQuery capacity)+  foldM_+    ( \map query -> do+        let (!expected, !map') = handleRef map query+        actual <- QCM.run $ handleAcl wm query+        QCM.assertWith (expected == actual) $ show (query, expected, actual)+        pure map'+    )+    map0+    qs++tests :: [TestTree]+tests =+  [ -- unit_boundary,+    QC.testProperty "random test" prop_randomTest+  ]
test/Tests/MaxFlow.hs view
@@ -2,7 +2,7 @@ module Tests.MaxFlow (tests) where  import AtCoder.MaxFlow qualified as MF-import Data.Bit (Bit(..))+import Data.Bit (Bit (..)) import Data.Vector.Unboxed qualified as VU import System.IO.Unsafe (unsafePerformIO) import Test.Hspec
test/Tests/Scc.hs view
@@ -1,5 +1,3 @@-{-# LANGUAGE RecordWildCards #-}- module Tests.Scc (tests) where  import AtCoder.Scc qualified as Scc
test/Tests/Util.hs view
@@ -1,4 +1,4 @@-module Tests.Util (myForAllShrink, laws) where+module Tests.Util (myForAllShrink, laws, intervalGen) where  import Data.Proxy (Proxy (..)) import Data.Typeable (Typeable, typeRep)@@ -40,3 +40,10 @@           let QCC.Laws name pairs = f (Proxy @a)            in testGroup name (map (uncurry QC.testProperty) pairs)       )++-- | Returns an interval [l, r) in [0, n)+intervalGen :: Int -> QC.Gen (Int, Int)+intervalGen n = do+  l <- QC.chooseInt (0, n)+  r <- QC.chooseInt (l, n)+  pure (l, r)