Problem:
Score : 100 points

Problem Statement

You are given a grid of N rows and M columns. The square at the i-th row and j-th column will be denoted as (i,j).
A nonnegative integer A_{i,j} is written for each square (i,j).

You choose some of the squares so that each row and column contains at most K chosen squares.
Under this constraint, calculate the maximum value of the sum of the integers written on the chosen squares.
Additionally, calculate a way to choose squares that acheives the maximum.

Constraints

1 \leq N \leq 50

1 \leq K \leq N

0 \leq A_{i,j} \leq 10^9

All values in Input are integer.

Input

Input is given from Standard Input in the following format:

N K
A_{1,1} A_{1,2} \cdots A_{1,N}
A_{2,1} A_{2,2} \cdots A_{2,N}
\vdots
A_{N,1} A_{N,2} \cdots A_{N,N}

Output

On the first line, print the maximum value of the sum of the integers written on the chosen squares.

On the next N lines, print a way that achieves the maximum.

Precisely, output the strings t_1,t_2,\cdots,t_N, that satisfies t_{i,j}=X if you choose (i,j) and t_{i,j}=. otherwise.

You may print any way to choose squares that maximizes the sum.

Sample Input 1

3 1
5 3 2
1 4 8
7 6 9

Sample Output 1

19
X..
..X
.X.

Sample Input 2

3 2
10 10 1
10 10 1
1 1 10

Sample Output 2

50
XX.
XX.
..X

Solution in Haskell (GHC 8.8.3) (judge verdict: Accepted)

