用函数式语言通过此题的尝试
查看原帖
用函数式语言通过此题的尝试
66287
樱初音斗橡皮楼主2023/1/29 11:31

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 ()
2023/1/29 11:31
加载中...