RT,这里是提交记录,84分,T四个点,想问问 Haskell 有什么卡常数的方法吗QAQ
代码如下
import qualified Data.Map.Strict as Map
data Info = Info Int Int
deriving (Show, Read, Eq)
data Tree a = Null | Node a (Tree a) (Tree a) Info
deriving (Show, Read, Eq)
height :: Tree a -> Int
height Null = 0
height (Node _ _ _ (Info h _)) = h
size :: Tree a -> Int
size Null = 0
size (Node _ _ _ (Info _ s)) = s
pushUp :: a -> Tree a -> Tree a -> Tree a
-- build a new tree with given subtrees and key.
pushUp x left right = let h = max (height left) (height right) + 1
s = (size left) + (size right) + 1
in Node x left right (Info h s)
balanceFromLeft :: Tree a -> Tree a
-- left subtree might be empty.
balanceFromLeft input@(Node _ Null _ _) = input
balanceFromLeft input@(Node x xleft@(Node y yleft yright _) xright _) =
if ((height xleft) >= (height xright) + 2) then
pushUp y yleft (pushUp x yright xright)
else
input
balanceFromRight :: Tree a -> Tree a
-- right subtree might be empty.
balanceFromRight input@(Node _ _ Null _) = input
balanceFromRight input@(Node x xleft xright@(Node y yleft yright _) _) =
if ((height xright) >= (height xleft) + 2) then
pushUp y (pushUp x xleft yleft) yright
else
input
insert :: (Ord a) => a -> Tree a -> Tree a
-- result nonempty.
insert x Null = Node x Null Null (Info 1 1)
insert x (Node y left right _)
| x <= y = let cur = insert x left in
balanceFromLeft $ pushUp y cur right
| x > y = let cur = insert x right in
balanceFromRight $ pushUp y left cur
deleteLargest :: (Ord a) => Tree a -> (Tree a, a)
-- input nonempty.
deleteLargest (Node y left Null _) = (left, y)
deleteLargest (Node y left right _) =
let (cur, z) = deleteLargest right
in (balanceFromLeft $ pushUp y left cur, z)
delete :: (Ord a) => a -> Tree a -> Tree a
-- if does not exist, do nothing.
delete _ Null = Null
delete x (Node y left right _)
| x < y = let cur = delete x left
in balanceFromRight $ pushUp y cur right
| x > y = let cur = delete x right
in balanceFromLeft $ pushUp y left cur
| x == y =
if (left == Null) then
right
else if (right == Null) then
left
else
let (cur, z) = deleteLargest left
in balanceFromRight $ pushUp z cur right
getRank :: (Ord a) => a -> Tree a -> Int
getRank _ Null = 1
getRank x (Node y left right _) =
if (x <= y) then
getRank x left
else
getRank x right + (size left) + 1
getValue :: (Ord a) => Int -> Tree a -> a
-- input in [1, treesize].
-- getValue _ (Node y Null Null _) = y
getValue n cur@(Node y left right _)
| n == sleft + 1 = y
| n <= sleft = getValue n left
| otherwise = getValue (n - sleft - 1) right
where sleft = size left
fromMaybeDefault :: Maybe a -> a -> a
fromMaybeDefault Nothing = id
fromMaybeDefault (Just y) = (\_ -> y)
getPred :: (Ord a) => a -> Tree a -> Maybe a
getPred _ Null = Nothing
getPred x (Node y left right _)
| x <= y = getPred x left
| x > y = Just $ fromMaybeDefault (getPred x right) y
getSucc :: (Ord a) => a -> Tree a -> Maybe a
getSucc _ Null = Nothing
getSucc x (Node y left right _)
| x >= y = getSucc x right
| x < y = Just $ fromMaybeDefault (getSucc x left) y
runCommands :: [Int] -> Map.Map Int (Tree Int) -> String
runCommands [] _ = []
runCommands (v:opt:x:restCmd) prevList
| opt <= 2 =
let curList =
if opt == 1 then Map.insert curStep (insert x curTree) prevList
else Map.insert curStep (delete x curTree) prevList
in runCommands restCmd curList
| opt >= 3 && opt <= 4 =
let curList = Map.insert curStep curTree prevList
ans =
if opt == 3 then getRank x curTree
else getValue x curTree
in (show ans) ++ "\n" ++ (runCommands restCmd curList)
| opt >= 5 && opt <= 6 =
let curList = Map.insert curStep curTree prevList
ansRaw =
if opt == 5 then getPred x curTree
else getSucc x curTree
defaultValue =
if opt == 5 then (1-2^31)
else (-1+2^31)
ans =
fromMaybeDefault ansRaw defaultValue
in (show ans) ++ "\n" ++ (runCommands restCmd curList)
where curStep = Map.size prevList
curTree = prevList Map.! v
-- main :: IO ()
main = do
buf <- getLine
let n = read buf :: Int
buf <- getContents
let commands = (map read) . words $ buf :: [Int]
putStrLn $ runCommands commands $ Map.singleton 0 Null
return ()