{-# OPTIONS_GHC -O2 #-}
{-# LANGUAGE BangPatterns, BinaryLiterals, CPP, DerivingStrategies  #-}
{-# LANGUAGE DerivingVia, FlexibleContexts, FlexibleInstances       #-}
{-# LANGUAGE GeneralizedNewtypeDeriving, KindSignatures, LambdaCase #-}
{-# LANGUAGE MagicHash, MultiParamTypeClasses, MultiWayIf           #-}
{-# LANGUAGE NumericUnderscores, OverloadedStrings, PatternSynonyms #-}
{-# LANGUAGE RankNTypes, RecordWildCards, ScopedTypeVariables       #-}
{-# LANGUAGE StandaloneDeriving, TupleSections, TypeApplications    #-}
{-# LANGUAGE TypeFamilies, TypeInType, UnboxedTuples, ViewPatterns  #-}

import           Control.Applicative
import           Control.Exception
import           Control.Monad
import           Control.Monad.Primitive
import           Control.Monad.Reader
import           Control.Monad.ST
import           Control.Monad.State.Strict
import           Data.Bifunctor
import           Data.Bool
import qualified Data.ByteString                   as B
import qualified Data.ByteString.Builder           as B
import qualified Data.ByteString.Char8             as C
import qualified Data.ByteString.Internal          as B
import qualified Data.ByteString.Unsafe            as B
import           Data.Char
import qualified Data.Foldable                     as F
import           Data.Function
import           Data.Functor.Identity
import qualified Data.IntMap.Strict                as IM
import qualified Data.IntSet                       as IS
import qualified Data.List                         as L
import qualified Data.Map.Strict                   as M
import           Data.Monoid
import           Data.Ord
import           Data.Primitive
import           Data.Proxy
import           Data.Ratio
import           Data.Semigroup
import qualified Data.Set                          as S
import           Data.Tuple
import qualified Data.Vector                       as V
import qualified Data.Vector.Algorithms.Intro      as Intro
import qualified Data.Vector.Fusion.Stream.Monadic as MS
import qualified Data.Vector.Fusion.Bundle.Monadic as MB
import           Data.Vector.Fusion.Util
import qualified Data.Vector.Generic               as G
import qualified Data.Vector.Generic.Mutable       as GM
import qualified Data.Vector.Mutable               as VM
import qualified Data.Vector.Primitive             as P
import qualified Data.Vector.Primitive.Mutable     as PM
import qualified Data.Vector.Unboxed               as U
import qualified Data.Vector.Unboxed.Mutable       as UM
import           Debug.Trace
import           Foreign                           hiding (void)
import           GHC.Exts
import           GHC.TypeLits
import           System.IO
import           Unsafe.Coerce

#define MOD 1000000007

main :: IO ()
main = do
    [n, k] <- map read.words <$> getLine
    xs <- U.unfoldrN (n * n) (runParser int) <$> C.getContents
    case solve n k xs of
        (c, mat) -> do
            print c
            forM_ [0..n-1] $ \i -> do
                putStrLn . U.toList $ U.slice (i * n) n mat


solve :: Int -> Int -> U.Vector Int -> (Int, U.Vector Char)
solve n k xs = first fst $ solve' n k xs cap
  where
    ((_,cap),_) = solve' n k xs $ n * n

solve' :: Int -> Int -> U.Vector Int -> Int -> ((Int, Int), U.Vector Char)
solve' n k xs flow = runST $ do
    builder <- newMinCostFlowBuilder (2 * n + 2)
    rep n $ \i -> do
        addEdgeMCFB builder source (row i) 0 k
    rep n $ \i -> do
        rep n $ \j -> do
            addEdgeMCFB builder (row i) (col j) (cost i j) 1
    rep n $ \j -> do
        addEdgeMCFB builder (col j) sink 0 k
    mcf <- buildMinCostFlow builder
    cc <- maximum .map (\(c, cap) -> (cap * lim - c, cap))
        <$> runMinCostFlow source sink flow mcf
    mat <- UM.replicate (n * n) '.'
    rep n $ \j -> do
        let v = col j
        let start = U.unsafeIndex (offsetMCF mcf) v
        let end   = U.unsafeIndex (offsetMCF mcf) (v + 1)
        flip MS.mapM_ (stream start end) $ \e -> do
            let nv = U.unsafeIndex (dstMCF mcf) e
            when (isRow nv) $ do
                residual <- UM.unsafeRead (residualMCF mcf) e
                when (residual > 0) $ do
                    UM.write mat (nv * n + j) 'X'
    (,) cc <$> U.freeze mat
  where
    isRow = (< n)
    row i = i
    col j = j + n
    source = 2 * n
    sink = 2 * n + 1
    cost i j = lim - xs U.! (i * n + j)

lim :: Int
lim = 1000000000

nothingMCF :: Int
nothingMCF = -1

type Vertex = Int
type Cost = Int
type Capacity = Int

data MinCostFlow s = MinCostFlow
    { numVerticesMCF :: !Int
    , numEdgesMCF    :: !Int
    , offsetMCF      :: U.Vector Int
    , dstMCF         :: U.Vector Vertex
    , costMCF        :: U.Vector Cost
    , residualMCF    :: UM.MVector s Capacity
    , potentialMCF   :: UM.MVector s Cost
    , distMCF        :: UM.MVector s Cost
    , heapMCF        :: MinBinaryHeap s Word64 -- (Cost, Vertex)
    , revEdgeMCF     :: U.Vector Int
    , prevVertexMCF  :: UM.MVector s Vertex
    , prevEdgeMCF    :: UM.MVector s Int
    }

runMinCostFlow :: (PrimMonad m)
    => Vertex -> Vertex -> Capacity -> MinCostFlow (PrimState m) -> m [(Cost, Capacity)]
runMinCostFlow source sink flow mcf@MinCostFlow{..} = go [(0, 0)] 0 flow
  where
    go !res !c !f
        | f == 0 = return $ reverse $ (c, flow):res
        | otherwise = do
            canFlow <- dijkstraMCF source sink mcf
            if canFlow
            then do
                rep numVerticesMCF $ \v -> do
                    dv <- UM.unsafeRead distMCF v
                    UM.unsafeModify potentialMCF (+dv) v
                flowed <- updateResidualMCF sink f mcf
                hsink <- UM.unsafeRead potentialMCF sink
                let !c' = hsink * flowed + c
                    !f' = f - flowed
                go ((c', flow - f'):res) c' f'
            else return $ reverse $ (c, flow - f):res


encodeMCF :: Cost -> Vertex -> Word64
encodeMCF cost v = unsafeCoerce $ unsafeShiftL cost 8 .|. v
{-# INLINE encodeMCF #-}

decodeMCF :: Word64 -> (Cost, Vertex)
decodeMCF costv = unsafeCoerce (cost, v)
  where
    !cost = unsafeShiftR costv 8
    !v = costv .&. 0xff
{-# INLINE decodeMCF #-}

dijkstraMCF :: (PrimMonad m)
    => Vertex -> Vertex -> MinCostFlow (PrimState m) -> m Bool
dijkstraMCF source sink MinCostFlow{..} = do
    UM.set distMCF maxBound
    UM.unsafeWrite distMCF source 0
    clearBH heapMCF
    insertBH (encodeMCF 0 source) heapMCF

    fix $ \loop -> do
        deleteFindTopBH heapMCF >>= \case
            Just cv -> do
                let (c, v) = decodeMCF cv
                dv <- UM.unsafeRead distMCF v
                unless (c > dv) $ do
                    let start = U.unsafeIndex offsetMCF v
                    let end   = U.unsafeIndex offsetMCF (v + 1)
                    U.forM_ (U.generate (end - start) (+start)) $ \e -> do
                        let nv = U.unsafeIndex dstMCF e
                        let v2nv = U.unsafeIndex costMCF e
                        cap  <- UM.unsafeRead residualMCF e
                        hv   <- UM.unsafeRead potentialMCF v
                        hnv  <- UM.unsafeRead potentialMCF nv
                        old  <- UM.unsafeRead distMCF nv
                        let dnv = dv + v2nv + hv - hnv
                        when (cap > 0 && dnv < old) $ do
                            UM.unsafeWrite distMCF nv dnv
                            UM.unsafeWrite prevVertexMCF nv v
                            UM.unsafeWrite prevEdgeMCF nv e
                            insertBH (encodeMCF dnv nv) heapMCF
                loop
            Nothing -> do
                cost <- UM.unsafeRead distMCF sink
                return $! cost < maxBound
{-# INLINE dijkstraMCF #-}

updateResidualMCF :: (PrimMonad m)
    => Vertex -> Capacity -> MinCostFlow (PrimState m) -> m Capacity
updateResidualMCF sink flow MinCostFlow{..} = go sink flow return
  where
    go !v !f k = do
        pv <- UM.unsafeRead prevVertexMCF v
        if pv < 0
        then k f
        else do
            pv2v <- UM.unsafeRead prevEdgeMCF v
            f' <- UM.unsafeRead residualMCF pv2v
            go pv (min f f') $ \nf -> do
                UM.unsafeModify residualMCF (subtract nf) pv2v
                UM.unsafeModify residualMCF (+nf) (U.unsafeIndex revEdgeMCF pv2v)
                k nf
{-# INLINE updateResidualMCF #-}


data MinCostFlowBuilder s = MinCostFlowBuilder
    { numVerticesMCFB :: !Int
    , inDegreeMCFB    :: UM.MVector s Int
    , edgesMCFB       :: VecQueue s (Vertex, Vertex, Cost, Capacity)
    }

newMinCostFlowBuilder :: (PrimMonad m)
    => Int -> m (MinCostFlowBuilder (PrimState m))
newMinCostFlowBuilder n = MinCostFlowBuilder n
    <$> UM.replicate n 0
    <*> newVecQueue (1024 * 1024)

addEdgeMCFB :: (PrimMonad m)
    => MinCostFlowBuilder (PrimState m)
    -> Vertex -> Vertex -> Cost -> Capacity -> m ()
addEdgeMCFB MinCostFlowBuilder{..} src dst cost capacity
    = assert (cost >= 0) $ do
        UM.unsafeModify inDegreeMCFB (+1) src
        UM.unsafeModify inDegreeMCFB (+1) dst
        enqueueVQ (src, dst, cost, capacity) edgesMCFB

buildMinCostFlow :: (PrimMonad m)
    => MinCostFlowBuilder (PrimState m) -> m (MinCostFlow (PrimState m))
buildMinCostFlow MinCostFlowBuilder{..} = do
    offsetMCF <- U.scanl' (+) 0 <$> U.unsafeFreeze inDegreeMCFB
    let numVerticesMCF = numVerticesMCFB
    let numEdgesMCF = U.last offsetMCF

    moffset <- U.thaw offsetMCF
    mdstMCF <- UM.replicate numEdgesMCF nothingMCF
    mcostMCF <- UM.replicate numEdgesMCF 0
    mrevEdgeMCF <- UM.replicate numEdgesMCF nothingMCF
    residualMCF <- UM.replicate numEdgesMCF 0

    edges <- freezeVecQueue edgesMCFB
    U.forM_ edges $ \(src, dst, cost, capacity) -> do
        srcOffset <- UM.unsafeRead moffset src
        dstOffset <- UM.unsafeRead moffset dst
        UM.unsafeModify moffset (+1) src
        UM.unsafeModify moffset (+1) dst

        UM.unsafeWrite mdstMCF srcOffset dst
        UM.unsafeWrite mdstMCF dstOffset src
        UM.unsafeWrite mcostMCF srcOffset cost
        UM.unsafeWrite mcostMCF dstOffset (-cost)
        UM.unsafeWrite mrevEdgeMCF srcOffset dstOffset
        UM.unsafeWrite mrevEdgeMCF dstOffset srcOffset
        UM.unsafeWrite residualMCF srcOffset capacity

    dstMCF <- U.unsafeFreeze mdstMCF
    costMCF <- U.unsafeFreeze mcostMCF
    potentialMCF <- UM.replicate numVerticesMCF 0
    distMCF <- UM.replicate numVerticesMCF 0
    heapMCF <- newMinBinaryHeap numEdgesMCF
    revEdgeMCF <- U.unsafeFreeze mrevEdgeMCF
    prevVertexMCF <- UM.replicate numVerticesMCF nothingMCF
    prevEdgeMCF <- UM.replicate numVerticesMCF nothingMCF
    return MinCostFlow{..}


-------------------------------------------------------------------------------
-- Utils
-------------------------------------------------------------------------------
rep :: (Monad m) => Int -> (Int -> m ()) -> m ()
rep n = flip MS.mapM_ (stream 0 n)
{-# INLINE rep #-}
rev :: (Monad m) => Int -> (Int -> m ()) -> m ()
rev !n = flip MS.mapM_ (streamR 0 n)
{-# INLINE rev #-}
stream :: (Monad m) => Int -> Int -> MS.Stream m Int
stream !l !r = MS.Stream step l where { step x | x < r = return $ MS.Yield x (x + 1) | otherwise = return MS.Done; {-# INLINE [0] step #-}}
{-# INLINE [1] stream #-}
streamR :: (Monad m) => Int -> Int -> MS.Stream m Int
streamR !l !r = MS.Stream step (r - 1) where { step x | x >= l = return $ MS.Yield x (x - 1) | otherwise = return MS.Done; {-# INLINE [0] step #-}}
{-# INLINE [1] streamR #-}
stream' :: (Monad m) => Int -> Int -> Int -> MS.Stream m Int
stream' !l !r !d = MS.Stream step l where { step x | x < r = return $ MS.Yield x (x + d) | otherwise = return MS.Done; {-# INLINE [0] step #-}}
{-# INLINE [1] stream' #-}
infixl 8 `shiftRL`, `unsafeShiftRL`
shiftRL :: Int -> Int -> Int
shiftRL = unsafeShiftRL
{-# INLINE shiftRL #-}
unsafeShiftRL :: Int -> Int -> Int
unsafeShiftRL (I# x#) (I# i#) = I# (uncheckedIShiftRL# x# i#)
{-# INLINE unsafeShiftRL #-}
type Parser a = StateT C.ByteString Maybe a
runParser :: Parser a -> C.ByteString -> Maybe (a, C.ByteString)
runParser = runStateT
{-# INLINE runParser #-}
int :: Parser Int
int = coerce $ C.readInt . C.dropWhile isSpace
{-# INLINE int #-}
int1 :: Parser Int
int1 = fmap (subtract 1) int
{-# INLINE int1 #-}
char :: Parser Char
char = coerce C.uncons
{-# INLINE char #-}
byte :: Parser Word8
byte = coerce B.uncons
{-# INLINE byte #-}
skipSpaces :: Parser ()
skipSpaces = modify' (C.dropWhile isSpace)
{-# INLINE skipSpaces #-}
lowerBoundM :: (Monad m) => Int -> Int -> (Int -> m Bool) -> m Int
lowerBoundM low high p = go low high where { go !low !high | high <= low = return high | otherwise = p mid >>= bool (go (mid + 1) high) (go low mid) where { mid = low + unsafeShiftRL (high - low) 1}}
{-# INLINE lowerBoundM #-}
upperBoundM :: (Monad m) => Int -> Int -> (Int -> m Bool) -> m Int
upperBoundM low high p = do { flg <- p high; if flg then return high else subtract 1 <$!> lowerBoundM low high (fmap not . p)}
{-# INLINE upperBoundM #-}
lowerBound :: Int -> Int -> (Int -> Bool) -> Int
lowerBound low high p = runIdentity (lowerBoundM low high (return . p))
{-# INLINE lowerBound #-}
upperBound :: Int -> Int -> (Int -> Bool) -> Int
upperBound low high p = runIdentity (upperBoundM low high (return . p))
{-# INLINE upperBound #-}
-------------------------------------------------------------------------------
-- Data.VecQueue
-------------------------------------------------------------------------------
data VecQueue s a = VecQueue{intVarsVQ :: !(UM.MVector s Int), internalVecQueue :: !(UM.MVector s a)}
_dequeueCount :: Int
_dequeueCount = 0
{-# INLINE _dequeueCount #-}
_enqueueCount :: Int
_enqueueCount = 1
{-# INLINE _enqueueCount #-}
newVecQueue :: (PrimMonad m, UM.Unbox a) => Int -> m (VecQueue (PrimState m) a)
newVecQueue n = VecQueue <$> UM.replicate 2 0 <*> UM.unsafeNew n
defaultVecQueueSize :: Int
defaultVecQueueSize = 1024 * 1024
lengthVQ :: (PrimMonad m, UM.Unbox a) => VecQueue (PrimState m) a -> m Int
lengthVQ (VecQueue info _) = (-) <$> UM.unsafeRead info _enqueueCount <*> UM.unsafeRead info _dequeueCount
{-# INLINE lengthVQ #-}
dequeueVQ :: (PrimMonad m, UM.Unbox a) => VecQueue (PrimState m) a -> m (Maybe a)
dequeueVQ (VecQueue info q) = do { f <- UM.unsafeRead info _dequeueCount; r <- UM.unsafeRead info _enqueueCount; if f < r then do { UM.unsafeWrite info _dequeueCount (f + 1); pure <$> UM.unsafeRead q f} else return Nothing}
{-# INLINE dequeueVQ #-}
enqueueVQ :: (PrimMonad m, UM.Unbox a) => a -> VecQueue (PrimState m) a -> m ()
enqueueVQ x (VecQueue info q) = do { r <- UM.unsafeRead info _enqueueCount; UM.unsafeWrite q r x; UM.unsafeWrite info _enqueueCount (r + 1)}
{-# INLINE enqueueVQ #-}
enqueuesVQ :: (PrimMonad m, UM.Unbox a) => U.Vector a -> VecQueue (PrimState m) a -> m ()
enqueuesVQ vec (VecQueue info q) = do { r <- UM.unsafeRead info _enqueueCount; UM.unsafeWrite info _enqueueCount (r + U.length vec); U.unsafeCopy (UM.unsafeSlice r (U.length vec) q) vec}
{-# INLINE enqueuesVQ #-}
clearVQ :: (UM.Unbox a, PrimMonad m) => VecQueue (PrimState m) a -> m ()
clearVQ (VecQueue info _) = do { UM.unsafeWrite info _dequeueCount 0; UM.unsafeWrite info _enqueueCount 0}
freezeVecQueue :: (PrimMonad m, UM.Unbox a) => VecQueue (PrimState m) a -> m (U.Vector a)
freezeVecQueue (VecQueue info q) = do { f <- UM.unsafeRead info _dequeueCount; r <- UM.unsafeRead info _enqueueCount; U.unsafeFreeze $ UM.unsafeSlice f (r - f) q}
-------------------------------------------------------------------------------
-- Data.Heap.Binary
-------------------------------------------------------------------------------
data BinaryHeap (f :: * -> *) s a = BinaryHeap{priorityBH :: a -> f a, intVarsBH :: !(UM.MVector s Int), internalVecBH :: !(UM.MVector s a)}
_sizeBH :: Int
_sizeBH = 0
{-# INLINE _sizeBH #-}
type MinBinaryHeap s a = BinaryHeap Identity s a
type MaxBinaryHeap s a = BinaryHeap Down s a
newBinaryHeap :: (U.Unbox a, PrimMonad m) => (a -> f a) -> Int -> m (BinaryHeap f (PrimState m) a)
newBinaryHeap prio n = BinaryHeap prio <$> UM.replicate 1 0 <*> UM.unsafeNew n
newMinBinaryHeap :: (U.Unbox a, PrimMonad m) => Int -> m (MinBinaryHeap (PrimState m) a)
newMinBinaryHeap = newBinaryHeap Identity
newMaxBinaryHeap :: (U.Unbox a, PrimMonad m) => Int -> m (MaxBinaryHeap (PrimState m) a)
newMaxBinaryHeap = newBinaryHeap Down
getBinaryHeapSize :: (PrimMonad m) => BinaryHeap f (PrimState m) a -> m Int
getBinaryHeapSize BinaryHeap{..} = UM.unsafeRead intVarsBH _sizeBH
{-# INLINE getBinaryHeapSize #-}
siftUpBy :: (U.Unbox a, PrimMonad m) => (a -> a -> Ordering) -> Int -> UM.MVector (PrimState m) a -> m ()
siftUpBy cmp k vec = do { x <- UM.unsafeRead vec k; flip fix k $ \ loop !i -> if i > 0 then do { let { parent = (i - 1) `unsafeShiftR` 1}; p <- UM.unsafeRead vec parent; case cmp p x of { GT -> UM.unsafeWrite vec i p >> loop parent; _ -> UM.unsafeWrite vec i x}} else UM.unsafeWrite vec 0 x}
{-# INLINE siftUpBy #-}
siftDownBy :: (U.Unbox a, PrimMonad m) => (a -> a -> Ordering) -> Int -> UM.MVector (PrimState m) a -> m ()
siftDownBy cmp k vec = do { x <- UM.unsafeRead vec k; let { !n = UM.length vec}; flip fix k $ \ loop !i -> do { let { l = unsafeShiftL i 1 .|. 1}; let { r = l + 1}; if n <= l then UM.unsafeWrite vec i x else do { vl <- UM.unsafeRead vec l; if r < n then do { vr <- UM.unsafeRead vec r; case cmp vr vl of { LT -> case cmp x vr of { GT -> UM.unsafeWrite vec i vr >> loop r; _ -> UM.unsafeWrite vec i x}; _ -> case cmp x vl of { GT -> UM.unsafeWrite vec i vl >> loop l; _ -> UM.unsafeWrite vec i x}}} else case cmp x vl of { GT -> UM.unsafeWrite vec i vl >> loop l; _ -> UM.unsafeWrite vec i x}}}}
{-# INLINE siftDownBy #-}
heapifyBy :: (U.Unbox a, PrimMonad m) => (a -> a -> Ordering) -> UM.MVector (PrimState m) a -> m ()
heapifyBy cmp vec = do { rev (UM.length vec `quot` 2) $ \ i -> do { siftDownBy cmp i vec}}
{-# INLINE heapifyBy #-}
class OrdVia f a where { compareVia :: (a -> f a) -> a -> a -> Ordering}
instance (Ord a) => OrdVia Identity a where { compareVia _ = coerce (compare :: Identity a -> Identity a -> Ordering); {-# INLINE compareVia #-}}
instance (Ord a) => OrdVia Down a where { compareVia _ = coerce (compare :: Down a -> Down a -> Ordering); {-# INLINE compareVia #-}}
buildBinaryHeapVia :: (OrdVia f a, U.Unbox a, PrimMonad m) => (a -> f a) -> U.Vector a -> m (BinaryHeap f (PrimState m) a)
buildBinaryHeapVia ~priorityBH vec = do { intVarsBH <- UM.replicate 1 $ U.length vec; internalVecBH <- U.thaw vec; heapifyBy (compareVia priorityBH) internalVecBH; return $! BinaryHeap{..}}
{-# INLINE buildBinaryHeapVia #-}
buildMinBinaryHeap :: (Ord a, U.Unbox a, PrimMonad m) => U.Vector a -> m (BinaryHeap Identity (PrimState m) a)
buildMinBinaryHeap = buildBinaryHeapVia Identity
{-# INLINE buildMinBinaryHeap #-}
buildMaxBinaryHeap :: (Ord a, U.Unbox a, PrimMonad m) => U.Vector a -> m (BinaryHeap Down (PrimState m) a)
buildMaxBinaryHeap = buildBinaryHeapVia Down
{-# INLINE buildMaxBinaryHeap #-}
unsafeViewBH :: (U.Unbox a, PrimMonad m) => BinaryHeap f (PrimState m) a -> m a
unsafeViewBH BinaryHeap{..} = UM.unsafeRead internalVecBH 0
{-# INLINE unsafeViewBH #-}
viewBH :: (U.Unbox a, PrimMonad m) => BinaryHeap f (PrimState m) a -> m (Maybe a)
viewBH bh = do { size <- getBinaryHeapSize bh; if size > 0 then Just <$!> unsafeViewBH bh else return $! Nothing}
{-# INLINE viewBH #-}
insertBH :: (OrdVia f a, U.Unbox a, PrimMonad m) => a -> BinaryHeap f (PrimState m) a -> m ()
insertBH x BinaryHeap{..} = do { size <- UM.unsafeRead intVarsBH _sizeBH; UM.unsafeWrite intVarsBH _sizeBH (size + 1); UM.unsafeWrite internalVecBH size x; siftUpBy (compareVia priorityBH) size internalVecBH}
{-# INLINE insertBH #-}
unsafeDeleteBH :: (OrdVia f a, U.Unbox a, PrimMonad m) => BinaryHeap f (PrimState m) a -> m ()
unsafeDeleteBH BinaryHeap{..} = do { size' <- subtract 1 <$!> UM.unsafeRead intVarsBH _sizeBH; UM.unsafeWrite intVarsBH _sizeBH size'; UM.unsafeSwap internalVecBH 0 size'; siftDownBy (compareVia priorityBH) 0 (UM.unsafeTake size' internalVecBH)}
{-# INLINE unsafeDeleteBH #-}
modifyTopBH :: (OrdVia f a, U.Unbox a, PrimMonad m) => (a -> a) -> BinaryHeap f (PrimState m) a -> m ()
modifyTopBH f BinaryHeap{..} = do { UM.unsafeModify internalVecBH f 0; size <- UM.unsafeRead intVarsBH _sizeBH; siftDownBy (compareVia priorityBH) 0 (UM.unsafeTake size internalVecBH)}
{-# INLINE modifyTopBH #-}
deleteFindTopBH :: (Ord a, U.Unbox a, PrimMonad m) => MinBinaryHeap (PrimState m) a -> m (Maybe a)
deleteFindTopBH bh = do { size <- getBinaryHeapSize bh; if size > 0 then do { !top <- unsafeViewBH bh <* unsafeDeleteBH bh; return $ Just top} else return Nothing}
{-# INLINE deleteFindTopBH #-}
clearBH :: (PrimMonad m) => BinaryHeap f (PrimState m) a -> m ()
clearBH BinaryHeap{..} = UM.unsafeWrite intVarsBH 0 0
freezeInternalVecBH :: (U.Unbox a, PrimMonad m) => BinaryHeap f (PrimState m) a -> m (U.Vector a)
freezeInternalVecBH BinaryHeap{..} = do { size <- UM.unsafeRead intVarsBH _sizeBH; U.unsafeFreeze (UM.unsafeTake size internalVecBH)}