{-# OPTIONS_GHC -O2 -funbox-strict-fields #-}
{-# LANGUAGE UnboxedTuples #-}
{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE ViewPatterns #-}
{-# LANGUAGE MagicHash #-}
{-# LANGUAGE TupleSections #-}
import Control.Applicative
import Control.Monad
import Data.Bits
import qualified Data.ByteString.Char8 as BS
import Data.Function
import Data.List
import qualified Data.Vector.Generic as G
import qualified Data.Vector.Unboxed as U
import qualified Data.Vector.Unboxed.Mutable as UM
import GHC.Exts (Int, MutableByteArray#, newByteArray#, readIntArray#, writeIntArray#, Int(..))
import GHC.ST (ST, ST(..))
main :: IO ()
main = do
n <- readLn
vec <- U.replicateM n $ do
[a, b] <- getInts
return (a, b)
print $ solve vec
solve :: U.Vector (Int, Int) -> Int
solve vec = negate $ U.minimum $ U.scanl (+) 0 $ U.map snd $ heapsort $ U.map (,-1) ins U.++ U.map (,1) outs
where
!(ins, outs) = U.unzip vec
----------------------------------------------------------------------------
-- IO
getInts :: IO [Int]
getInts = readInts <$> BS.getLine
readInts :: BS.ByteString -> [Int]
readInts s0 = unfoldr step s0
where
step (BS.dropWhile (==' ') -> s)
| s == "" = Nothing
| Just (v, r) <- BS.readInt s = Just (v, r)
| otherwise = error $ "not an integer: " ++ show s
----------------------------------------------------------------------------
-- MHeap
data MHeap s k a = MHeap
{ mhSize :: {-# UNPACK #-} !(MBA s)
, mhKeys :: !(UM.MVector s k)
, mhVals :: !(UM.MVector s a)
}
heapsort :: (UM.Unbox a, Ord a) => U.Vector a -> U.Vector a
heapsort = U.map fst . heapsortKV . U.map (,())
heapsortKV :: (UM.Unbox k, Ord k, UM.Unbox a) => U.Vector (k, a) -> U.Vector (k, a)
heapsortKV xs = U.create $ do
mv <- UM.new $ U.length xs
h <- newMH $ U.length xs
U.forM_ xs $ \(k, v) -> insertMH h k v
flip fix 0 $ \loop !i -> do
r <- deleteMH h
case r of
Nothing -> return ()
Just (k, v) -> do
UM.write mv i (k, v)
loop $! i + 1
return mv
deleteMH :: (UM.Unbox k, Ord k, UM.Unbox a) => MHeap s k a -> ST s (Maybe (k, a))
deleteMH MHeap{mhSize=szV, mhVals=vals, mhKeys=keys} = do
sz <- readIntMBA szV 0
let !sz' = sz - 1
if sz' < 0
then return Nothing
else do
outKey <- UM.unsafeRead keys 0
outVal <- UM.unsafeRead vals 0
writeIntMBA szV 0 sz'
key <- UM.unsafeRead keys sz'
val <- UM.unsafeRead vals sz'
loop sz' 0 key val
return $ Just (outKey, outVal)
where
loop !sz !pos !(forceU -> key) !(forceU -> val)
| lch >= sz = do
UM.unsafeWrite keys pos key
UM.unsafeWrite vals pos val
| otherwise = do
lkey <- UM.unsafeRead keys lch
(!ch, forceU -> !ckey, forceU -> !cval) <-
if rch >= sz
then do
lval <- UM.unsafeRead vals lch
return (lch, lkey, lval)
else do
rkey <- UM.unsafeRead keys rch
if lkey < rkey
then do
lval <- UM.unsafeRead vals lch
return (lch, lkey, lval)
else do
rval <- UM.unsafeRead vals rch
return (rch, rkey, rval)
if key < ckey
then do
UM.unsafeWrite keys pos key
UM.unsafeWrite vals pos val
else do
UM.unsafeWrite keys pos ckey
UM.unsafeWrite vals pos cval
loop sz ch key val
where
!lch = 2 * pos + 1
!rch = lch + 1
forceU :: (U.Unbox a) => a -> a
forceU x = G.elemseq (vec x) x x
where
vec :: a -> U.Vector a
vec = undefined
{-# INLINE forceU #-}
insertMH :: (UM.Unbox k, Ord k, UM.Unbox a) => MHeap s k a -> k -> a -> ST s ()
insertMH MHeap{mhSize=szV, mhVals=vals, mhKeys=keys} !key !val = do
sz <- readIntMBA szV 0
let !sz' = sz + 1
--trace ("insert: sz'=" ++ show sz') $ return ()
when (sz' > UM.length vals) $ overflowErrorMH $! UM.length vals
writeIntMBA szV 0 sz'
loop sz
where
loop 0 = do
UM.unsafeWrite keys 0 key
UM.unsafeWrite vals 0 val
loop pos = do
parent <- UM.unsafeRead keys pos'
if parent <= key
then do
UM.unsafeWrite keys pos key
UM.unsafeWrite vals pos val
else do
UM.unsafeWrite keys pos parent
UM.unsafeWrite vals pos =<< UM.unsafeRead vals pos'
loop pos'
where
!pos' = (pos - 1) `shiftR` 1
overflowErrorMH :: Int -> ST s ()
overflowErrorMH s = fail $ "insertMH: overflow (cap=" ++ show s ++ ")"
{-# NOINLINE overflowErrorMH #-}
newMH :: (UM.Unbox k, UM.Unbox a) => Int -> ST s (MHeap s k a)
newMH cap = MHeap
<$> do
r <- newMBA 8
writeIntMBA r 0 0
return r
<*> UM.new cap
<*> UM.new cap
----------------------------------------------------------------------------
-- MBA
data MBA s = MBA (MutableByteArray# s)
readIntMBA :: MBA s -> Int -> ST s Int
readIntMBA (MBA mba) (I# ofs) = ST $ \s -> let
!(# s1, val #) = readIntArray# mba ofs s
in (# s1, I# val #)
{-# INLINE readIntMBA #-}
writeIntMBA :: MBA s -> Int -> Int -> ST s ()
writeIntMBA (MBA mba) (I# ofs) (I# val) = ST $ \s -> let
!s1 = writeIntArray# mba ofs val s
in (# s1, () #)
{-# INLINE writeIntMBA #-}
newMBA :: Int -> ST s (MBA s)
newMBA (I# bytes) = ST $ \s -> let
!(# s1, mba #) = newByteArray# bytes s
in (# s1, MBA mba #)