forked from c910335/2D-Rank-Finding-Problem
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmain.hs
61 lines (55 loc) · 1.6 KB
/
main.hs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE Strict, StrictData #-}
import Data.List
import Data.Maybe
import Data.Ord
import Data.Array.Unboxed
import Data.Array.ST
import Control.Monad
import Control.Monad.State.Lazy
import Control.Monad.ST
import qualified Data.ByteString.Char8 as B
data Point = Point { location :: (Int, Int)
, idx :: Int }
main = putStr . unlines . map (unwords . map show . sol) .
evalState getTestcases . B.words =<< B.getContents
where
getInt = fst . fromJust . B.readInt <$> state (\(x:xs) -> (x, xs))
getPoint i = do
x <- getInt
y <- getInt
return $ Point (x, y) i
getTestcase = do
n <- getInt
forM [1..n] getPoint
getTestcases =
getTestcase >>= \case
[] -> return []
tc -> (tc:) <$> getTestcases
sol :: [Point] -> [Int]
sol pts = elems $ runSTUArray $ do
ans <- newArray (1, length pts) 0
conquer (sortBy (comparing location) pts) ans
return ans
conquer :: [Point] -> STUArray s Int Int -> ST s [Point]
conquer [] _ = return []
conquer [p] _ = return [p]
conquer pts ans = do
l' <- conquer l ans
r' <- conquer r ans
merge l' r' 0 ans
where
(l, r) = splitAt (length pts `div` 2) pts
merge xs [] _ _ = return xs
merge [] ys acc ans = do
forM_ ys $ \p -> addRank ans (idx p) acc
return ys
merge (x:xs) (y:ys) acc ans
| (snd . location $ x) <= (snd . location $ y) =
(x:) <$> merge xs (y:ys) (acc+1) ans
| otherwise = do
addRank ans (idx y) acc
(y:) <$> merge (x:xs) ys acc ans
addRank arr idx val = do
newVal <- (val+) <$> readArray arr idx
writeArray arr idx newVal