The winner of the card game popular in Berland "Berlogging" is determined according to the following rules. If at the end of the game there is only one player with the maximum number of points, he is the winner. The situation becomes more difficult if the number of such players is more than one. During each round a player gains or loses a particular number of points. In the course of the game the number of points is registered in the line "name score", where name is a player's name, and score is the number of points gained in this round, which is an integer number. If score is negative, this means that the player has lost in the round. So, if two or more players have the maximum number of points (say, it equals to m) at the end of the game, than wins the one of them who scored at least m points first. Initially each player has 0 points. It's guaranteed that at the end of the game at least one player has a positive number of points.

The first line contains an integer number n (1  ≤  n  ≤  1000), n is the number of rounds played. Then follow n lines, containing the information about the rounds in "name score" format in chronological order, where name is a string of lower-case Latin letters with the length from 1 to 32, and score is an integer number between -1000 and 1000, inclusive.

import Control.Monad
import Data.List
import Text.Printf

findIndexIn :: [(String, Int)] -> String -> Int
findIndexIn list key =
    let keys = map (\(k, _) -> k) list
        result = elemIndex key keys
    in case result of Just index -> index
                      Nothing -> -1

findAnswer :: [(String, Int)] -> [(String, Int)]  -> Int -> [String] -> String
findAnswer current ((name, score):others) mx candidates =
    let findIndexInCurrent = findIndexIn current
        index = findIndexInCurrent name
        new =
            if index >= 0
                then
                    let prefix = take index current
                        suffix = drop (index + 1) current
                        update = [(name, score + (snd (current !! index)))]
                    in prefix ++ update ++ suffix
                else current ++ [(name, score)]
        currentValue =
            if index >= 0
                then score + (snd ( current !! index ))
                else score
    in if (currentValue >= mx) && (elem name candidates)
        then name
        else findAnswer new others mx candidates

computeNameScoreMap :: [(String, Int)] -> [(String, Int)] -> [(String, Int)]
computeNameScoreMap result [] = result
computeNameScoreMap current ((name, score):others) =
    let findIndexInCurrent = findIndexIn current
        index = findIndexInCurrent name
        new =
            if index >= 0
                then
                    let prefix = take index current
                        suffix = drop (index + 1) current
                        update = [(name, score + (snd (current !! index)))]
                    in prefix ++ update ++ suffix
                else current ++ [(name, score)]
    in computeNameScoreMap new others

readInputRow :: Int -> IO (String, Int)
readInputRow _ = do
    input <- getLine
    let [name, score_] = words input
        score = read score_ :: Int
    return (name, score)

readInputs :: IO [(String, Int)]
readInputs = do
    input <- getLine
    let n = read input
    inputs <- forM [1..n] readInputRow
    return inputs

solve :: [(String, Int)] -> String
solve list =
    let cnsMap = computeNameScoreMap [] list
        keys = map (\(k, _) -> k) cnsMap
        mx = foldl (\c (_, v) -> (if v > c then v else c)) (-1000000) cnsMap
        candidates = map (\(k, _) -> k) (filter (\(_, v) -> v == mx) cnsMap)
        answer = findAnswer [] list mx candidates
    in answer

main = do
    inputs <- readInputs
    printf "%s\n" (solve inputs)

import qualified Data.ByteString.Char8 as B
import Data.Map.Strict (Map, fromListWith, toList)
import Data.List (maximumBy, minimumBy)

main = do
    n <- readLn
    lst <- sequence $ take n $ repeat B.getLine
    B.putStrLn $ calc n lst

calc::Int->[B.ByteString]->B.ByteString
calc n strLst = let
                    lst1 = zipWith zipFun [1..n] strLst
                      where
                        zipFun a b = (head nameScore, [(a, (read::String->Int) $ B.unpack $ last nameScore)])
                          where nameScore = B.split (toEnum $ fromEnum ' ') b

                    lst2::[(B.ByteString, [(Int,Int)])]
                    lst2 = toList $ fromListWith mapFun lst1
                      where mapFun ((newNum,newScore):_) xs@((_,oldScore):_) = (newNum, oldScore+newScore) : xs

                    getScore (_,((_, score):_)) = score
                    maxScore = getScore $ maximumBy (\a b-> compare (getScore a) (getScore b)) lst2

                    lst3 = filter (\a->getScore a == maxScore) lst2

                    getLider (a:[]) = fst a
                    getLider lst = fst $ minimumBy (\(_, num1)(_, num2)->compare num1 num2) (map mapFunc lst)
                        where mapFunc (name, numList) = (name, fst $ minimumBy (\(num1, _)(num2, _)->compare num1 num2) (filter (\(_, score)->score >= maxScore) numList))
                in
                    getLider lst3

import qualified Data.Map as M

solve :: (M.Map String Int, [(String, Int)]) -> (String, Int) -> (M.Map String Int, [(String, Int)])
solve (table, records) (name, score') =
  (M.insert name score table, (name, score) : records)
  where score = score' + M.findWithDefault 0 name table

parse :: [String] -> [(String, Int)]
parse [] = []
parse (name : score : rest) = (name, read score) : parse rest

main :: IO ()
main = do
  input <- getContents

  let
    (table, records) = foldl solve (M.empty, []) (parse . tail . words $ input)
    highscore = maximum $ M.elems table
    cands = M.filter (== highscore) table
    isWinner (name, score) = score >= highscore && name `M.member` cands

  putStrLn . fst . last . filter isWinner $ records

import qualified Data.Map as M
import Data.Functor ((<$>))
import Control.Monad (foldM)

solve :: (M.Map String Int, [(String, Int)]) -> Int -> IO (M.Map String Int, [(String, Int)])
solve (table, records) _ = do
  [name, score'] <- words <$> getLine
  let score = read score' + M.findWithDefault 0 name table
  return (M.insert name score table, (name, score) : records)

main :: IO ()
main = do
  n <- readLn
  (table, records) <- foldM solve (M.empty, []) [1..n]
  let
    pickWinners (highscore', cands') name score
      | score == highscore' = (highscore', M.insert name () cands')
      | score > highscore' = (score, M.singleton name ())
      | otherwise = (highscore', cands')
    --(highscore, cands) = M.foldlWithKey pickWinners (-1, M.empty) table
    highscore = maximum $ M.elems table
    cands = M.filter (== highscore) table
    isWinner (name, score) = score >= highscore && name `M.member` cands

  putStrLn . fst . last . filter isWinner $ records

import qualified Data.Map as M
import Data.Functor ((<$>))
import Control.Monad (foldM)

solve :: (M.Map String Int, [(String, Int)]) -> Int -> IO (M.Map String Int, [(String, Int)])
solve (table, records) _ = do
  [name, score'] <- words <$> getLine
  let score = read score' + M.findWithDefault 0 name table
  return (M.insert name score table, (name, score) : records)

main :: IO ()
main = do
  n <- readLn
  (table, records) <- foldM solve (M.empty, []) [1..n]
  let
    pickWinners (highscore', cands') name score
      | score == highscore' = (highscore', M.insert name () cands')
      | score > highscore' = (score, M.singleton name ())
      | otherwise = (highscore', cands')
    (highscore, cands) = M.foldlWithKey pickWinners (-1, M.empty) table
    isWinner (name, score) = score >= highscore && name `M.member` cands

  putStrLn . fst . head . filter isWinner $ reverse records

main = do
	n<-getLine
	reading (read n) []

reading 0 buf = do
	putStrLn $ pars buf
reading a buf = do
	s<-getLine
	reading (a-1) $ buf++ s ++"\n"

example = "3\nmike 3\n andrew 5\nmike 2\n"

ex2="mike 3\n andrew 5\nmike 2\n" -- andrew
ex="a 3\na 2\nm 5" -- a

test6="alex 3\nalex 3\n alex 2\nalex -1\nmike 7\n" -- ans is alex
test7="alex 3\nalex 4\n alex -1\nmike 7\n" -- ans is mike
test8="a 1\na 1\na 1\na 1\na 1\na 1\na 1\na 1\na 1\na 1\na 1\na 1\na 1\na 1\na 1\na 1\na 1\na 1\na 1\na 1\na 1\na 1\na 1\na 1\na 1\na 1\na 1\na 1\na 1\na 1\na 1\na 1\na 1\na 1\na 1\na 1\na 1\na 1\na 1\na 1\na 1\na 1\na 1\na 1\na 1\na 1\na 1\na 1\na 1\na 1\na 1\na 1\na 1\na 1\na 1\na 1\na 1\na 1\na 1\na 1\na 1\na 1\na 1\na 1\na 1\na 1\na 1\na 1\na 1\na 1\na 1\na 1\na 1\na 1\na 1\nm 500\n"
test9="g 10\ng 10\ng -100\na 5\nm 5\n"

pars::String->String
pars s = solve $map helppars $lines s

helppars::String->(String,Int)
helppars s = (name,score)
  where
  	 parts= words s
  	 name = head parts
  	 score = read $last parts

solve::[(String,Int)]->String
solve x =  if length winners == 1 then fst $head winners
           else simulate 0 toSimulate m
    where
         res = summarize x
         m = maxScore $ res
         winners = filter ((==m).snd) res
         toSimulate =  filter (myelem (map fst winners).fst) x

myelem s m = elem m s

addScore::[(String,Int)]->(String,Int)
addScore s = (fst (head s), sum $ map snd s)

compNames::String->(String,Int)->Bool
compNames name1 (name2,score2)= name1==name2
comp::String->[(String,Int)]->[(String,Int)]
comp name s = filter (compNames name) $ s

summarize::[(String,Int)]->[(String,Int)]
summarize []= []
summarize s = [addScore (comp (name) s )] ++
            (summarize $ ( clearNames name (tail s)))
            where name = fst (head s)

simulate position s m
-- берем первые position+1 строк
-- ищем в них имя из текущей позиции
-- складываем все вхождения на данный момент
-- если вдруг мы получили результат больше или равный максимуму - мы нашил победителя
   | position<length s = if snd (addScore (comp (name) (take (position+1) s) ))>=m then name
            else simulate (position+1) s m
	        where name = fst (s!!position)

clearNames name s = filter (not.compNames name) s

maxScore s = maximum $ map snd s

{-
    Get a list of "name score" pairs and output the name of the person who reaches the maximum
    score first
-}

import qualified Data.Map as M
import Data.List (mapAccumL)

parse [x,y] = (x, (read y) :: Int)

solve :: [(String, Int)] -> String
solve xs = head [ name | (name, score) <- ms, M.member name winners, score >= maxScore]
            -- (m, ms) :: ( Map String Int, [(String, Int)] )
    where
        (m, ms) = mapAccumL (\s (p, i) -> (M.insertWith (+) p i s, (p, M.findWithDefault 0 p s + i))) M.empty xs
        maxScore = maximum (M.elems m)
        winners = M.filter (==maxScore) m

main = interact $ solve . map (parse.words) . tail . lines

import Data.Map as Map

main = do
        n <- fmap read getLine
        a <- mapM (\_ -> fmap (\[name, score] -> (name, read score::Int)) $ fmap words getLine) [1..n]
        let (scores, bestScore) = winner a
	    bests = Map.filter (\score -> score == bestScore) scores
        putStr $ if size bests == 1
		then fst $ head $ Map.toList bests
		else winner1 a scores bestScore Map.empty

winner ((name, score):xs) = winner' xs (Map.singleton name score) name
winner' []                 scores best =
        let bestScore = Map.fold max 0 scores
        in (scores, bestScore)

winner' ((name, score):xs) scores best =
        let newScores = Map.insertWith (+) name score scores
            (Just bestScore) = Map.lookup best scores
            (Just changedScore) = Map.lookup name newScores
            newBest = if bestScore < changedScore
                then name
                else best
        in winner' xs newScores newBest

winner1 ((name, score):xs) endScores bestScore scores =
	let newScores = Map.insertWith (+) name score scores
	    (Just changedScore) = Map.lookup name newScores
	    (Just endScore) = Map.lookup name endScores
	in if endScore == bestScore && changedScore >= bestScore
		then name
		else winner1 xs endScores bestScore newScores

import Data.Map as Map

main = do
        n <- fmap read getLine
        game <- mapM (\_ -> fmap (\[name, score] -> (name, read score::Int)) $ fmap words getLine) [1..n]
        let scores    = foldl (\scores (name, score) -> Map.insertWith (+) name score scores) Map.empty game
	    bestScore = Map.fold max 0 scores
	    bests     = Map.filter (\score -> score == bestScore) scores
        putStr $ if size bests == 1
		then fst $ head $ Map.toList bests
		else winner game scores bestScore Map.empty

winner ((name, score):xs) endScores bestScore scores =
	let newScores = Map.insertWith (+) name score scores
	    (Just changedScore) = Map.lookup name newScores
	    (Just endScore) = Map.lookup name endScores
	in if endScore == bestScore && changedScore >= bestScore
		then name
		else winner xs endScores bestScore newScores

import Data.Map as Map

main = do
	n <- fmap read getLine
	a <- mapM (\_ -> fmap (\[name, score] -> (name, read score::Int)) $ fmap words getLine) [1..n]
	let (scores, bestScore) = winner a
	putStr $ winner1 a scores bestScore Map.empty

winner ((name, score):xs) = winner' xs (Map.singleton name score) name
winner' []		   scores best =
	let bestScore = Map.fold max 0 scores
	in (scores, bestScore)

winner' ((name, score):xs) scores best =
	let newScores = Map.insertWith (+) name score scores
	    (Just bestScore) = Map.lookup best scores
	    (Just changedScore) = Map.lookup name newScores
	    newBest = if bestScore < changedScore
		then name
		else best
	in winner' xs newScores newBest

winner1 ((name, score):xs) endScores bestScore scores
	| size bests == 1 = fst $ head $ Map.toList bests
	| otherwise 	    =
		let newScores = Map.insertWith (+) name score scores
	    	    (Just changedScore) = Map.lookup name newScores
	    	    (Just endScore) = Map.lookup name endScores
		in if endScore == bestScore && changedScore >= bestScore
			then name
			else winner1 xs endScores bestScore newScores
	where bests = Map.filter (\score -> score == bestScore) endScores

parse [a, b] = (a, read b :: Int)

qsort :: [(String, Int)] -> [(String, Int)]
qsort [] = []
qsort((imie, liczba):xs) = qsort [y | y <- xs, fst y < imie] ++ ((imie, liczba):[y | y <- xs, fst y == imie]) ++ qsort [y | y <- xs, fst y > imie]

-- teraz stworzymy liste (imie, ostatecznyWynik) zakladajac posortowanie po imionach, bedzie fold

sumujPoWyniku :: [(String, Int)] -> [(String, Int)]
sumujPoWyniku [] = []
sumujPoWyniku [(imie, liczba)] = [(imie, liczba)]
sumujPoWyniku ((imie, liczba):(imie1, liczba1):xs) = if imie == imie1 then sumujPoWyniku ((imie, liczba+liczba1):xs) else (imie, liczba):sumujPoWyniku ((imie1, liczba1):xs)

--oki doki, teraz bedziemy chcieli maksa z tego. czyli po prostu bierzemy funkcje, drugie i bierzemy maximum

drugie :: [(String, Int)] -> [Int]
drugie = foldr f []
  where
    f (imie, liczba) xs = (liczba:xs)

--i teraz m = maximum.drugie.sumujPoWyniku.qsort l

winners :: [(String, Int)] -> [String]
winners l = map fst (filter ((==m).snd) maksy)
  where
    m = (maximum.drugie.sumujPoWyniku.qsort) l
    maksy = (sumujPoWyniku.qsort) l

ztrojkuj :: (String, Int) -> Int -> (String, Int, Int)
ztrojkuj (a, b) c = (a, b, c)

--if wynikSoFar imie indeks >= m then imie else licz xs

zmienWTrojki :: [(String, Int)] -> [(String, Int, Int)]
zmienWTrojki l = zipWith ztrojkuj l [1..]

--czyli mamy trojki, teraz mozemy to posumowac

wynikSoFar :: Int -> String -> Int -> [(String, Int, Int)] -> Int
wynikSoFar aktualny imie indeks [] = aktualny
wynikSoFar aktualny imie indeks ((imie1, liczba1, indeks1):xs) = if indeks < indeks1 then aktualny else ( if imie == imie1 then wynikSoFar (aktualny+liczba1) imie indeks xs else wynikSoFar aktualny imie indeks xs )

znajdzWynik :: [(String, Int, Int)] -> Int -> [(String, Int)] -> [String] -> String
znajdzWynik ((imie, liczba, indeks):xs) maksik lista zwyciezcy = if ((wynikSoFar 0 imie indeks (zmienWTrojki lista) >= maksik) && (elem imie zwyciezcy)) then imie else znajdzWynik xs maksik lista zwyciezcy

ziomek :: [(String, Int)] -> String
ziomek l = znajdzWynik (zmienWTrojki l) maks l zwyciezcy
  where
    maks = (maximum.drugie.sumujPoWyniku.qsort) l
    zwyciezcy = winners l

main = do
  s <- getContents
  let inp = map (parse . words) . tail . lines $ s
  putStrLn $ ziomek inp

import qualified Data.Map as M
import Debug.Trace
import Data.List (sortBy)

type Score = Int
data Round = Round { roundNumber :: Int
                   , player :: String
                   , roundScore :: Score
                   } deriving (Show)

type Game = M.Map String [Round]

toRound :: (String, Int) -> Round
toRound (roundInfo, roundNum) = Round roundNum name score
    where name = takeWhile (\x -> x /= ' ') roundInfo
          score = read $ drop (length name + 1) roundInfo

totalScore :: [Round] -> Score
totalScore = (foldl (+) 0) . (map roundScore)

maxScore :: Game -> Score
maxScore = maximum . M.elems . fmap totalScore

playersWithMax :: Game -> Game
playersWithMax g = M.filter (\v -> (totalScore v) == ms) g
    where ms = maxScore g

winner :: Game -> String
winner g = case M.size candidates of
    1 -> M.keys candidates !! 0
    _ -> compareByRound candidates ms
    where
        ms = maxScore g
        candidates = playersWithMax g

updateRound :: Round -> Score -> Round
updateRound r s = Round (roundNumber r) (player r) (s)

roundReachScore :: Score -> [Round] -> Int
roundReachScore s rs = roundNumber . head $ dropWhile lessThanScore cumulative
  where add r1 r2 = updateRound r2 ((roundScore r1) + (roundScore r2))
        cumulative = scanl1 add rs
        lessThanScore r = (roundScore r) < s

compareByRound :: Game -> Score -> String
compareByRound g s = fst . head . sort . M.toList $ roundForScore
  where
    roundForScore = M.map (roundReachScore s) g
    sort = sortBy (\x y -> compare (snd x) (snd y))

playRound :: Round -> Game -> Game
playRound r g = M.insertWith (flip (++)) (player r) [r] g

main :: IO ()
main = do
    input <- getLine
    final <- playN $ read input
    putStrLn $ winner final

playN :: Int -> IO Game
playN n = playOne 1 n M.empty
    where playOne r n g
            | r > n = return g
            | otherwise = do
                input <- getLine
                playOne (r + 1) n $ playRound (toRound (input, r)) g

-- Codeforces 2A
import qualified Data.Map as Map
import Data.Maybe
import Data.List.Split
import Control.Monad

type Score = Integer
type Name = String

createMap :: [(Name, Score)] -> Map.Map Name Score
createMap list = Map.fromListWith (+) list

findMaxVal :: Map.Map Name Score -> Score
findMaxVal map = maximum (Map.elems map)

filterPlayers :: Map.Map Name Score -> Score -> [Name]
filterPlayers map score = filter prediate (Map.keys map)
    where prediate = (\key -> fromJust (Map.lookup key map) == score)

findFirst :: [(Name, Score)] -> Map.Map Name Score -> [Name] -> Score -> Name
findFirst [] _ _ _ = ""
findFirst (x:xs) map potentialWinners maxScore = winner
    where name = fst x
          score = snd x
          newMap = Map.alter (updateValue score) name map
          newScore = fromJust (Map.lookup name newMap)
          winner
            | newScore >= maxScore && name `elem` potentialWinners = name
            | otherwise = findFirst xs newMap potentialWinners maxScore

updateValue :: Score -> Maybe Score -> Maybe Score
updateValue x Nothing = Just x
updateValue x (Just y) = Just (x + y)

toRecord :: String -> (Name, Score)
toRecord string = (name, score)
    where strings = splitOn " " string
          name = strings !! 0
          score = read $ strings !! 1

main :: IO ()
main = do
    linesToRead <- getLine
    input <- getContents
    let inputs = take (read linesToRead) (lines input)
    let records = map toRecord inputs
    let map = createMap records
    let maxVal = findMaxVal map
    let potentialWinners = filterPlayers map maxVal
    let result = findFirst records Map.empty potentialWinners maxVal
    putStrLn $ id (result)

import Control.Monad
import Data.List
import Debug.Trace
import qualified Data.Map as M

myTrace :: (Show a) => a -> a
myTrace x = traceShow x x

data LogEntry = LogEntry String Int
	deriving (Eq, Show)

score (LogEntry _ v) = v
name (LogEntry n _) = n

instance Ord LogEntry where
	(<=) (LogEntry _ a) (LogEntry _ b) = a <= b

getInput = do
	n <- (liftM read) getLine :: IO Int
	lines <- sequence $ replicate n getLine
	return $ map parseEntry lines

parseEntry s = LogEntry name deltaScore
	where
		parts = words s
		name = head parts
		deltaScore = read $ parts !! 1

foldLog :: [LogEntry] -> (Int, [LogEntry])
foldLog log = (maxValue, filter (\(LogEntry n v) -> maxValue == M.findWithDefault 0 n m) entries)
	where
		maxValue = snd $ maximumBy (\(k1, a1) (k2, a2) -> a1 `compare` a2) $ M.toList m
		(m, entries) = mapAccumL foldEntry M.empty log
		foldEntry :: M.Map String Int -> LogEntry -> (M.Map String Int, LogEntry)
		foldEntry m (LogEntry name deltaScore) = (newMap, LogEntry name newScore)
			where
				newScore = deltaScore + M.findWithDefault 0 name m
				newMap = M.insert name newScore m

winner (maxValue, foldedLog) = name $ head $ filter (\(LogEntry _ value) -> value >= maxValue) foldedLog

main = do
	log <- getInput
	putStrLn $ winner $ foldLog log

{-# OPTIONS_GHC -O2 -XNoMonomorphismRestriction #-}
{-# LANGUAGE BangPatterns #-}
{-(c) gorlum0 [at] gmail.com-}
import qualified Data.Map as M
import qualified Data.Set as S

splitEvery _ [] = []
splitEvery n xs = ys : splitEvery n xs'
    where (ys, xs') = splitAt n xs

winner :: [(String, Int)] -> String
winner rounds = f M.empty rounds'
    where
    rounds' = [(k, v) | (k, v) <- rounds, S.member k cands]

    game = M.fromListWith (+) rounds
    m = maximum $ M.elems game
    cands = S.fromList [k | (k, v) <- M.toList game, v == m]

    f :: M.Map String Int -> [(String, Int)] -> String
    f game ((k,v):xs)
        | n >= m    = k
        | otherwise = f game' xs
        where game' = M.insertWith (+) k v game
              Just n = M.lookup k game'

body :: [String] -> [String]
body [] = []
body (n:xs) = winner rounds : body xs'
    where
    n' = read n
    (ys, xs') = splitAt (n'*2) xs
    rounds = [(k, read v) | [k, v] <- splitEvery 2 ys]

main = do
    ws <- words `fmap` getContents
    mapM_ putStrLn $ body ws

{-# OPTIONS_GHC -O2 -XNoMonomorphismRestriction #-}
{-# LANGUAGE BangPatterns #-}
{-(c) gorlum0 [at] gmail.com-}
import qualified Data.Map as M
import qualified Data.Set as S

splitEvery _ [] = []
splitEvery n xs = ys : splitEvery n xs'
    where (ys, xs') = splitAt n xs

winner rounds = f M.empty rounds''
    where
    rounds' = [(k, read v) | [k, v] <- splitEvery 2 rounds]
    rounds'' = [(k, v) | (k, v) <- rounds', S.member k cands]

    game = M.fromListWith (+) rounds'
    m = maximum [v | (_, v) <- M.toList game]
    cands = S.fromList [k | (k, v) <- M.toList game, v == m]

    f :: M.Map String Int -> [(String, Int)] -> String
    f game ((k,v):xs)
        | n >= m    = k
        | otherwise = f game' xs
        where game' = M.insertWith (+) k v game
              Just n = M.lookup k game'

body :: [String] -> [String]
body [] = []
body (n:xs) = winner ys : body xs'
    where
    n' = read n
    (ys, xs') = splitAt (n'*2) xs

main = do
    ws <- words `fmap` getContents
    mapM_ putStrLn $ body ws

import qualified Data.Map as M
import Data.Maybe

split [] = []
split (x:y:xs) = (x, read y :: Int) : split xs

candidates x =
    let r = M.fromListWith (+) x
        m = maximum $ M.elems r
    in M.filter (== m) r

verify ((k,v0):xs) m0
    | v1 == Nothing     = verify xs m0
    | fromJust v1 <= v0 = k
    | otherwise         = verify xs (M.insertWith (+) k (-v0) m0)
    where v1 = M.lookup k m0

main = do
    s <- getContents
    let l = split . tail . words $ s
    putStrLn $ verify l $ candidates l

import List (maximumBy)
import Data.Map (Map, empty, insertWith, assocs, filter, keys, findWithDefault)

{-
--------------------------------------------------------------------------------

import HUnit

testOnePlayer :: Test
testOnePlayer  =  TestList "TestOnePlayer"
  [
    Test "1" $ assertEq "Dims" (solve [("Dims", 1)]),
    Test "2" $ assertEq "Tanya" (solve [("Tanya", 1)])
  ]

testTwoPlayers :: Test
testTwoPlayers  =  TestList "TestTwoPlayers"
  [
    Test "1" $ assertEq "Dims" (solve [("Dims", 2), ("Tanya", 1)]),
    Test "2" $ assertEq "Tanya" (solve [("Dims", 1), ("Tanya", 2)])
  ]

testSumScore :: Test
testSumScore  =  Test "TestSumScore" $
    assertEq "Dims" (solve [("Dims", 2), ("Dims", 2), ("Tanya", 3)])

testDifficult :: Test
testDifficult  =  TestList "TestDifficult"
  [
    Test "1" $ assertEq "Dims" (solve [("Dims", 2), ("Dims", 2), ("Tanya", 4)]),
    Test "2" $ assertEq "Tanya" (solve [("Dims", 2), ("Tanya", 4), ("Dims", 2)])
  ]

testMaxScoreNotWinner :: Test
testMaxScoreNotWinner  =  Test "TestMaxScoreNotWinner" $
    assertEq "Tanya" (solve [("Dims", 5), ("Tanya", 1), ("Dims", -5)])

testInput :: Test
testInput  =  TestList "TestInput"
  [
    Test "1" $ assertEq "andrew" (solve [("mike", 3), ("andrew", 5), ("mike", 2)]),
    Test "2" $ assertEq "andrew" (solve [("andrew", 3), ("andrew", 2), ("mike", 5)])
  ]

test :: IO ()
test  =  mapM_ run
  [
    testOnePlayer,
    testTwoPlayers,
    testSumScore,
    testDifficult,
    testMaxScoreNotWinner,
    testInput
  ]

--------------------------------------------------------------------------------
-}

solve :: [(String, Int)] -> String
solve results  =  solve' results empty
  where
    map  =  foldl (flip (\(name, score) -> insertWith (+) name score)) empty results
    maxScore  =  snd $ maximumBy (\x y -> compare (snd x) (snd y)) (assocs map)
    canBeWinners  =  keys $ Data.Map.filter (== maxScore) map
    solve' [] _  =  error "Logical error."
    solve' ((name, score):xs) map
      | name `notElem` canBeWinners  =  solve' xs map
      | findWithDefault 0 name map' >= maxScore  =  name
      | otherwise  =  solve' xs map'
      where
        map'  =  insertWith (+) name score map

getResult ::  IO (String, Int)
getResult  =  do
    line  <-  getLine
    let [name, score]  =  words line
    return (name, read score)

main :: IO ()
main  =  do
    n  <-  readLn
    results  <-  mapM (const getResult) [1..n]
    putStrLn $ solve results

-- Codeforce 2A

import Data.Maybe
import qualified Data.Map as Map

main :: IO ()
main = do
    getLine
    getContents >>= putStrLn . solve . map ((\[name, score] -> (name, (read score) :: Int)) . words) . lines

solve :: [(String, Int)] -> String
solve xs = winner xs $ allwinners xs

winner :: [(String, Int)] -> Map.Map String Int -> String
winner ((name, score):xs) all
    | target == Nothing = winner xs all
    | score >= fromJust target = name
    | otherwise = winner xs (Map.insertWith (+) name (-score) all)
    where target = Map.lookup name all

allwinners :: [(String, Int)] -> Map.Map String Int
allwinners xs = Map.filter (== val) m where
    m = Map.fromListWith (+) xs
    val = maximum $ Map.elems m

import qualified Data.Map.Lazy as M
import Data.Maybe

main :: IO ()
main = interact $ show . solve . map read . tail . lines

data Point = Point { name :: String, score :: Integer }

instance Show Point where
  show (Point n _) = n

instance Read Point where
  readsPrec _ s = let [n, p] = words s in [(Point n (read p), "")]

instance Eq Point where
  (==) (Point _ x) (Point _ y) = (==) x y

instance Ord Point where
  (<=) (Point _ x) (Point _ y) = (<=) x y

(+++) :: Point -> Point -> Point
(+++) (Point _ x) (Point n y) = Point n (x + y)

solve :: [Point] -> Point
solve pps = snd $ head $ filter (\(_, p) -> p >= maxPoint && name p `elem` winnerNames) scores
  where maxPoint = maximum $ map snd $ M.toList lastScores
        scores = scanl go (M.empty, Point "" 0) pps
        lastScores = fst $ last scores
        winnerNames = M.keys $ M.filter (==maxPoint) lastScores
        go (m, _) p@(Point n _) =
          let newhm = M.insertWith (+++) n p m
              in (newhm, fromJust $ M.lookup n newhm)

import qualified Data.Map as M
import Control.Arrow (second)
import Data.List (mapAccumL)

main :: IO ()
main = getContents >>= putStrLn . solve . map (second read . toTuple . words) . tail . lines

solve :: [(String, Integer)] -> String
solve xs = head [ name | (name, score) <- scores, M.member name winners, score >= maxScore ]
  where (lastScores, scores) = mapAccumL f M.empty xs
        f s (x, i) = (M.insertWith (+) x i s, (x, M.findWithDefault 0 x s + i))
        maxScore = maximum (M.elems lastScores)
        winners = M.filter (==maxScore) lastScores

toTuple :: [a] -> (a, a)
toTuple xs = (head xs, xs !! 1)

import qualified Data.Map.Lazy as M
import Data.Maybe

main :: IO ()
main = interact $ show . solve . map read . tail . lines

data Point = Point { name :: String, score :: Integer }

instance Show Point where
  show (Point n _) = n

instance Read Point where
  readsPrec _ s = let [n, p] = words s in [(Point n (read p), "")]

instance Eq Point where
  (==) (Point _ x) (Point _ y) = (==) x y

instance Ord Point where
  (<=) (Point _ x) (Point _ y) = (<=) x y

(+++) :: Point -> Point -> Point
(+++) (Point _ x) (Point n y) = Point n (x + y)

solve :: [Point] -> Point
solve pps = snd $ head $ filter (\(_, p) -> p >= maxp && name p `elem` names) scores
  where maxp = maximum $ map snd $ M.toList lastscores
        scores = scanl go (M.empty, Point "" 0) pps
        lastscores = fst $ last scores
        names = M.keys $ M.filter (==maxp) lastscores
        go (m, _) p@(Point n _) =
          let newhm = M.insertWith (+++) n p m
              in (newhm, fromJust $ M.lookup n newhm)

import qualified Data.Map as M
import Control.Arrow (second)
import Data.List (mapAccumL)

main :: IO ()
main = getContents >>= putStrLn . solve . map (second read . toTuple . words) . tail . lines

solve :: [(String, Integer)] -> String
solve xs = head [ name | (name, score) <- ms, M.member name winners, score >= maxScore ]
  where (m, ms) = mapAccumL (\s (x, i) -> (M.insertWith (+) x i s, (x, M.findWithDefault 0 x s + i))) M.empty xs
        maxScore = maximum (M.elems m)
        winners = M.filter (==maxScore) m

toTuple :: [a] -> (a, a)
toTuple xs = (head xs, xs !! 1)

import qualified Data.Map as M
import Data.Maybe

main :: IO ()
main = getContents >>= print . solve . map read . tail . lines

data Point = Point { name :: String, score :: Integer }

instance Show Point where
  show (Point n _) = n

instance Read Point where
  readsPrec _ s = let [n, p] = words s in [(Point n (read p), "")]

instance Eq Point where
  (==) (Point _ x) (Point _ y) = (==) x y

instance Ord Point where
  (<=) (Point _ x) (Point _ y) = (<=) x y

(+++) :: Point -> Point -> Point
(+++) (Point _ x) (Point n y) = Point n (x + y)

solve :: [Point] -> Point
solve pps = snd $ head $ filter isWinner scores
  where maxPoint = maximum $ map snd $ M.toList lastscores
        scores = scanl go (M.empty, Point "" 0) pps
        lastscores = fst $ last scores
        winnerNames = M.keys $ M.filter (==maxPoint) lastscores
        isWinner (_, p) = p >= maxPoint && name p `elem` winnerNames
        go (m, _) p@(Point n _) =
          let newhm = M.insertWith (+++) n p m
              in (newhm, fromJust $ M.lookup n newhm)

import Data.Maybe
import Data.List
import qualified Data.Map as M
import Control.Monad

main = putStrLn . solve . map words . tail . lines =<< getContents
solve s = case ws of
            [w1] -> w1
            _ -> head $ catMaybes $ map snd game
    where f (a,_) [rw,rs] = a' `seq`
                            ( a', guard (rw `elem` ws) >>
                                  M.lookup rw a' >>=
                                  guard . (>=m) >>
                                  return rw )
              where a' = M.insertWith (+) rw (read rs) a
          game = scanl f (M.empty,Nothing) s
          final = fst (last game)
          m = M.fold max 0 final
          ws = M.keys (M.filter (==m) final)

import Data.Maybe
import qualified Data.Map as M

parse [a,b] = (a,(read b)::Int)

winners l = M.filter (==m) res
    where
        res = M.fromListWith (+) l
        m = maximum $ M.elems res

eval ((p,x):xs) w
    | goal == Nothing = eval xs w
    | x >= fromJust goal = p
    | otherwise = eval xs (M.insertWith (+) p (-x) w)
    where goal = M.lookup p w

main = do
    s <- getContents
    let inp = map (parse.words) . tail . lines $ s
    putStrLn $ eval inp $ winners inp

module Main where

import Data.Ord (comparing)
import qualified Data.Map as Map
import qualified Data.Set as Set

type Player = String
type Score = Int
type Round = (Player, Score)

main :: IO ()
main = interact (game . parseRounds)

game :: [Round] -> Player
game rounds = winner winScore candidates candidateRounds where
	results = Map.toList $ Map.fromListWith (+) rounds
	winScore = maximum $ map snd results
	candidates = map fst $ filter ((== winScore) . snd) results
	candidateSet = Set.fromList candidates
	candidateRounds = filter ((flip Set.member) candidateSet . fst) rounds

winner :: Score -> [Player] -> [Round] -> Player
winner winScore players = go startScores where
	startScores = Map.fromList $ zip players (repeat 0)
	go scores ((player, score) : rounds)
		| score' >= winScore = player
		| otherwise = go scoreMap' rounds
		where (Just score', scoreMap') = Map.updateLookupWithKey (const (Just . (+ score))) player scores

parseRounds :: String -> [Round]
parseRounds = map readRound . tail . lines

readRound :: String -> Round
readRound str = (player, read score)
	where [player, score] = words str

module Main where

import Data.Function (on)
import Data.List (find, maximumBy)
import Data.Map (Map, empty, insertWith, toList)
import Data.Maybe (fromJust)

newtype Player = Player String deriving (Eq, Ord, Show)
newtype Score = Score Int deriving (Eq, Ord, Show)
newtype Index = Index Int deriving (Eq, Ord, Show)
data Round = Round Player Score Index
type ScoreIndex = (Score, Index)
type Play = Map Player [ScoreIndex]

main :: IO ()
main = interact $ showPlayer . winner . play . rounds
	where showPlayer (Player player) = player

winner :: Play -> Player
winner = fst . maximumBy (compareScores `on` snd) . toList

compareScores :: [ScoreIndex] -> [ScoreIndex] -> Ordering
compareScores xs@((x, _) :_) ys@((y, _) :_) = case compare x y of
	EQ -> (flip compare `on` scoredIndex x) xs ys
	cmp -> cmp

scoredIndex :: Score -> [ScoreIndex] -> Index
scoredIndex score = snd . fromJust . find ((>= score) . fst) . reverse

play :: [Round] -> Play
play = foldl (flip addRound) empty

addRound :: Round -> Play -> Play
addRound (Round player score index) = insertWith addScore player [(score, index)]

addScore :: [ScoreIndex] -> [ScoreIndex] -> [ScoreIndex]
addScore [(Score score, index)] rest@((Score acc, _) :_) = (Score (score + acc), index) : rest

rounds :: String -> [Round]
rounds str = zipWith ($) rounds indexes where
	rounds = map readRound . tail . lines $ str
	indexes = map Index [1 ..]

readRound :: String -> Index -> Round
readRound str = Round (Player player) (Score $ read score)
	where [player, score] = words str

import Data.List as L (filter, find, mapAccumL)
import Data.Map.Strict as M (empty, insert, filter, findWithDefault, member, toList)

main = interact $ winner . play . rounds . tail . words

winner (totals, rounds) = fst winner where
    max         = maximum . map snd $ toList totals
    winners     = M.filter (== max) totals
    Just winner = find ((>= max) . snd) $ L.filter ((flip member) winners . fst) rounds

play = mapAccumL addRound empty

addRound totals (player, score) = (insert player score' totals, (player, score'))
    where score' = score + findWithDefault 0 player totals

rounds [] = []
rounds (player : score : rest) = (player, read score) : rounds rest

import Data.List as L (filter, find, mapAccumL)
import Data.Map as M (empty, insert, filter, findWithDefault, member, toList)

main = interact $ winner . play . rounds . tail . words

winner (totals, rounds) = fst winner where
    max         = maximum . map snd $ toList totals
    winners     = M.filter (== max) totals
    Just winner = find ((>= max) . snd) $ L.filter ((flip member) winners . fst) rounds

play = mapAccumL addRound empty

addRound totals (player, score) = (insert player score' totals, (player, score'))
    where score' = score + findWithDefault 0 player totals

rounds [] = []
rounds (player : score : rest) = (player, read score) : rounds rest

import Data.List as L (filter, find, mapAccumL)
import Data.Map.Strict as M (empty, insert, filter, findWithDefault, member, toList)

main = interact $ winner . play . rounds . tail . words

winner (totals, rounds) = fst winner where
    max         = maximum . map snd $ toList totals
    winners     = M.filter (== max) totals
    Just winner = find ((>= max) . snd) $ L.filter ((flip member) winners . fst) rounds

play = mapAccumL addRound empty

addRound totals (player, score) = score' `seq` (insert player score' totals, (player, score'))
    where score' = score + findWithDefault 0 player totals

rounds [] = []
rounds (player : score : rest) = (player, read score) : rounds rest

module Main where

import Data.Function (on)
import Data.List (find, foldl', maximumBy)
import Data.Map (Map, empty, insertWith, toList)
import Data.Maybe (fromJust)

newtype Player = Player String deriving (Eq, Ord, Show)
newtype Score = Score Int deriving (Eq, Ord, Show)
newtype Index = Index Int deriving (Eq, Ord, Show)
data Round = Round Player Score Index
type ScoreIndex = (Score, Index)
type Play = Map Player [ScoreIndex]

main :: IO ()
main = interact $ showPlayer . winner . play . rounds
	where showPlayer (Player player) = player

winner :: Play -> Player
winner = fst . maximumBy (compareScores `on` snd) . toList

compareScores :: [ScoreIndex] -> [ScoreIndex] -> Ordering
compareScores xs@((x, _) :_) ys@((y, _) :_) = case compare x y of
	EQ -> (flip compare `on` scoredIndex x) xs ys
	cmp -> cmp

scoredIndex :: Score -> [ScoreIndex] -> Index
scoredIndex score = snd . fromJust . find ((>= score) . fst) . reverse

play :: [Round] -> Play
play = foldl' (flip addRound) empty

addRound :: Round -> Play -> Play
addRound (Round player score index) = insertWith addScore player [(score, index)]

addScore :: [ScoreIndex] -> [ScoreIndex] -> [ScoreIndex]
addScore [(Score score, index)] rest@((Score acc, _) :_) = (Score (score + acc), index) : rest

rounds :: String -> [Round]
rounds str = zipWith ($) rounds indexes where
	rounds = map readRound . tail . lines $ str
	indexes = map Index [1 ..]

readRound :: String -> Index -> Round
readRound str = Round (Player player) (Score $ read score)
	where [player, score] = words str

import Control.Applicative
import Control.Monad
import qualified Data.Map as Map
import Data.List
import Data.Ord

type Name = String
type Score = Int
type ID = Int
type Record = (Score, ID)
type PlainDB = [(Name, Record)]
type DB = [(Name, [Record])]

conv :: [String] -> PlainDB
conv (x : xs) = do
  (id_, [name_, score_]) <- zip [0 ..] . map words $ take (read x) xs
  return $ (name_, (read score_, id_))

merge :: PlainDB -> DB
merge = Map.toList . foldl' f Map.empty where
  f mp (name, others) = Map.insertWith g name [others] mp where
    g [(a, i)] xs@((b, _) : _) = (a + b, i) : xs

search :: DB -> String
search = findWinner . pickupCandidates . sortDB where
  score = fst . head . snd
  sortDB = sortBy (flip (comparing score))
  pickupCandidates db = check $ takeWhile ((== best) . score) db where
    best = score $ head db
    check = map (fmap (minimum . map snd . filter ((best <=) . fst)))
  findWinner = fst . minimumBy (comparing snd)

solve :: [String] -> [String]
solve = return . search . merge . conv

main = interact $ unlines . solve . lines

import qualified Data.Map as Map
import Data.List
main = do
    n <- read `fmap` getLine
    s <- mapM (\_ -> (\[w1, w2] -> (w1, read w2)) `fmap` (words `fmap` getLine)) [1..n]
    let map' = foldl' (\map (name, score) -> Map.insertWith (+) name score map) Map.empty s
        s' = groupBy (\(_, a) (_, b) -> a == b) $
                    sortBy (\(_, a) (_, b) -> compare b a) $ Map.toList map'
        s1' = head s'
    if length s1' == 1 then putStrLn $ fst.head $ s1' else do
        let m = snd (head s1')
            winners = map fst s1'
            f map ((name, score):ss) = let map' =  Map.insertWith (+) name score map in
                    if map' Map.! name >= m then name else f map' ss
            f _ [] = undefined
        putStrLn $ f Map.empty (filter (\(n,_) -> n `elem` winners) s)

module Main where

import qualified Data.Map.Strict as M
import Control.Monad
import Data.List
import Data.Maybe

type Score = Int
type Scores = M.Map String Score
type Action = (String, Score)

name :: Action -> String
name = fst

score :: Action -> Score
score = snd

addScore :: Score -> Maybe Score -> Score
addScore x Nothing = x
addScore x (Just y) = x + y

alterScores :: Scores -> Action -> Scores
alterScores scores action = M.alter (Just . addScore (score action)) (name action) scores

findFinalScores :: [Action] -> Scores
findFinalScores = foldl' alterScores M.empty

findWinnerScore :: Scores -> Score
findWinnerScore = maximum . M.elems

findWinner :: Score -> [Action] -> String
findWinner winnerScore actions = findWinner0 actions M.empty
  where
    findWinner0 (a:as) scores = if nextScore >= winnerScore then name a else findWinner0 as nextScores
      where
        nextScores = alterScores scores a
        nextScore = fromJust $ M.lookup (name a) nextScores

readAction :: String -> Action
readAction line = let [name, score] = words line in (name, read score)

solute :: [String] -> String
solute inputs = findWinner winnerScore winnerActions
  where
    actions = fmap readAction inputs
    finalScores = findFinalScores actions
    winnerScore = findWinnerScore finalScores
    winners = M.filterWithKey (\_ score -> score >= winnerScore) finalScores
    winnerActions = filter (\(n, _) -> M.member n winners) actions

main :: IO ()
main = do
  n <- read `fmap` getLine :: IO Int
  inputs <- replicateM n getLine
  putStrLn (solute inputs)

{-# LANGUAGE TypeSynonymInstances #-}
{-# OPTIONS_GHC -O2 #-}
import Data.Array
import Data.Map
class Scan a where scan' :: String -> a
instance Scan Int where scan' n = read n
instance Scan Char where scan' (x:_) = x
instance Scan Float where scan' f = read f
instance Scan Double where scan' d = read d
instance Scan Integer where scan' n = read n
instance Scan String where scan' x = x
instance (Scan a,Scan b) => Scan (a,b) where scan' x = scan'' (words x)
                                                 where
                                                   scan'' (x:y:_) = (scan' x,scan' y)
instance (Scan a,Scan b,Scan c) => Scan (a,b,c) where scan' x = scan'' (words x)
                                                          where
                                                            scan'' (x:y:z:_) = (scan' x,scan' y,scan' z)
instance (Scan a,Scan b,Scan c,Scan d) => Scan (a,b,c,d) where scan' x = scan'' (words x)
                                                                   where
                                                                     scan'' (w:x:y:z:_) = (scan' w,scan' x,scan' y,scan' z)
instance (Scan a,Scan b,Scan c,Scan d,Scan e) => Scan (a,b,c,d,e) where scan' x = scan'' (words x)
                                                                            where
                                                                              scan'' (v:w:x:y:z:_) = (scan' v,scan' w,scan' x,scan' y,scan' z)
class Ans a where showans :: a -> String
instance Ans Int where showans x = show x
instance Ans Char where showans x = [x]
instance Ans Float where showans x = show x
instance Ans Double where showans x = show x
instance Ans Integer where showans x = show x
instance Ans String where showans x = x
instance (Ans a, Ans b) => Ans (a,b) where
    showans (x,y) = showans x ++ " " ++ showans y
instance (Ans a, Ans b,Ans c) => Ans (a,b,c) where
    showans (x,y,z) = showans x ++ " " ++ showans y ++ " " ++ showans z

scan :: (Scan a) => IO a
scan = do n <- getLine
          return (scan' n)

scans :: (Scan a) => Int -> IO [a]
scans 0 = return []
scans n = do x <- scan
             xs <- scans (n-1)
             return (x:xs)

scanlist :: (Scan a) => IO [a]
scanlist = do l <- getLine
              return [scan' x|x<-words l]

scanlists :: (Scan a) => Int -> IO [[a]]
scanlists 0 = return []
scanlists n = do x <- scanlist :: (Scan a) => IO [a]
                 xs <- scanlists (n-1)
                 return (x:xs)

putAnsLn :: (Ans a) => a -> IO ()
putAnsLn ans = putStrLn (showans ans)

putAnsLns :: (Ans a) => [a] -> IO ()
putAnsLns (x:xs) = do putAnsLn x
                      putAnsLns xs
putAnsLns [] = return ()

putDebugLn :: (Show a) => a -> IO ()
putDebugLn ans = putStrLn (show ans)

neginf = -1000000000

-- �ǽ�Ū�˺ǹ�������ͤ����Υꥹ�ȤȺǹ���
maxscore [] mp = foldlWithKey (\(mx,l) -> \name -> \score -> if score>mx then (score,[name]) else if score==mx then (mx,name:l) else (mx,l)) (neginf,[]) mp
maxscore ((name,score):xs) mp= let mp' = insertWith (+) name score mp in maxscore xs mp'

solve ((name,score):xs) mp mx = case Data.Map.lookup name mp of
                                  Just sc |mx <= (sc+score) -> name
                                          |otherwise -> solve xs (insert name (score+sc) mp) mx
                                  Nothing -> solve xs mp mx

solve' l (mx,mem) = solve l (fromList (zip mem [0..])) mx

main = do n <- scan ::IO Int
          l <- scans n :: IO [(String,Int)]
          putAnsLn (solve' l (maxscore l empty))

import Control.Monad
import Data.Char
import Data.Maybe
import qualified Data.List as List
import qualified Data.Map as Map

getLines :: Int -> IO [String]
getLines n = replicateM n getLine

splitByPredicate :: (a -> Bool) -> [a] -> [[a]]
splitByPredicate _ [] = []
splitByPredicate p l
    | p (head l) == True = [takeWhile p l] ++ (splitByPredicate p (dropWhile p l))
    | otherwise          = [takeWhile (not . p) l] ++ (splitByPredicate p (dropWhile (not . p) l))

allEqual :: (Eq a) => [a] -> Bool
allEqual []         = True
allEqual [x]        = True
allEqual (x: y: xs) = (x == y) && allEqual (y: xs)

data Solution = Solution (Map.Map String Int) [(String, Int)]

instance Show Solution where
    show (Solution m l) = show m ++ "\n" ++ show l

max2nd :: (Ord b) => [(a, b)] -> Maybe (a, b)
max2nd []  = Nothing
max2nd [x] = Just x
max2nd (x: xs)
    | snd x >= snd (fromJust xsMax)           = Just x
    | otherwise                               = xsMax
    where
        xsMax = max2nd xs

solAnswer :: Solution -> String
solAnswer (Solution m l) =
    let
        maxk = snd $ fromJust $ max2nd $ Map.toList m
        winList = filter (\p -> snd p == maxk) (Map.toList m)
        winNames = fst $ unzip winList
        winCandidats = filter (\s -> (snd s >= maxk) && (List.elemIndex (fst s) winNames /= Nothing)) l
    in fst $ winCandidats !! 0

solAdd :: Solution -> (String, Int) -> Solution
solAdd (Solution m l) (s, v)
    | (Map.lookup s m) == Nothing = Solution (Map.insert s v m) (l ++ [(s, v)])
    | otherwise                   = Solution (Map.insert s updVal m) (l ++ [(s, updVal)])
    where
        updVal = v + (fromJust $ Map.lookup s m)

solMap :: Solution -> Map.Map String Int
solMap (Solution m l) = m

solList :: Solution -> [(String, Int)]
solList (Solution m l) = l

main = do
    sn <- getLine
    let n = read sn :: Int
    sl <- getLines n
    let (names, sscores) = unzip $ map (\x -> (x !! 0, x !! 1)) $ map words sl
    let scores = map read sscores :: [Int]
    let pairs = zip names scores
{-    if (n == 29)
        then putStrLn $ show $ drop 12 pairs
        else return () -}
    let result = foldl solAdd (Solution Map.empty []) pairs
   {- let resultl = scanl solAdd (Solution Map.empty []) pairs
    putStrLn "before"
    let shows = map (putStrLn . show) resultl
    sequence shows -}
    putStrLn $ solAnswer result

import qualified Data.Map as M

solve :: (M.Map String Int, [(String, Int)]) -> (String, Int) -> (M.Map String Int, [(String, Int)])
solve (table, records) (name, score') =
  (M.insert name score table, (name, score) : records)
  where score = score' + M.findWithDefault 0 name table

parse :: [String] -> [(String, Int)]
parse [] = []
parse (name : score : rest) = (name, read score::Int) : parse rest

main :: IO ()
main = do
  input <- getContents

  let
    (table, records) = foldl solve (M.empty, []) (parse . tail . words $ input)
    highscore = maximum $ M.elems table
    cands = M.filter (== highscore) table
    isWinner (name, score) = score >= highscore && name `M.member` cands

  putStrLn . fst . last . filter isWinner $ records

import qualified Data.Map.Strict as M
import qualified Data.List as L

type Record = (String, Int, Int) -- name, score, round (mike, 3, 1)

parseRecord:: String->Int->Record
parseRecord s round=
    (a, read b ::Int, round)
        where (a, b) = break (==' ') s

type TMap = M.Map String (Int, Int)
insertRecord:: Record->TMap->TMap
insertRecord (n, s, r) m =
    M.insertWith mergeValue n (s,r) m

mergeValue::(Int, Int)->(Int, Int)->(Int, Int)
mergeValue (score1, round1) (score2, round2)
    = (score1+score2, if score2>0 then round2 else round1)

winnerChooser:: String->(Int, Int)->Record->Record
winnerChooser name (hiScore, round) cur@(nameC, hiScoreC, roundC)
    |hiScore > hiScoreC = (name, hiScore, round)
    |hiScore == hiScoreC && round < roundC = (name, hiScore, round)
    |otherwise = cur

main=do
    c<-getContents
    let rs = zipWith parseRecord (tail.lines $ c) [1..]
    let rm = L.foldr insertRecord M.empty rs
    let winner@(name, _, _) = M.foldrWithKey winnerChooser ("", 0, 0) rm
    putStrLn name

import qualified Data.Map.Strict as M
import qualified Data.List as L

parseRecord s round=
    (a, read b ::Int, round)
        where (a, b) = break (==' ') s

insertRecord (n, s, r) m =
    M.insertWith mergeValue n (s,r) m

mergeValue (score1, round1) (score2, round2)
    = (score1+score2, if score2>0 then round2 else round1)

winnerChooser name (hiScore, round) cur@(nameC, hiScoreC, roundC)
    |hiScore > hiScoreC || hiScore == hiScoreC && round < roundC = (name, hiScore, round)
    |otherwise = cur

main=do
    c<-getContents
    let rs = zipWith parseRecord (tail.lines $ c) [1..]
    let rm = L.foldr insertRecord M.empty rs
    let winner@(name, _, _) = M.foldrWithKey winnerChooser ("", 0, 0) rm
    putStrLn name

module Main where

import Data.Function (on)
import Data.List (find, maximumBy)
import Data.Map (Map, empty, insert, filter, findWithDefault, member, assocs)

newtype Player = Player String deriving (Eq, Ord, Show)
type Score  = Int
type Round  = (Player, Score)
type Rounds = [Round]
type Totals = Map Player Score
type Play   = (Rounds, Totals)

main :: IO ()
main = interact $ showPlayer . winner . play
    where showPlayer (Player player, score) = player

winner :: Play -> Round
winner (rounds, totals) = winner where
    max         = maximum $ map snd $ assocs totals
    winners     = Data.Map.filter (== max) totals
    Just winner = find (\(player, score) -> score >= max && member player winners) (reverse rounds)

play :: String -> Play
play str = foldl addRound ([], empty) rounds
    where rounds = map readRound . tail . lines $ str

addRound :: Play -> Round -> Play
addRound (rounds, totals) (player, score) = ((player, score') : rounds, insert player score' totals)
    where score' = findWithDefault 0 player totals + score

readRound :: String -> Round
readRound str = (Player player, read score :: Score)
    where [player, score] = words str

module Main where

import Data.Function (on)
import Data.List (find, maximumBy)
import Data.Map (Map, empty, insert, filter, findWithDefault, member, assocs)

main :: IO ()
main = interact $ winner . play

winner (rounds, totals) = fst winner where
    max         = maximum $ map snd $ assocs totals
    winners     = Data.Map.filter (== max) totals
    Just winner = find (\(player, score) -> score >= max && member player winners) (reverse rounds)

play str = foldl addRound ([], empty) rounds
    where rounds = map readRound . tail . lines $ str

addRound (rounds, totals) (player, score) = ((player, score') : rounds, insert player score' totals)
    where score' = findWithDefault 0 player totals + score

readRound str = (player, read score :: Int)
    where [player, score] = words str

module Main where

import Data.Function (on)
import Data.List     (find, maximumBy)
import Data.Map      (Map, empty, insert, filter, findWithDefault, member, assocs)
import Data.Sequence ((><), (<|), (|>))
import qualified Data.Sequence as Seq
import qualified Data.Foldable as Foldable

main :: IO ()
main = interact $ winner . play

winner (rounds, totals) = fst winner where
    max         = maximum $ map snd $ assocs totals
    winners     = Data.Map.filter (== max) totals
    Just winner = find (\(player, score) -> score >= max && member player winners) (Foldable.toList rounds)

play str = foldl addRound (Seq.empty, empty) rounds
    where rounds = readRounds . tail . words $ str

addRound (rounds, totals) (player, score) = (rounds |> (player, score'), insert player score' totals)
    where score' = findWithDefault 0 player totals + score

readRounds [] = []
readRounds (player:score:rest) = (player, read score :: Int) : readRounds rest

module Main where

import qualified Data.HashTable as H
import Data.Function (on)
import Data.List (sortBy, groupBy)
import Data.Ord (comparing)

fst3 (x, y, z) = x
snd3 (x, y, z) = y
thd3 (x, y, z) = z

input [] = []
input (player:score:xs) = (player, read score :: Integer) : input xs

total = map (\x -> (foldl acc [] x, sum $ map snd3 x))
        . groupBy ((==) `on` fst3)
        . sortBy (comparing fst3)

acc [] x = [x]
acc ((x', y', z'):list) (x, y, z) = (x, y + y', z) : (x', y', z') : list

main = do
    count <- getLine
    contents <- getContents
    let steps   = input $ words contents
    let steps'  = zipWith (\(x,y) z -> (x, y, z)) steps [1..]
    let total'  = total steps'
    let max'    = maximum $ map snd total'
    let filter' = filter (\x -> snd x >= max')
    let filter''= filter (\x -> snd3 x >= max')
    let winners = filter'' $ sortBy (comparing thd3) $ concat $ map fst $ filter' total'
    putStrLn $ fst3 $ head winners

module Main where

import Data.Function (on)
import Data.List (find, maximumBy)
import Data.Map (Map, empty, insert, filter, findWithDefault, member, assocs)

main :: IO ()
main = interact $ winner . play

winner (rounds, totals) = fst winner where
    max         = maximum $ map snd $ assocs totals
    winners     = Data.Map.filter (== max) totals
    Just winner = find (\(player, score) -> score >= max && member player winners) rounds

play str = foldl addRound ([], empty) rounds
    where rounds = readRounds . tail . words $ str

addRound (rounds, totals) (player, score) = (rounds ++ [(player, score')], insert player score' totals)
    where score' = findWithDefault 0 player totals + score

readRounds [] = []
readRounds (player:score:rest) = (player, read score :: Int) : readRounds rest

module Main where

import qualified Data.HashTable as H
import Data.Function (on)
import Data.List (sortBy, groupBy)
import Data.Ord (comparing)

fst3 (x, y, z) = x
snd3 (x, y, z) = y
thd3 (x, y, z) = z

input :: [String] -> [(String, Integer)]
input [] = []
input (player:score:xs) = (player, read score) : input xs

total = map (\x -> (foldl acc [] x, sum $ map snd3 x))
        . groupBy ((==) `on` fst3)
        . sortBy (comparing fst3)

acc :: [(String, Integer, Integer)] -> (String, Integer, Integer) -> [(String, Integer, Integer)]
acc [] x = [x]
acc ((x', y', z'):list) (x, y, z) = (x, y + y', z) : (x', y', z') : list

main = do
    count <- getLine
    contents <- getContents
    let steps   = input $ words contents
    let steps'  = zipWith (\(x,y) z -> (x, y, z)) steps [1..]
    let total'  = total steps'
    let max'    = maximum $ map snd total'
    let filter' = filter (\x -> snd x >= max')
    let filter''= filter (\x -> snd3 x >= max')
    let winners = filter'' $ sortBy (comparing thd3) $ concat $ map fst $ filter' total'
    putStrLn $ fst3 $ head winners

module Main where

import Data.Function (on)
import Data.List (find, maximumBy)
import Data.Map (Map, empty, insert, filter, findWithDefault, member, assocs)

main :: IO ()
main = interact $ winner . play

winner (rounds, totals) = fst winner where
    max         = maximum $ map snd $ assocs totals
    winners     = Data.Map.filter (== max) totals
    Just winner = find (\(player, score) -> score >= max && member player winners) (reverse rounds)

play str = foldl addRound ([], empty) rounds
    where rounds = readRounds . tail . words $ str

addRound (rounds, totals) (player, score) = ((player, score') : rounds, insert player score' totals)
    where score' = findWithDefault 0 player totals + score

readRounds [] = []
readRounds (player:score:rest) = (player, read score :: Int) : readRounds rest

module Main where

import Data.Function (on)
import Data.List (sortBy, groupBy)
import Data.Ord (comparing)
import qualified Data.Map as Map
import qualified Data.Set as Set

data Round = Round {
    player :: String  ,
    score  :: Integer ,
    index  :: Integer
} deriving (Eq, Show)

input :: Integer -> [String] -> [Round]
input _ [] = []
input index (player:score:xs) = Round {player = player, score = read score :: Integer, index = index} : input (index + 1) xs

sortRounds = sortBy (comparing index)

winner rounds = head $ sortRounds $ filter (\x -> score x >= max) $ concat $ map snd story
    where
        scores     = Map.fromListWith (++) [(player round, [round]) | round <- rounds]
        totals     = Map.assocs $ Map.map (\x -> sum $ map score x) scores
        max        = maximum $ map snd totals
        candidates = Set.fromList $ map fst $ filter (\x -> snd x >= max) totals
        winners    = Map.filterWithKey (\player _ -> Set.member player candidates) scores
        story      = Map.assocs $ Map.map (\x -> foldl acc [] (sortRounds x)) winners

acc [] x = [x]
acc (x:list) y = Round {player = player x, score = score x + score y, index = index y} : x : list

main = do
    count <- getLine
    contents <- getContents
    let rounds = input 0 $ words contents
    putStrLn $ player $ winner rounds

import qualified Data.Map as Map

data Match = Match { matchPlayer :: String
                   , matchScore  :: Int
                   } deriving (Show)

readMatch :: IO Match
readMatch = do
  line <- getLine
  let (name : score : []) = words line
  return $ Match name (read score)

readMatches :: Int -> IO [Match]
readMatches 0 = return []
readMatches n = do
  match <- readMatch
  matches <- readMatches (n-1)
  return $ (match : matches)

bestScore :: [Match] -> (Int, [String])
bestScore ms = bestScore2 ms Map.empty
  where bestScore2 :: [Match] -> Map.Map String Int -> (Int, [String])
        bestScore2 [] results = (score, (Map.keys (Map.filter (==score) results)))
          where score = maximum (Map.elems results)
        bestScore2 (m:ms) results = bestScore2 ms (Map.insertWith (+) (matchPlayer m) (matchScore m) results)

firstReachingScore :: Int -> [Match] -> String
firstReachingScore score matches = f matches Map.empty
  where f :: [Match] -> Map.Map String Int -> String
        f [] results = "<no one>"
        f (m:ms) results = if (currentScore >= score)
          then matchPlayer m
          else f ms updatedResults
          where currentScore = updatedResults Map.! (matchPlayer m)
                updatedResults = (Map.insertWith (+) (matchPlayer m) (matchScore m) results)

main = do
  line <- getLine
  let n = read line
  matches <- readMatches n
  let (score, winners) = bestScore matches
  putStrLn $ firstReachingScore score (filter (\m -> (matchPlayer m) `elem` winners) matches)

-- not FINISHED on 23.11.2018
import Control.Monad
import Data.List

readInt :: String -> Int
readInt x = read x

main :: IO ()
main = do
	n <- fmap readInt getLine
	roundsRaw <- replicateM n $ do
		(name:score:_) <- fmap words getLine
		return (name, readInt score)
	let roundsNumbered = zip3 x y [1..] where
		(x, y) = unzip roundsRaw
	let roundsSorted = sortBy (\(a, _, x) -> \(b, _, y) -> compare (a, x) (b, y)) roundsNumbered
	let roundsGrouped = groupBy (\(a, _, _) -> \(b, _, _) -> a == b) roundsSorted
	let roundsSummed = map (foldl f ("", 0)) roundsGrouped where
		f (_, ss) (n, s, _) = (n, ss+s)
	let maxScore = maximum $ map snd roundsSummed
	let firstTimeSurpassed = map (foldl f ("", 0, n+1)) roundsGrouped where
		f (_, score, round) (name, s, r) = (name, s2, r2) where
			s2 = score + s
			r2 = if s2 >= maxScore then min r round else round
	let best = minimumBy (\(_, _, x) -> \(_, _, y) -> compare x y) valid where
		valid = filter (\(_, endScore, _) -> endScore==maxScore) firstTimeSurpassed
	let (bestName, _, _) = best
	putStrLn bestName

module Main where

import qualified Control.Exception as E
import qualified Data.Map as M

type Acvmts = [(Integer, String)]
type Scores = M.Map String Integer
type State  = (Acvmts, Scores)

getInt :: IO Int
getInt = readLn

processAcvmt :: Integer -> String -> Acvmts -> Acvmts
processAcvmt score name scores = (score, name) : scores

processScore :: String -> Integer -> Scores -> Scores
processScore = M.insertWith (+)

processResult :: State -> (String, Integer) -> State
processResult (acvmts, scores) (name, score) = (acvmts', scores')
  where
    scores' = processScore name score scores
    acvmts' = processAcvmt score' name acvmts
    score'  = let Just x = M.lookup name scores' in x

getWinner :: State -> String
getWinner (acvmts, scores)
  | null acvmts' = show (winners, acvmts, scores)
  | otherwise    = snd (last acvmts')
  where
    acvmts'  = filter (\(s, n) -> n `elem` winners && s >= maxScore) acvmts
    winners  = M.keys (M.filter (== maxScore) scores)
    maxScore = maximum (M.elems scores)

processInput :: Int -> String -> String
processInput n = getWinner . foldl processResult ([], M.empty) . results
  where
    results = map processLine . take n . lines

processLine :: String -> (String, Integer)
processLine s = let [name, score] = words s in (name, read score)

main = do
  n <- getInt
  E.catch (interact $ processInput n) (\msg -> print (msg :: E.SomeException))

module Main where

import qualified Data.Map as M

type Acvmts = [(Integer, String)]
type Scores = M.Map String Integer
type State  = (Acvmts, Scores)

getInt :: IO Int
getInt = readLn

processAcvmt :: Integer -> String -> Acvmts -> Acvmts
processAcvmt score name scores = (score, name) : scores

processScore :: String -> Integer -> Scores -> Scores
processScore = M.insertWith (+)

processResult :: State -> (String, Integer) -> State
processResult (acvmts, scores) (name, score) = (acvmts', scores')
  where
    scores' = processScore name score scores
    acvmts' = processAcvmt score' name acvmts
    score'  = let Just x = M.lookup name scores' in x

getWinner :: State -> String
getWinner (acvmts, scores) = snd (last acvmts')
  where
    acvmts'  = filter (\(s, n) -> n `elem` winners && s >= maxScore) acvmts
    winners  = M.keys (M.filter (== maxScore) scores)
    maxScore = maximum (M.elems scores)

processInput :: Int -> String -> String
processInput n = getWinner . foldl processResult ([], M.empty) . results
  where
    results = map processLine . take n . lines

processLine :: String -> (String, Integer)
processLine s = let [name, score] = words s in (name, read score)

main = do
  n <- getInt
  interact $ processInput n

import Control.Monad
import Data.List
import Text.Printf

findIndexIn :: [(String, Int)] -> String -> Int
findIndexIn list key =
    let keys = map (\(k, _) -> k) list
        result = elemIndex key keys
    in case result of Just index -> index
                      Nothing -> -1

findMaxElem :: (String, Int) -> [(String, Int)] -> [(String, Int)] -> (String, Int)
findMaxElem maxElem result [] = maxElem
findMaxElem maxElem current ((name, score):others) =
    let findIndexInCurrent = findIndexIn current
        index = findIndexInCurrent name
        new =
            if index >= 0
            then
                let prefix = take index current
                    suffix = drop (index + 1) current
                    update = [(name, score + (snd (current !! index)))]
                in prefix ++ update ++ suffix
            else current ++ [(name, score)]
        newMaxElem =
            if index >= 0
                then
                    let v = (score + (snd (current !! index)))
                        mx = snd maxElem
                    in if v > mx
                        then (name, v)
                        else maxElem
                else
                    let v = score
                        mx = snd maxElem
                    in if v > mx
                        then (name, v)
                        else maxElem
    in findMaxElem newMaxElem new others

readInputRow :: Int -> IO (String, Int)
readInputRow _ = do
    input <- getLine
    let [name, score_] = words input
        score = read score_ :: Int
    return (name, score)

readInputs :: IO [(String, Int)]
readInputs = do
    input <- getLine
    let n = read input
    inputs <- forM [1..n] readInputRow
    return inputs

solve :: [(String, Int)] -> String
solve = fst . (findMaxElem ("foo", (-1000000)) [])

main = do
    inputs <- readInputs
    printf "%s\n" (solve inputs)

import Control.Monad
import Data.List
import Text.Printf

findIndexIn :: [(String, Int)] -> String -> Int
findIndexIn list key =
    let keys = map (\(k, _) -> k) list
        result = elemIndex key keys
    in case result of Just index -> index
                      Nothing -> -1

calculateScore :: [(String, Int)] -> [(String, Int)] -> [(String, Int)]
calculateScore result [] = result
calculateScore current ((name, score):others) =
    let findIndexInCurrent = findIndexIn current
        index = findIndexInCurrent name
        new =
            if index >= 0
            then
                let prefix = take index current
                    suffix = drop (index + 1) current
                    update = [(name, score + (snd (current !! index)))]
                in prefix ++ update ++ suffix
            else current ++ [(name, score)]
    in calculateScore new others

getMax :: [(String, Int)] -> (String, Int)
getMax list =
    let comp = \a b -> if (snd b) > (snd a)
        then b
        else a
        initial = head list
    in foldl comp initial list

readInputRow :: Int -> IO (String, Int)
readInputRow _ = do
    input <- getLine
    let [name, score_] = words input
        score = read score_ :: Int
    return (name, score)

readInputs :: IO [(String, Int)]
readInputs = do
    input <- getLine
    let n = read input
    inputs <- forM [1..n] readInputRow
    return inputs

solve :: [(String, Int)] -> String
solve = fst . getMax . (calculateScore [])

main = do
    inputs <- readInputs
    printf "%s" (solve inputs)

import Control.Monad
import Data.List

findIndexIn :: [(String, Int)] -> String -> Int
findIndexIn list key =
    let keys = map (\(k, _) -> k) list
        result = elemIndex key keys
    in case result of Just index -> index
                      Nothing -> -1

calculateScore :: [(String, Int)] -> [(String, Int)] -> [(String, Int)]
calculateScore result [] = result
calculateScore current ((name, score):others) =
    let findIndexInCurrent = findIndexIn current
        index = findIndexInCurrent name
        new =
            if index >= 0
            then
                let prefix = take index current
                    suffix = drop (index + 1) current
                    update = [(name, score + (snd (current !! index)))]
                in prefix ++ update ++ suffix
            else current ++ [(name, score)]
    in calculateScore new others

getMax :: [(String, Int)] -> (String, Int)
getMax list =
    let comp = \a b -> if (snd b) > (snd a)
        then b
        else a
        initial = head list
    in foldl comp initial list

readInputRow :: Int -> IO (String, Int)
readInputRow _ = do
    input <- getLine
    let [name, score_] = words input
        score = read score_ :: Int
    return (name, score)

readInputs :: IO [(String, Int)]
readInputs = do
    input <- getLine
    let n = read input
    inputs <- forM [1..n] readInputRow
    return inputs

solve :: [(String, Int)] -> String
solve = fst . getMax . (calculateScore [])

main = do
    inputs <- readInputs
    print $ solve inputs

import Control.Monad
import Data.List
import Text.Printf

findIndexIn :: [(String, Int)] -> String -> Int
findIndexIn list key =
    let keys = map (\(k, _) -> k) list
        result = elemIndex key keys
    in case result of Just index -> index
                      Nothing -> -1

calculateScore :: [(String, Int)] -> [(String, Int)] -> [(String, Int)]
calculateScore result [] = result
calculateScore current ((name, score):others) =
    let findIndexInCurrent = findIndexIn current
        index = findIndexInCurrent name
        new =
            if index >= 0
            then
                let prefix = take index current
                    suffix = drop (index + 1) current
                    update = [(name, score + (snd (current !! index)))]
                in prefix ++ update ++ suffix
            else current ++ [(name, score)]
    in calculateScore new others

getMax :: [(String, Int)] -> (String, Int)
getMax list =
    let comp = \a b -> if (snd b) > (snd a)
        then b
        else a
        initial = head list
    in foldl comp initial list

readInputRow :: Int -> IO (String, Int)
readInputRow _ = do
    input <- getLine
    let [name, score_] = words input
        score = read score_ :: Int
    return (name, score)

readInputs :: IO [(String, Int)]
readInputs = do
    input <- getLine
    let n = read input
    inputs <- forM [1..n] readInputRow
    return inputs

solve :: [(String, Int)] -> String
solve = fst . getMax . (calculateScore [])

main = do
    inputs <- readInputs
    printf "%s\n" (solve inputs)

import qualified Data.ByteString.Char8 as B
import Data.Map.Strict (Map, fromListWith, toList)
import Data.List (maximumBy, minimumBy)

main = do
    n <- readLn
    lst <- sequence $ take n $ repeat B.getLine
    print $ calc n lst

calc::Int->[B.ByteString]->B.ByteString
calc n strLst = let
                    lst1 = zipWith zipFun [1..n] strLst
                      where
                        zipFun a b = (head nameScore, [(a, (read::String->Int) $ B.unpack $ last nameScore)])
                          where nameScore = B.split (toEnum $ fromEnum ' ') b

                    lst2::[(B.ByteString, [(Int,Int)])]
                    lst2 = toList $ fromListWith mapFun lst1
                      where mapFun ((newNum,newScore):_) xs@((_,oldScore):_) = (newNum, oldScore+newScore) : xs

                    getScore (_,((_, score):_)) = score
                    maxScore = getScore $ maximumBy (\a b-> compare (getScore a) (getScore b)) lst2

                    lst3 = filter (\a->getScore a == maxScore) lst2

                    getLider (a:[]) = fst a
                    getLider lst = fst $ minimumBy (\(_, num1)(_, num2)->compare num1 num2) (map mapFunc lst)
                        where mapFunc (name, numList) = (name, fst $ minimumBy (\(num1, _)(num2, _)->compare num1 num2) (filter (\(_, score)->score >= maxScore) numList))
                in
                    getLider lst3

import qualified Data.ByteString.Char8 as B
import Data.Map.Strict (Map, fromListWith, toList)
import Data.List (maximumBy, minimumBy)

main = do
    n <- readLn
    lst <- sequence $ take n $ repeat B.getLine
    B.putStrLn $ calc n lst

calc::Int->[B.ByteString]->B.ByteString
calc n strLst = let
                    lst1 = zipWith zipFun [1..n] strLst
                      where
                        zipFun a b = (head nameScore, [(a, (read::String->Int) $ B.unpack $ last nameScore)])
                          where nameScore = B.split (toEnum $ fromEnum ' ') b

                    lst2::[(B.ByteString, [(Int,Int)])]
                    lst2 = toList $ fromListWith mapFun lst1
                      where mapFun ((newNum,newScore):_)((_,oldScore):_) = [(newNum, oldScore+newScore)]

                    getScore (_,((_, score):_)) = score
                    maxScore = getScore $ maximumBy (\a b-> compare (getScore a) (getScore b)) lst2

                    lst3 = filter (\a->getScore a == maxScore) lst2

                    getLider (a:[]) = fst a
                    getLider lst = fst $ minimumBy (\(_, num1)(_, num2)->compare num1 num2) (map mapFunc lst)
                        where mapFunc (name, numList) = (name, fst $ minimumBy (\(num1, _)(num2, _)->compare num1 num2) (filter (\(_, score)->score >= maxScore) numList))
                in
                    getLider lst3

import qualified Data.Map as M
import Data.Functor ((<$>))
import Control.Monad (foldM)

solve :: (M.Map String Int, [(String, Int)]) -> Int -> IO (M.Map String Int, [(String, Int)])
solve (table, records) _ = do
  [name, score'] <- words <$> getLine
  let score = read score' + M.findWithDefault 0 name table
  return (M.insert name score table, (name, score) : records)

main :: IO ()
main = do
  n <- readLn
  (table, records) <- foldM solve (M.empty, []) [0..n-1]
  let winScore = snd $ M.findMax table
  putStrLn . fst . head . filter ((>= winScore) . snd) $ reverse records

import qualified Data.Map as M
import Data.Functor ((<$>))
import Control.Monad (foldM)

solve :: (M.Map String Int, (Int, String)) -> Int -> IO (M.Map String Int, (Int, String))
solve (table, (highscore, winner)) _ = do
  [name, score'] <- words <$> getLine

  let score = read score' + M.findWithDefault 0 name table
      newScores = if score > highscore
                  then (score, name)
                  else (highscore, winner)

  return (M.insert name score table, newScores)

main :: IO ()
main = do
  n <- readLn
  putStrLn . snd . snd =<< foldM solve (M.empty, (0, "")) [0..n-1]

import qualified Data.Map as M
import Data.Functor ((<$>))
import Control.Monad (foldM)

solve :: (M.Map String Int, [(String, Int)]) -> Int -> IO (M.Map String Int, [(String, Int)])
solve (table, records) _ = do
  [name, score'] <- words <$> getLine
  let score = read score' + M.findWithDefault 0 name table
  return (M.insert name score table, (name, score) : records)

main :: IO ()
main = do
  n <- readLn
  (table, records) <- foldM solve (M.empty, []) [0..n-1]
  let winScore = snd $ M.findMax table
  putStrLn . fst . head . filter ((== winScore) . snd) $ reverse records

main = do
	n<-getLine
	reading (read n) []

reading 0 buf = do
	putStrLn $ pars buf
reading a buf = do
	s<-getLine
	reading (a-1) $ buf++ s ++"\n"

example = "3\nmike 3\n andrew 5\nmike 2\n"
ex2="mike 3\n andrew 5\nmike 2\n"
pars::String->String
pars s = solve $map helppars $lines s

helppars::String->(String,Int)
helppars s = (name,score)
  where
  	 parts= words s
  	 name = head parts
  	 score = read $last parts

solve::[(String,Int)]->String
solve x =  check winners m
    where  res = summarize x
    	   m = maxScore $ res
    	   winners = filter ((>=m).snd) res

addScore::[(String,Int)]->(String,Int)
addScore s = (fst (head s), sum $ map snd s)

compNames::String->(String,Int)->Bool
compNames name1 (name2,score2)= name1==name2
comp::String->[(String,Int)]->[(String,Int)]
comp name s = filter (compNames name) $ s

summarize::[(String,Int)]->[(String,Int)]
summarize []= []
summarize s = [addScore (comp (name) s )] ++
            (summarize $ ( clearNames name (init s)))
            where name = fst (last s)

check s m = if snd (addScore (comp (name) s) )==m then name
	        else check (tail s) m
	        where name = fst (last s)

clearNames name s = filter (not.compNames name) s

maxScore s = maximum $ map snd s

main = do
	n<-getLine
	reading (read n) []

reading 0 buf = do
	putStrLn $ pars buf
reading a buf = do
	s<-getLine
	reading (a-1) $ buf++ s ++"\n"

example = "3\nmike 3\n andrew 5\nmike 2\n"
ex2="mike 3\n andrew 5\nmike 2\n"
pars::String->String
pars s = solve $map helppars $lines s

helppars::String->(String,Int)
helppars s = (name,score)
  where
  	 parts= words s
  	 name = head parts
  	 score = read $last parts

solve::[(String,Int)]->String
solve x =  if length winners == 1 then fst $head winners
           else simulate 0 x m
    where  res = summarize x
    	   m = maxScore $ res
    	   winners = filter ((==m).snd) res

addScore::[(String,Int)]->(String,Int)
addScore s = (fst (head s), sum $ map snd s)

compNames::String->(String,Int)->Bool
compNames name1 (name2,score2)= name1==name2
comp::String->[(String,Int)]->[(String,Int)]
comp name s = filter (compNames name) $ s

summarize::[(String,Int)]->[(String,Int)]
summarize []= []
summarize s = [addScore (comp (name) s )] ++
            (summarize $ ( clearNames name (tail s)))
            where name = fst (head s)

simulate position s m
-- берем первые position+1 строк
-- ищем в них имя из текущей позиции
-- складываем все вхождения на данный момент
-- если вдруг мы получили результат больше или равный максимуму - мы нашил победителя
   | position<length s = if snd (addScore (comp (name) (take (position+1) s) ))>=m then name
            else simulate (position+1) s m
	        where name = fst (s!!position)

clearNames name s = filter (not.compNames name) s

maxScore s = maximum $ map snd s

main = do
	n<-getLine
	reading (read n) []

reading 0 buf = do
	putStrLn $ pars buf
reading a buf = do
	s<-getLine
	reading (a-1) $ buf++ s ++"\n"

example = "3\nmike 3\n andrew 5\nmike 2\n"
ex2="mike 3\n andrew 5\nmike 2\n"
pars::String->String
pars s = solve $map helppars $lines s

helppars::String->(String,Int)
helppars s = (name,score)
  where
  	 parts= words s
  	 name = head parts
  	 score = read $last parts

solve::[(String,Int)]->String
solve x = fst $ head $ reverse $ summarize x

addScore::[(String,Int)]->(String,Int)
addScore s = (fst (head s), sum $ map snd s)

compNames::String->(String,Int)->Bool
compNames name1 (name2,score2)= name1==name2
comp::String->[(String,Int)]->[(String,Int)]
comp name s = filter (compNames name) $ s

summarize::[(String,Int)]->[(String,Int)]
summarize []= []
summarize s = [addScore (comp (name) s )] ++
            (summarize $ ( clearNames name (init s)))
            where name = fst (last s)

clearNames name s = filter (not.compNames name) s

main = do
	n<-getLine
	reading (read n) []

reading 0 buf = do
	putStrLn $ pars buf
reading a buf = do
	s<-getLine
	reading (a-1) $ buf++ s ++"\n"

example = "3\nmike 3\n andrew 5\nmike 2\n"
ex2="mike 3\n andrew 5\nmike 2\n"
pars::String->String
pars s = solve $map helppars $lines s

helppars::String->(String,Int)
helppars s = (name,score)
  where
  	 parts= words s
  	 name = head parts
  	 score = read $last parts

solve::[(String,Int)]->String
solve x =  simulate 0 x m
    where  res = summarize x
    	   m = maxScore $ res
    	   winners = filter ((>=m).snd) res

addScore::[(String,Int)]->(String,Int)
addScore s = (fst (head s), sum $ map snd s)

compNames::String->(String,Int)->Bool
compNames name1 (name2,score2)= name1==name2
comp::String->[(String,Int)]->[(String,Int)]
comp name s = filter (compNames name) $ s

summarize::[(String,Int)]->[(String,Int)]
summarize []= []
summarize s = [addScore (comp (name) s )] ++
            (summarize $ ( clearNames name (tail s)))
            where name = fst (head s)

simulate position s m
   | position<length s = if snd (addScore (comp (name) (take (position+1) s) ))==m then name
            else simulate (position+1) s m
	        where name = fst (s!!position)

clearNames name s = filter (not.compNames name) s

maxScore s = maximum $ map snd s

main = do
	n<-getLine
	reading (read n) []

reading 0 buf = do
	putStrLn $ pars buf
reading a buf = do
	s<-getLine
	reading (a-1) $ buf++ s ++"\n"

example = "3\nmike 3\n andrew 5\nmike 2\n"
ex2="mike 3\n andrew 5\nmike 2\n"
pars::String->String
pars s = solve $map helppars $lines s

helppars::String->(String,Int)
helppars s = (name,score)
  where
  	 parts= words s
  	 name = head parts
  	 score = read $last parts

solve::[(String,Int)]->String
solve x =  if length winners == 1 then fst $head winners
           else simulate 0 x m
    where  res = summarize x
    	   m = maxScore $ res
    	   winners = filter ((>=m).snd) res

addScore::[(String,Int)]->(String,Int)
addScore s = (fst (head s), sum $ map snd s)

compNames::String->(String,Int)->Bool
compNames name1 (name2,score2)= name1==name2
comp::String->[(String,Int)]->[(String,Int)]
comp name s = filter (compNames name) $ s

summarize::[(String,Int)]->[(String,Int)]
summarize []= []
summarize s = [addScore (comp (name) s )] ++
            (summarize $ ( clearNames name (tail s)))
            where name = fst (head s)

simulate position s m
-- берем первые position+1 строк
-- ищем в них имя из текущей позиции
-- складываем все вхождения на данный момент
-- если вдруг мы получили результат больше или равный максимуму - мы нашил победителя
   | position<length s = if snd (addScore (comp (name) (take (position+1) s) ))>=m then name
            else simulate (position+1) s m
	        where name = fst (s!!position)

clearNames name s = filter (not.compNames name) s

maxScore s = maximum $ map snd s

main = do
	n<-getLine
	reading (read n) []

reading 0 buf = do
	putStrLn $ pars buf
reading a buf = do
	s<-getLine
	reading (a-1) $ buf++ s ++"\n"

example = "3\nmike 3\n andrew 5\nmike 2\n"
ex2="mike 3\n andrew 5\nmike 2\n"
pars::String->String
pars s = solve $map helppars $lines s

helppars::String->(String,Int)
helppars s = (name,score)
  where
  	 parts= words s
  	 name = head parts
  	 score = read $last parts

solve::[(String,Int)]->String
solve x =  simulate 0 x m
    where  res = summarize x
    	   m = maxScore $ res
    	   winners = filter ((>=m).snd) res

addScore::[(String,Int)]->(String,Int)
addScore s = (fst (head s), sum $ map snd s)

compNames::String->(String,Int)->Bool
compNames name1 (name2,score2)= name1==name2
comp::String->[(String,Int)]->[(String,Int)]
comp name s = filter (compNames name) $ s

summarize::[(String,Int)]->[(String,Int)]
summarize []= []
summarize s = [addScore (comp (name) s )] ++
            (summarize $ ( clearNames name (tail s)))
            where name = fst (head s)

simulate position s m
   | position<length s = if snd (addScore (comp (name) (take (position+1) s) ))>=m then name
            else simulate (position+1) s m
	        where name = fst (s!!position)

clearNames name s = filter (not.compNames name) s

maxScore s = maximum $ map snd s

main = do
	n<-getLine
	reading (read n) []

reading 0 buf = do
	putStrLn $ pars buf
reading a buf = do
	s<-getLine
	reading (a-1) $ buf++ s ++"\n"

example = "3\nmike 3\n andrew 5\nmike 2\n"
ex2="mike 3\n andrew 5\nmike 2\n"
pars::String->String
pars s = solve $map helppars $lines s

helppars::String->(String,Int)
helppars s = (name,score)
  where
  	 parts= words s
  	 name = head parts
  	 score = read $last parts

solve::[(String,Int)]->String
solve x = fst $ head $ reverse $ winners
    where  res = summarize x
    	   m = maxScore $ res
    	   winners = filter ((>=m).snd) res

addScore::[(String,Int)]->(String,Int)
addScore s = (fst (head s), sum $ map snd s)

compNames::String->(String,Int)->Bool
compNames name1 (name2,score2)= name1==name2
comp::String->[(String,Int)]->[(String,Int)]
comp name s = filter (compNames name) $ s

summarize::[(String,Int)]->[(String,Int)]
summarize []= []
summarize s = [addScore (comp (name) s )] ++
            (summarize $ ( clearNames name (init s)))
            where name = fst (last s)

clearNames name s = filter (not.compNames name) s

maxScore s = maximum $ map snd s

import Data.Map as Map

main = do
	n <- fmap read getLine
	a <- mapM (\_ -> fmap (\[name, score] -> (name, read score::Int)) $ fmap words getLine) [1..n]
	putStr $ winner a

winner ((name, score):xs) = winner' xs (Map.singleton name score) name
winner' []		   scores best = best
winner' ((name, score):xs) scores best =
	let newScores = Map.insertWith (+) name score scores
	    (Just bestScore) = Map.lookup best scores
	    (Just changedScore) = Map.lookup name newScores
	    newBest = if bestScore < changedScore then name else best
	in winner' xs newScores newBest

import Data.Map as Map

main = do
	n <- fmap read getLine
	a <- mapM (\_ -> fmap (\[name, score] -> (name, read score::Int)) $ fmap words getLine) [1..n]
	print $ winner a

winner ((name, score):xs) = winner' xs (Map.singleton name score) name
winner' []		   scores best = best
winner' ((name, score):xs) scores best =
	let newScores = Map.insertWith (+) name score scores
	    (Just bestScore) = Map.lookup best scores
	    (Just changedScore) = Map.lookup name newScores
	    newBest = if bestScore < changedScore then name else best
	in winner' xs newScores newBest

import Data.Map as Map

main = do
	n <- fmap read getLine
	a <- mapM (\_ -> fmap (\[name, score] -> (name, read score::Int)) $ fmap words getLine) [1..n]
	let (scores, best)   = winner a
	    (Just bestScore) = Map.lookup best scores
	    bests 	     = Map.filter (\score -> score == bestScore) scores
	putStr $ if size bests == 1
		then fst $ head $ Map.toList bests
		else winner1 a scores bestScore Map.empty

winner ((name, score):xs) = foldl winner' (Map.singleton name score, name) xs

winner' (scores, best) (name, score) =
	let newScores = Map.insertWith (+) name score scores
	    (Just bestScore)	= Map.lookup best scores
	    (Just changedScore) = Map.lookup name newScores
	in if bestScore < changedScore
		then (newScores, name)
		else (newScores, best)

winner1 ((name, score):xs) endScores bestScore scores =
	let newScores = Map.insertWith (+) name score scores
	    (Just changedScore) = Map.lookup name newScores
	    (Just endScore) = Map.lookup name endScores
	in if endScore == bestScore && changedScore >= bestScore
		then name
		else winner1 xs endScores bestScore newScores

import Data.Map as Map

main = do
	n <- fmap read getLine
	a <- mapM (\_ -> fmap (\[name, score] -> (name, read score::Int)) $ fmap words getLine) [1..n]
	let (scores, best)   = winner a
	    (Just bestScore) = Map.lookup best scores
	    bests 	     = Map.filter (\score -> score == bestScore) scores
	putStr $ if size bests == 1
		then fst $ head $ Map.toList bests
		else winner1 a scores bestScore Map.empty

winner ((name, score):xs) = foldl winner' (Map.singleton name score, name) xs

winner' (scores, best) (name, score) =
	let newScores = Map.insertWith (+) name score scores
	    (Just bestScore)	= Map.lookup best newScores
	    (Just changedScore) = Map.lookup name newScores
	in if bestScore < changedScore
		then (newScores, name)
		else (newScores, best)

winner1 ((name, score):xs) endScores bestScore scores =
	let newScores = Map.insertWith (+) name score scores
	    (Just changedScore) = Map.lookup name newScores
	    (Just endScore) = Map.lookup name endScores
	in if endScore == bestScore && changedScore >= bestScore
		then name
		else winner1 xs endScores bestScore newScores

import Data.Map as Map

main = do
	n <- fmap read getLine
	a <- mapM (\_ -> fmap (\[name, score] -> (name, read score::Int)) $ fmap words getLine) [1..n]
	putStr $ winner a

winner ((name, score):xs) = winner' xs (Map.singleton name score) name
winner' []		   _	  best = best
winner' ((name, score):xs) scores best =
	let newScores = Map.insertWith (+) name score scores
	    (Just bestScore) = Map.lookup best newScores
	    (Just changedScore) = Map.lookup name newScores
	    newBest = if bestScore < changedScore then name else best
	in winner' xs newScores newBest

import Data.Map as Map

main = do
	n <- fmap read getLine
	a <- mapM (\_ -> fmap (\[name, score] -> (name, read score::Int)) $ fmap words getLine) [1..n]
	let (scores, best)   = winner a
	    (Just bestScore) = Map.lookup best scores
	    bests 	     = Map.filter (\score -> score == bestScore) scores
	putStr $ if size bests == 1
		then fst $ head $ Map.toList bests
		else winner1 a scores bestScore Map.empty

winner ((name, score):xs) = foldl winner' (Map.singleton name score, name) xs

winner' (scores, best) (name, score) =
	let newScores = Map.insertWith (+) name score scores
	    bestScore		= Map.fold max 0 scores
	    (Just changedScore) = Map.lookup name newScores
	in if bestScore < changedScore
		then (newScores, name)
		else (newScores, best)

winner1 ((name, score):xs) endScores bestScore scores =
	let newScores = Map.insertWith (+) name score scores
	    (Just changedScore) = Map.lookup name newScores
	    (Just endScore) = Map.lookup name endScores
	in if endScore == bestScore && changedScore >= bestScore
		then name
		else winner1 xs endScores bestScore newScores

import Data.Map as M
import Data.List as L
import Debug.Trace (trace)

type Name = String
type Score = Int
data Round = Round { roundNumber :: Int
                   , playerName :: Name
                   , playerScore :: Score
                   } deriving (Show, Eq)
instance Ord Round where
    compare r1 r2 = case scores of
        EQ -> rounds
        _ -> scores
        where scores = compare (playerScore r1) (playerScore r2)
              rounds = compare (- (roundNumber r1)) (- (roundNumber r2))
type Game = Map Name [Round]

winner :: Game -> String
winner = playerName . maximum . elems . (fmap maxScore)

maxScore :: [Round] -> Round
maxScore = maximum . (scanl combine (Round 0 "" 0))
  where combine r1 r2 = Round
                        (roundNumber r2)
                        (playerName r2)
                        ((playerScore r1) + (playerScore r2))

nextRound :: Game -> Round -> Game
nextRound game round = M.insertWith updateScore name score game
    where name = playerName round
          score = [round]
          updateScore = (++)

toRound :: (String, Int) -> Round
toRound (roundInfo, roundNum) = Round roundNum name score
    where name = takeWhile (\x -> x /= ' ') roundInfo
          score = read $ drop (length name + 1) roundInfo

runOnce :: Game -> (String, Int) -> Game
runOnce game = nextRound game . toRound

runTimes :: Int -> IO ()
runTimes n = runN 1 n M.empty

runN :: Int -> Int -> Game -> IO ()
runN round total game
    | round > total = putStrLn (winner game)
    | otherwise = do
        scoreInfo <- getLine
        let g = runOnce game (scoreInfo, round)
        runN (round + 1) total g

main :: IO ()
main = getLine >>= runTimes . read

import Data.Map as M
import Data.List as L
import Debug.Trace (trace)

type Name = String
type Score = Int
data Round = Round { roundNumber :: Int
                   , playerName :: Name
                   , playerScore :: Score
                   } deriving (Show)
type Game = Map Name (Score, Int)

winner :: Game -> String
winner game = fst win
    where win = maximumBy scoreThenRound $ M.toList game
          scoreThenRound (pn, (ps, pr)) (nn, (ns, nr))
            | ps > ns = GT
            | ps < ns = LT
            | otherwise = compare (-pr) (-nr)

----scoreThenRound (Name, (Score, Int)) (Name, (Score, Int))
--scoreThenRound (pn, (ps, pr)) (nn, (ns, nr))
--    | ps > ns = GT
--    | ps < ns = GT
--    | otherwise = compare pr nr

nextRound :: Game -> Round -> Game
nextRound game round = M.insertWith updateScore name score game
    where name = playerName round
          score = (playerScore round, roundNumber round)
          updateScore (ps, pr) (ns, nr) = (ps + ns, max pr nr)

toRound :: (String, Int) -> Round
toRound (roundInfo, roundNum) = Round roundNum name score
    where name = takeWhile (\x -> x /= ' ') roundInfo
          score = read $ drop (length name + 1) roundInfo

runOnce :: Game -> (String, Int) -> Game
runOnce game = nextRound game . toRound

runTimes :: Int -> IO ()
runTimes n = runN 1 n M.empty

runN :: Int -> Int -> Game -> IO ()
runN round total game
    | round > total = putStrLn (winner game)
    | otherwise = do
        scoreInfo <- getLine
        let g = runOnce game (scoreInfo, round)
        runN (round + 1) total g

main :: IO ()
main = getLine >>= runTimes . read

import Data.Map as M
import Data.List as L
import Control.Applicative (liftA2)
type Name = String
type Score = Int
data Round = Round { roundNumber :: Int
                   , playerName :: Name
                   , playerScore :: Score
                   } deriving (Show)
type Game = Map Name (Score, Int)

winner :: Game -> String
winner game = fst win
    where win = maximumBy scoreThenRound $ M.toList game
          scoreThenRound (pn, (ps, pr)) (nn, (ns, nr))
            | ps > ns = GT
            | ps < ns = GT
            | otherwise = compare pr nr

nextRound :: Game -> Round -> Game
nextRound game round = M.insertWith updateScore name score game
    where name = playerName round
          score = (roundNumber round, playerScore round)
          updateScore (ps, pr) (ns, nr) = (ps + ns, nr)

toRound :: (String, Int) -> Round
toRound (roundInfo, roundNum) = Round roundNum name score
    where name = takeWhile (\x -> x /= ' ') roundInfo
          score = read $ drop (length name + 1) roundInfo

runOnce :: Game -> (String, Int) -> Game
runOnce game = nextRound game . toRound

runTimes :: Int -> IO String
runTimes n = runN 1 n M.empty

runN :: Int -> Int -> Game -> IO String
runN round total game
    | round == total = return (winner game)
    | otherwise = do
        scoreInfo <- getLine
        let g = runOnce M.empty (scoreInfo, round)
        runN (round + 1) total g

main :: IO String
main = getLine >>= runTimes . read

import Data.Map as Map

type Score = Int
data Standing = Standing { score :: Score
                         , maxPt :: Score
                         , maxPtRound :: Int
                         , playerName :: String
                         } deriving (Show, Eq)

instance Ord Standing where
    compare s1 s2
      | (maxPt s1) == (maxPt s2) =
            compare (- (maxPtRound s1)) (- (maxPtRound s2))
      | otherwise = compare (maxPt s1) (maxPt s2)

data Round = Round { roundNumber :: Int
                   , player :: String
                   , roundScore :: Score
                   } deriving (Show)
type Game = Map String Standing

firstRound :: Round -> Standing
firstRound r = Standing
               (roundScore r)
               (roundScore r)
               (roundNumber r)
               (player r)

toRound :: (String, Int) -> Round
toRound (roundInfo, roundNum) = Round roundNum name score
    where name = takeWhile (\x -> x /= ' ') roundInfo
          score = read $ drop (length name + 1) roundInfo

{-
  Given the current Standing of a user,
  play a round, and update the Standing.
-}
userPlayRound :: Round -> Standing -> Standing
userPlayRound r st = Standing
                     newScore
                     newMaxPoints
                     newMaxPointsRound
                     (player r)
  where newScore = (score st) + (roundScore r)
        hasNewMax = (roundScore r) > 0
        newMaxPoints = if hasNewMax then newScore else (score st)
        newMaxPointsRound = if hasNewMax then (roundNumber r)  else (maxPtRound st)
{-
  Plays a Round of the game and update the Game state
-}
playRound :: Round -> Game -> Game
playRound r g = case Map.member (player r) g of
    True -> Map.adjust (userPlayRound r) (player r) g
    False -> Map.insert (player r) (firstRound r) g

main :: IO ()
main = do
    input <- getLine
    final <- playN $ read input
    putStrLn $ winner final

winner :: Game -> String
winner = playerName . maximum . elems

playN :: Int -> IO Game
playN n = playOne 1 n Map.empty
    where playOne r n g
            | r > n = return g
            | otherwise = do
                input <- getLine
                playOne (r + 1) n $ playRound (toRound (input, r)) g

import Data.Map as M
import Data.Monoid as Monoid
import Data.List as L
import Debug.Trace (trace)

type Name = String
type Score = Int
data Round = Round { roundNumber :: Int
                   , playerName :: Name
                   , playerScore :: Score
                   } deriving (Show, Eq)
type Game = Map Name [Round]

instance Monoid Round where
    mempty = Round 0 "" 0
    mappend r1 r2 = Round
                    (max (roundNumber r1) (roundNumber r2))
                    (playerName r2)
                    ((playerScore r1) + (playerScore r2))

instance Ord Round where
    compare r1 r2 = case scores of
        EQ -> rounds
        _ -> scores
        where scores = compare (playerScore r1) (playerScore r2)
              rounds = compare (- (roundNumber r1)) (- (roundNumber r2))

winner :: Game -> String
winner = playerName . maximum . elems . (fmap maxScore)

maxScore :: [Round] -> Round
maxScore = maximum . (scanr1 mappend)

nextRound :: Game -> Round -> Game
nextRound game round = M.insertWith (++) name [round] game
    where name = playerName round

toRound :: (String, Int) -> Round
toRound (roundInfo, roundNum) = Round roundNum name score
    where name = takeWhile (\x -> x /= ' ') roundInfo
          score = read $ drop (length name + 1) roundInfo

runN :: Int -> Int -> Game -> IO ()
runN round total game
    | round > total = putStrLn (winner game)
    | otherwise = do
        scoreInfo <- getLine
        let g = nextRound game $ toRound (scoreInfo, round)
        runN (round + 1) total g

runTimes :: Int -> IO ()
runTimes n = runN 1 n M.empty

main :: IO ()
main = getLine >>= runTimes . read

import Data.Map as Map

type Score = Int
data Standing = Standing { score :: Score
                         , maxPt :: Score
                         , maxPtRound :: Int
                         , playerName :: String
                         } deriving (Show, Eq)

instance Ord Standing where
    compare s1 s2
      | (maxPt s1) == (maxPt s2) =
            compare (- (maxPtRound s1)) (- (maxPtRound s2))
      | otherwise = compare (maxPt s1) (maxPt s2)

data Round = Round { roundNumber :: Int
                   , player :: String
                   , roundScore :: Score
                   } deriving (Show)
type Game = Map String Standing

firstRound :: Round -> Standing
firstRound r = Standing
               (roundScore r)
               (roundScore r)
               (roundNumber r)
               (player r)

toRound :: (String, Int) -> Round
toRound (roundInfo, roundNum) = Round roundNum name score
    where name = takeWhile (\x -> x /= ' ') roundInfo
          score = read $ drop (length name + 1) roundInfo

{-
  Given the current Standing of a user,
  play a round, and update the Standing.
-}
userPlayRound :: Round -> Standing -> Standing
userPlayRound r st = Standing
                     newScore
                     newMaxPoints
                     newMaxPointsRound
                     (player r)
  where newScore = (score st) + (roundScore r)
        hasNewMax = (roundScore r) > 0
        newMaxPoints = if hasNewMax then newScore else (score st)
        newMaxPointsRound = if hasNewMax then (roundNumber r)  else (maxPtRound st)
{-
  Plays a Round of the game and update the Game state
-}
playRound :: Round -> Game -> Game
playRound r g = case Map.member (player r) g of
    True -> Map.adjust (userPlayRound r) (player r) g
    False -> Map.insert (player r) (firstRound r) g

main :: IO ()
main = do
    input <- getLine
    final <- playN $ read input
    print $ winner final

winner :: Game -> String
winner = playerName . maximum . elems

playN :: Int -> IO Game
playN n = playOne 1 n Map.empty
    where playOne r n g
            | r > n = return g
            | otherwise = do
                input <- getLine
                playOne (r + 1) n $ playRound (toRound (input, r)) g

import Data.Map as M
import Data.List as L
import Control.Applicative (liftA2)
type Name = String
type Score = Int
data Round = Round { roundNumber :: Int
                   , playerName :: Name
                   , playerScore :: Score
                   } deriving (Show)
type Game = Map Name (Score, Int)

winner :: Game -> String
winner game = fst win
    where win = maximumBy scoreThenRound $ M.toList game
          scoreThenRound (pn, (ps, pr)) (nn, (ns, nr))
            | ps > ns = GT
            | ps < ns = GT
            | otherwise = compare pr nr

nextRound :: Game -> Round -> Game
nextRound game round = M.insertWith updateScore name score game
    where name = playerName round
          score = (roundNumber round, playerScore round)
          updateScore (ps, pr) (ns, nr) = (ps + ns, nr)

toRound :: (String, Int) -> Round
toRound (roundInfo, roundNum) = Round roundNum name score
    where name = takeWhile (\x -> x /= ' ') roundInfo
          score = read $ drop (length name + 1) roundInfo

runOnce :: Game -> (String, Int) -> Game
runOnce game = nextRound game . toRound

runTimes :: Int -> IO ()
runTimes n = runN 1 n M.empty

runN :: Int -> Int -> Game -> IO ()
runN round total game
    | round == total = putStrLn (winner game)
    | otherwise = do
        scoreInfo <- getLine
        let g = runOnce M.empty (scoreInfo, round)
        runN (round + 1) total g

main :: IO ()
main = getLine >>= runTimes . read

import Data.Map as Map
import Debug.Trace

type Score = Int
data Standing = Standing { score :: Score
                         , maxPt :: Score
                         , maxPtRound :: Int
                         , playerName :: String
                         } deriving (Show, Eq)

instance Ord Standing where
    compare s1 s2
      | (maxPt s1) == (maxPt s2) =
            compare (- (maxPtRound s1)) (- (maxPtRound s2))
      | otherwise = compare (maxPt s1) (maxPt s2)

data Round = Round { roundNumber :: Int
                   , player :: String
                   , roundScore :: Score
                   } deriving (Show)
type Game = Map String Standing

firstRound :: Round -> Standing
firstRound r = Standing
               (roundScore r)
               (roundScore r)
               (roundNumber r)
               (player r)

toRound :: (String, Int) -> Round
toRound (roundInfo, roundNum) = Round roundNum name score
    where name = takeWhile (\x -> x /= ' ') roundInfo
          score = read $ drop (length name + 1) roundInfo

{-
  Given the current Standing of a user,
  play a round, and update the Standing.
-}
userPlayRound :: Round -> Standing -> Standing
userPlayRound r st = Standing
                     newScore
                     newMaxPoints
                     newMaxPointsRound
                     (player r)
  where newScore = (score st) + (roundScore r)
        hasNewMax = newScore > (maxPt st)
        newMaxPoints = if hasNewMax then newScore else (maxPt st)
        newMaxPointsRound = if hasNewMax then (roundNumber r)  else (maxPtRound st)
{-
  Plays a Round of the game and update the Game state
-}
playRound :: Round -> Game -> Game
playRound r g = case Map.member (player r) g of
    True -> Map.adjust (userPlayRound r) (player r) g
    False -> Map.insert (player r) (firstRound r) g

main :: IO ()
main = do
    input <- getLine
    final <- playN $ read input
    putStrLn $ winner final

winner :: Game -> String
winner g = playerName . maximum . elems $ g

playN :: Int -> IO Game
playN n = playOne 1 n Map.empty
    where playOne r n g
            | r > n = return g
            | otherwise = do
                input <- getLine
                playOne (r + 1) n $ playRound (toRound (input, r)) g

import Data.Map as M
import Data.Monoid as Monoid
import Data.List as L
import Debug.Trace (trace)

type Name = String
type Score = Int
data Round = Round { roundNumber :: Int
                   , playerName :: Name
                   , playerScore :: Score
                   } deriving (Show, Eq)
type Game = Map Name [Round]

instance Monoid Round where
    mempty = Round 0 "" 0
    mappend r1 r2 = Round
                    (max (roundNumber r1) (roundNumber r2))
                    (playerName r2)
                    ((playerScore r1) + (playerScore r2))

instance Ord Round where
    compare r1 r2 = case scores of
        EQ -> rounds
        _ -> scores
        where scores = compare (playerScore r1) (playerScore r2)
              rounds = compare (- (roundNumber r1)) (- (roundNumber r2))

winner :: Game -> String
winner = playerName . maximum . elems . (fmap maxScore)

maxScore :: [Round] -> Round
maxScore = maximum . (scanl mappend mempty)

nextRound :: Game -> Round -> Game
nextRound game round = M.insertWith (++) name [round] game
    where name = playerName round

toRound :: (String, Int) -> Round
toRound (roundInfo, roundNum) = Round roundNum name score
    where name = takeWhile (\x -> x /= ' ') roundInfo
          score = read $ drop (length name + 1) roundInfo

runN :: Int -> Int -> Game -> IO ()
runN round total game
    | round > total = putStrLn (winner game)
    | otherwise = do
        scoreInfo <- getLine
        let g = nextRound game $ toRound (scoreInfo, round)
        runN (round + 1) total g

runTimes :: Int -> IO ()
runTimes n = runN 1 n M.empty

main :: IO ()
main = getLine >>= runTimes . read

-- Codeforces 2A
import qualified Data.Map as Map
import Data.Maybe
import Data.List.Split
import Control.Monad

type Score = Int
type Name = String

compareScore :: Map.Map Name Score -> Maybe Name -> Maybe Name -> Maybe Name
compareScore _ Nothing Nothing = Nothing
compareScore _ (Just n) Nothing = Just n
compareScore _ Nothing (Just n) = Just n
compareScore map (Just a) (Just b)
    | isNothing scoreA && isNothing scoreB = Nothing
    | isNothing scoreA = Just b
    | isNothing scoreB = Just a
    | fromJust scoreA < fromJust scoreB = Just b
    | otherwise       = Just a
    where scoreA = Map.lookup a map
          scoreB = Map.lookup b map

updateValue :: Score -> Maybe Score -> Maybe Score
updateValue x Nothing = Just x
updateValue x (Just y) = Just (x + y)

findMax :: [(Name, Score)] -> Map.Map Name Score -> Maybe Name -> Maybe Name
findMax [] map older = older
findMax (x:xs) map older = findMax xs newMap winner
    where name = fst x
          score = snd x
          newMap = Map.alter (updateValue score) name map
          winner = compareScore newMap older (Just name)

toRecord :: String -> (Name, Score)
toRecord string = (name, score)
    where parts = splitOn " " string
          name = parts !! 0
          score = read (parts !! 1)

main :: IO ()
main = do
    linesToRead <- getLine
    input <- getContents
    let inputs = lines input
    let records = map toRecord inputs
    let result = findMax records (Map.empty :: Map.Map Name Score) Nothing
    putStrLn $ id (fromJust result)

-- Codeforces 2A
import qualified Data.Map as Map
import Data.Maybe
import Data.List.Split
import Control.Monad

type Score = Integer
type Name = String

createMap :: [(Name, Score)] -> Map.Map Name Score
createMap list = Map.fromListWith (+) list

findMaxVal :: Map.Map Name Score -> Score
findMaxVal map = maximum (Map.elems map)

filterPlayers :: Map.Map Name Score -> Score -> [Name]
filterPlayers map score = filter prediate (Map.keys map)
    where prediate = (\key -> fromJust (Map.lookup key map) == score)

findFirst :: [(Name, Score)] -> Map.Map Name Score -> [Name] -> Score -> Name
findFirst [] _ list __ = list !! 0
findFirst (x:xs) map queue maxScore = findFirst xs newMap newQueue maxScore
    where name = fst x
          score = snd x
          newMap = Map.alter (updateValue score) name map
          oldScore = fromMaybe (maxScore - 1) (Map.lookup name map)
          newScore = fromJust (Map.lookup name newMap)
          newQueue
            | newScore < maxScore = [x | x <- queue, x /= name] -- become lesser
            | oldScore >= maxScore = queue -- already greater
            | otherwise = queue ++ [name]

updateValue :: Score -> Maybe Score -> Maybe Score
updateValue x Nothing = Just x
updateValue x (Just y) = Just (x + y)

toRecord :: String -> (Name, Score)
toRecord string = (name, score)
    where strings = splitOn " " string
          name = strings !! 0
          score = read $ strings !! 1

main :: IO ()
main = do
    linesToRead <- getLine
    input <- getContents
    let inputs = take (read linesToRead) (lines input)
    let records = map toRecord inputs
    let maxVal = findMaxVal (createMap records)
    let result = findFirst records Map.empty [] maxVal
    putStrLn $ id (result)

-- Codeforces 2A
import qualified Data.Map as Map
import Data.Maybe
import Data.List.Split
import Control.Monad

type Score = Int
type Name = String

compareScore :: Map.Map Name Score -> Maybe Name -> Maybe Name -> Maybe Name
compareScore _ Nothing Nothing = Nothing
compareScore _ (Just n) Nothing = Just n
compareScore _ Nothing (Just n) = Just n
compareScore map (Just a) (Just b)
    | scoreA < scoreB = Just b
    | otherwise       = Just a
    where scoreA = fromMaybe (0 :: Score) (Map.lookup a map)
          scoreB = fromMaybe (0 :: Score) (Map.lookup b map)

updateValue :: Score -> Maybe Score -> Maybe Score
updateValue x Nothing = Just x
updateValue x (Just y) = Just (x + y)

findMax :: [(Name, Score)] -> Map.Map Name Score -> Maybe Name -> Maybe Name
findMax [] map older = older
findMax (x:xs) map older = findMax xs newMap winner
    where name = fst x
          score = snd x
          newMap = Map.alter (updateValue score) name map
          winner = compareScore newMap older (Just name)

toRecord :: String -> (Name, Score)
toRecord string = (name, score)
    where parts = splitOn " " string
          name = parts !! 0
          score = read (parts !! 1)

main :: IO ()
main = do
    linesToRead <- getLine
    input <- getContents
    let inputs = lines input
    let records = map toRecord inputs
    let result = findMax records (Map.empty :: Map.Map Name Score) Nothing
    print (fromJust result)

-- Codeforces 2A
import qualified Data.Map as Map
import Data.Maybe
import Data.List.Split
import Control.Monad

type Score = Integer
type Name = String

compareScore :: Map.Map Name Score -> Maybe Name -> Maybe Name -> Maybe Name
compareScore _ Nothing Nothing = Nothing
compareScore _ (Just n) Nothing = Just n
compareScore _ Nothing (Just n) = Just n
compareScore map (Just a) (Just b)
    | isNothing scoreA && isNothing scoreB = Nothing
    | isNothing scoreA = Just b
    | isNothing scoreB = Just a
    | fromJust scoreA < fromJust scoreB = Just b
    | otherwise       = Just a
    where scoreA = Map.lookup a map
          scoreB = Map.lookup b map

updateValue :: Score -> Maybe Score -> Maybe Score
updateValue x Nothing = Just x
updateValue x (Just y) = Just (x + y)

findMax :: [(Name, Score)] -> Map.Map Name Score -> Maybe Name -> Maybe Name
findMax [] map older = older
findMax (x:xs) map older = findMax xs newMap winner
    where name = fst x
          score = snd x
          newMap = Map.alter (updateValue score) name map
          winner = compareScore newMap older (Just name)

toRecord :: String -> (Name, Score)
toRecord string = (name, score)
    where parts = splitOn " " string
          name = parts !! 0
          score = read (parts !! 1)

main :: IO ()
main = do
    linesToRead <- getLine
    input <- getContents
    let inputs = lines input
    let records = map toRecord inputs
    let result = findMax records (Map.empty :: Map.Map Name Score) Nothing
    putStrLn $ id (fromJust result)

-- Codeforces 2A
import qualified Data.Map as Map
import Data.Maybe
import Data.List.Split
import Control.Monad

type Score = Integer
type Name = String

createMap :: [(Name, Score)] -> Map.Map Name Score
createMap list = Map.fromListWith (+) list

findMaxVal :: Map.Map Name Score -> Score
findMaxVal map = maximum (Map.elems map)

filterPlayers :: Map.Map Name Score -> Score -> [Name]
filterPlayers map score = filter prediate (Map.keys map)
    where prediate = (\key -> fromJust (Map.lookup key map) == score)

findFirst :: [(Name, Score)] -> Map.Map Name Score -> Score -> Name
findFirst [] _ _ = ""
findFirst (x:xs) map maxScore = winner
    where name = fst x
          score = snd x
          newMap = Map.alter (updateValue score) name map
          newScore = fromJust (Map.lookup name newMap)
          winner
            | newScore >= maxScore = name
            | otherwise = findFirst xs newMap maxScore

updateValue :: Score -> Maybe Score -> Maybe Score
updateValue x Nothing = Just x
updateValue x (Just y) = Just (x + y)

toRecord :: String -> (Name, Score)
toRecord string = (name, score)
    where strings = splitOn " " string
          name = strings !! 0
          score = read $ strings !! 1

main :: IO ()
main = do
    linesToRead <- getLine
    input <- getContents
    let inputs = take (read linesToRead) (lines input)
    let records = map toRecord inputs
    let maxVal = findMaxVal (createMap records)
    let result = findFirst records Map.empty maxVal
    putStrLn $ id (result)

-- Codeforces 2A
import qualified Data.Map as Map
import Data.Maybe
import Data.List.Split
import Control.Monad

type Score = Int
type Name = String

compareScore :: Map.Map Name Score -> Maybe Name -> Maybe Name -> Maybe Name
compareScore _ Nothing Nothing = Nothing
compareScore _ (Just n) Nothing = Just n
compareScore _ Nothing (Just n) = Just n
compareScore map (Just a) (Just b)
    | scoreA < scoreB = Just b
    | otherwise       = Just a
    where scoreA = fromMaybe (0 :: Score) (Map.lookup a map)
          scoreB = fromMaybe (0 :: Score) (Map.lookup b map)

updateValue :: Score -> Maybe Score -> Maybe Score
updateValue x Nothing = Just x
updateValue x (Just y) = Just (x + y)

findMax :: [(Name, Score)] -> Map.Map Name Score -> Maybe Name -> Maybe Name
findMax [] map older = older
findMax (x:xs) map older = findMax xs newMap winner
    where name = fst x
          score = snd x
          newMap = Map.alter (updateValue score) name map
          winner = compareScore newMap older (Just name)

toRecord :: String -> (Name, Score)
toRecord string = (name, score)
    where parts = splitOn " " string
          name = parts !! 0
          score = read (parts !! 1)

main :: IO ()
main = do
    linesToRead <- getLine
    input <- getContents
    let inputs = lines input
    let records = map toRecord inputs
    let result = findMax records (Map.empty :: Map.Map Name Score) Nothing
    putStrLn $ id (fromJust result)

import Control.Monad
import Data.List
import qualified Data.Map as M

data LogEntry = LogEntry String Int
	deriving (Eq, Show)

score (LogEntry _ v) = v
name (LogEntry n _) = n

instance Ord LogEntry where
	(<=) (LogEntry _ a) (LogEntry _ b) = a <= b

getInput = do
	n <- (liftM read) getLine :: IO Int
	lines <- sequence $ replicate n getLine
	return $ map parseEntry lines

parseEntry s = LogEntry name deltaScore
	where
		parts = words s
		name = head parts
		deltaScore = read $ parts !! 1

foldLog :: [LogEntry] -> [LogEntry]
foldLog log = snd $ mapAccumL foldEntry M.empty log
	where
		foldEntry :: M.Map String Int -> LogEntry -> (M.Map String Int, LogEntry)
		foldEntry m (LogEntry name deltaScore) = (newMap, LogEntry name newScore)
			where
				newScore = deltaScore + M.findWithDefault 0 name m
				newMap = M.insert name newScore m

winner foldedLog = name $ head $ filter (\(LogEntry _ value) -> value >= maxValue) foldedLog
	where
		(LogEntry _ maxValue) = maximum foldedLog

main = do
	log <- getInput
	putStrLn $ winner $ foldLog log

{-# OPTIONS_GHC -O2 -XNoMonomorphismRestriction #-}
{-# LANGUAGE BangPatterns #-}
{-(c) gorlum0 [at] gmail.com-}
import qualified Data.Map as M

splitEvery _ [] = []
splitEvery n xs = ys : splitEvery n xs'
    where (ys, xs') = splitAt n xs

winner rounds = f M.empty rounds'
    where
    rounds' = [(k, read v) | [k, v] <- splitEvery 2 rounds]

    game = M.fromListWith (+) rounds'
    m = maximum [v | (_, v) <- M.toList game]

    f :: M.Map String Int -> [(String, Int)] -> String
    f game ((k,v):xs)
        | n == m    = k
        | otherwise = f game' xs
        where game' = M.insertWith (+) k v game
              Just n = M.lookup k game'

body :: [String] -> [String]
body [] = []
body (n:xs) = winner ys : body xs'
    where
    n' = read n
    (ys, xs') = splitAt (n'*2) xs

main = do
    ws <- words `fmap` getContents
    mapM_ putStrLn $ body ws

{-# OPTIONS_GHC -O2 -XNoMonomorphismRestriction #-}
{-# LANGUAGE BangPatterns #-}
{-(c) gorlum0 [at] gmail.com-}
import qualified Data.Map as M

splitEvery _ [] = []
splitEvery n xs = ys : splitEvery n xs'
    where (ys, xs') = splitAt n xs

winner rounds = f M.empty rounds'
    where
    rounds' = [(k, read v) | [k, v] <- splitEvery 2 rounds]

    game = M.fromListWith (+) rounds'
    m = maximum [v | (_, v) <- M.toList game]

    f :: M.Map String Int -> [(String, Int)] -> String
    f game ((k,v):xs)
        | n >= m    = k
        | otherwise = f game' xs
        where game' = M.insertWith (+) k v game
              Just n = M.lookup k game'

body :: [String] -> [String]
body [] = []
body (n:xs) = winner ys : body xs'
    where
    n' = read n
    (ys, xs') = splitAt (n'*2) xs

main = do
    ws <- words `fmap` getContents
    mapM_ putStrLn $ body ws

import qualified Data.Map as M

split [] = []
split (x:y:xs) = (x, read y :: Int) : split xs

findMax x = let r = M.fromListWith (+) x in maximum $ M.elems r

verify ((k,v0):xs) m0 n = if v1 == n then k else verify xs m1 n
    where m1 = M.insertWith (+) k v0 m0
          v1 = m1 M.! k

main = do
    s <- getContents
    let l = split . tail . words $ s
    putStrLn $ verify l M.empty (findMax l)

import qualified Data.Map as M
import Data.Maybe

split [] = []
split (x:y:xs) = (x, read y :: Int) : split xs

candidates x =
    let r = M.fromListWith (+) x
        m = maximum $ M.elems r
    in M.filter (== m) r

verify ((k,v0):xs) m0
    | v1 == Nothing     = verify xs m0
    | fromJust v1 == v0 = k
    | otherwise         = verify xs (M.insertWith (+) k (-v0) m0)
    where v1 = M.lookup k m0

main = do
    s <- getContents
    let l = split . tail . words $ s
    putStrLn $ verify l $ candidates l

import qualified Data.Map as M

split [] = []
split (x:y:xs) = (x, read y :: Int) : split xs

candidates x =
    let r = M.fromListWith (+) x
        m = maximum $ M.elems r
    in M.filter (== m) r

verify ((k,v0):xs) m0 = if v1 == 0 then k else verify xs m1
    where m1 = M.insertWith (+) k (-v0) m0
          v1 = m1 M.! k

main = do
    s <- getContents
    let l = split . tail . words $ s
    putStrLn $ verify l $ candidates l

split [] = []
split (n:s:xs) = (n, read s :: Int) : (split xs)

solve (x:xs) = fst (foldl1 better (split xs))
    where better acc@(n1, s1) y@(n2, s2) = if (s1 >= s2) then acc else y

main = interact $ id . solve . words

-- Codeforce 2A

import Data.Maybe
import qualified Data.Map as Map

main :: IO ()
main = do
    getLine
    getContents >>= putStrLn . solve . map ((\[name, score] -> (name, (read score) :: Int)) . words) . lines

solve :: [(String, Int)] -> String
solve xs = winner Map.empty xs $ mscore xs

winner :: Map.Map String Int -> [(String, Int)] -> Int -> String
winner m ((name, score):xs) goal
    | val >= goal = name
    | otherwise = winner nxt xs goal
    where
        nxt = Map.insertWith (+) name score m
        val = fromJust $ Map.lookup name nxt

mscore :: [(String, Int)] -> Int
mscore = maximum . Map.elems . Map.fromListWith (+)

import qualified Data.Map.Lazy as M
import Data.Maybe

main :: IO ()
main = interact $ show . solve . map (read :: String -> Point) . tail . lines

data Point = Point String Int

instance Show Point where
  show (Point name _) = name

instance Read Point where
  readsPrec _ s = let [name, score] = words s in [(Point name (read score), "")]

instance Ord Point where
  (<=) (Point _ x) (Point _ y) = (<=) x y

instance Eq Point where
  (==) (Point _ x) (Point _ y) = (==) x y

(+++) :: Point -> Point -> Point
(+++) (Point _ x) (Point n y) = Point n (x + y)

scoreOfPoint :: Point -> Int
scoreOfPoint (Point _ x) = x

solve :: [Point] -> Point
solve pps = snd $ head $ filter (\(_, pp) -> pp >= maxpp) scores
  where maxpp = maximum $ map snd $ M.toList $ fst $ last scores
        scores = scanl go (M.empty, Point "" (scoreOfPoint $ minimum pps)) pps
        go (m, _) pp@(Point name _) =
          let newhm = M.insertWith (+++) name pp m
              in (newhm, fromJust $ M.lookup name newhm)

import qualified Data.Map as M
import Control.Arrow (second)
import Data.List (maximumBy)
import Data.Function (on)

main :: IO ()
main = getContents >>= putStrLn . solve . map (second read . toTuple . words) . tail . lines

solve :: [(String, Integer)] -> String
solve xs = fst $ head [ maximumBy (compare `on` snd) $ M.toList m | m <- ms, s `elem` M.elems m ]
  where ms = scanl (flip $ uncurry $ M.insertWith (+)) M.empty xs
        s = maximum (M.elems (last ms))

toTuple :: [a] -> (a, a)
toTuple xs = (head xs, xs !! 1)

import qualified Data.Map.Lazy as M
import Data.Maybe

main :: IO ()
main = interact $ show . solve . map read . tail . lines

data Point = Point String Integer

instance Show Point where
  show (Point name _) = name

instance Read Point where
  readsPrec _ s = let [name, score] = words s in [(Point name (read score), "")]

instance Eq Point where
  (==) (Point _ x) (Point _ y) = (==) x y

instance Ord Point where
  (<=) (Point _ x) (Point _ y) = (<=) x y

(+++) :: Point -> Point -> Point
(+++) (Point _ x) (Point n y) = Point n (x + y)

scoreOfPoint :: Point -> Integer
scoreOfPoint (Point _ x) = x

solve :: [Point] -> Point
solve pps = snd $ head $ filter (\(_, pp) -> pp >= maxpp) scores
  where maxpp = maximum $ map snd $ M.toList $ fst $ last scores
        scores = scanl go (M.empty, Point "" 0) pps
        go (m, _) pp@(Point name _) =
          let newhm = M.insertWith (+++) name pp m
              in (newhm, fromJust $ M.lookup name newhm)

import qualified Data.Map.Lazy as M
import Data.Maybe

main :: IO ()
main = interact $ show . solve . map (read :: String -> Point) . tail . lines

data Point = Point String Int

instance Show Point where
  show (Point name _) = name

instance Read Point where
  readsPrec _ s = let [name, score] = words s in [(Point name (read score), "")]

instance Ord Point where
  (<=) (Point _ x) (Point _ y) = (<=) x y

instance Eq Point where
  (==) (Point _ x) (Point _ y) = (==) x y

(+++) :: Point -> Point -> Point
(+++) (Point _ x) (Point n y) = Point n (x + y)

solve :: [Point] -> Point
solve pps = snd $ head $ filter (\(_, pp) -> pp >= maxpp) lastScore
  where maxpp = maximum $ map snd $ M.toList $ fst $ last lastScore
        lastScore = scanl go (M.empty, Point "" 0) pps
        go (m, _) pp@(Point name _) =
          let newhm = M.insertWith (+++) name pp m
              in (newhm, fromJust $ M.lookup name newhm)

import qualified Data.Map.Lazy as M
import Data.Maybe

main :: IO ()
main = interact $ show . solve . map read . tail . lines

data Point = Point String Int

instance Show Point where
  show (Point name _) = name

instance Read Point where
  readsPrec _ s = let [name, score] = words s in [(Point name (read score), "")]

instance Eq Point where
  (==) (Point _ x) (Point _ y) = (==) x y

instance Ord Point where
  (<=) (Point _ x) (Point _ y) = (<=) x y

(+++) :: Point -> Point -> Point
(+++) (Point _ x) (Point n y) = Point n (x + y)

scoreOfPoint :: Point -> Int
scoreOfPoint (Point _ x) = x

solve :: [Point] -> Point
solve pps = snd $ head $ filter (\(_, pp) -> pp >= maxpp) scores
  where maxpp = maximum $ map snd $ M.toList $ fst $ last scores
        scores = scanl go (M.empty, Point "" 0) pps
        go (m, _) pp@(Point name _) =
          let newhm = M.insertWith (+++) name pp m
              in (newhm, fromJust $ M.lookup name newhm)

import qualified Data.Map.Lazy as M
import Data.Maybe

main :: IO ()
main = interact $ show . solve . map (read :: String -> Point) . tail . lines

data Point = Point String Int

instance Show Point where
  show (Point name _) = name

instance Read Point where
  readsPrec _ s = let [name, score] = words s in [(Point name (read score), "")]

instance Ord Point where
  (<=) (Point _ x) (Point _ y) = (<=) x y

instance Eq Point where
  (==) (Point _ x) (Point _ y) = (==) x y

(+++) :: Point -> Point -> Point
(+++) (Point _ x) (Point n y) = Point n (x + y)

solve :: [Point] -> Point
solve pps = snd $ head $ filter (\(_, pp) -> pp == maxpp) lastScore
  where maxpp = maximum $ map snd $ M.toList $ fst $ last lastScore
        lastScore = scanl go (M.empty, Point "" 0) pps
        go (m, _) pp@(Point name _) =
          let newhm = M.insertWith (+++) name pp m
              in (newhm, fromJust $ M.lookup name newhm)

import qualified Data.Map as M
import Data.List

main = putStrLn . solve . map words . tail . lines =<< getContents
solve = fst . M.foldrWithKey h ("",(minBound::Int,1000)) . fst . foldl' f (M.empty,0)
    where f (m,n) [rw,rs] = m' `seq` n' `seq` (m',n')
              where m' = M.insertWith' g rw (read rs,n) m
                    n' = n + 1
          g (s,t) (ps,_) = s' `seq` (s',t) where s' = s+ps
          h n (s,t) (gw,(gs,gt)) = if s > gs && t > gt
                                   then (n,(s,t))
                                   else (gw,(gs,gt))

import Data.Maybe
import Data.List
import qualified Data.Map as M
import Control.Monad

main = putStrLn . solve . map words . tail . lines =<< getContents
solve s = case ws of
            [w1] -> w1
            _ -> head $ catMaybes $ map snd game
    where f (a,_) [rw,rs] = a' `seq`
                            ( a', guard (rw `elem` ws) >>
                                  M.lookup rw a' >>=
                                  guard . (>=m) >>
                                  return rw )
              where a' = M.insertWith (+) rw (read rs) a
          game = scanl f (M.empty,Nothing) s
          final = fst (last game)
          m = snd (M.findMax final)
          ws = M.keys (M.filter (==m) final)

import Data.List
main = putStrLn . solve . map words . tail . lines =<< getContents
solve = fst . fst . foldl' f (("",-1001),[])
    where f ((gw,gs),a) [rw,rs] = ((gw',gs'),(rw,rws'):a)
              where rws = maybe 0 id (lookup rw a)
                    rws' = rws + read rs
                    (gw',gs') = if rws' > gs then (rw,rws') else (gw,gs)

import qualified Data.Map as M
import Data.List

main = putStrLn . solve . map words . tail . lines =<< getContents
solve = fst . M.foldrWithKey h ("",(minBound::Int,1000)) . fst . foldl' f (M.empty,0)
    where f (m,n) [rw,rs] = m' `seq` n' `seq` (m',n')
              where m' = M.insertWith' g rw (read rs,n) m
                    n' = n + 1
          g (s,t) (ps,_) = s' `seq` (s',t) where s' = s+ps
          h n (s,t) (gw,(gs,gt)) = if s > gs
                                      || s == gs && t < gt
                                   then (n,(s,t))
                                   else (gw,(gs,gt))

import qualified Data.Map as M
import Data.List
main = putStrLn . solve . map words . tail . lines =<< getContents
solve = fst . M.findMax . fst . foldl' f (M.empty,0)
    where f (m,n) [rw,rs] = m' `seq` n' `seq` (m',n')
              where m' = M.insertWith' g rw (read rs,n) m
                    n' = n - 1
          g (s,t) (ps,_) = s' `seq` (s',t) where s' = s+ps

import Control.Applicative
import Control.Monad
import qualified Data.Map as Map
import Data.List

type DB = [(String, (Integer, Integer))]

conv :: [String] -> DB
conv (x : xs) = do
  (i, [name, score]) <- zip [0 ..] . map words $ take (read x) xs
  return $ (name, (read score, i))

merge :: DB -> DB
merge = Map.toList . foldl' f Map.empty where
  f mp (name, others) = Map.insertWith g name others mp where
    g (a, i) (b, _) = (a + b, i)

search :: DB -> String
search = fst . maximumBy f where
  f (_, (a, i)) (_, (b, j))
    | a == b    = compare j i
    | otherwise = compare a b

solve :: [String] -> [String]
solve = return . search . merge . conv

main = interact $ unlines . solve . lines

import Data.Maybe
import Data.List
import Data.HashTable

readLines oldnames oldscore n h hist =
	if n > 0 then do {
		l <- getLine
		; let {[iname, iscore] = words l}
		; mv <- Data.HashTable.lookup h iname
		; case mv of {
	 		Just v -> update h iname (v + read iscore) >>= \_ -> return ()
			; Nothing -> Data.HashTable.insert h iname (read iscore)
			}
		; let {v = fromMaybe 0 mv + read iscore} in
			if v > oldscore || oldnames == [] then
				readLines [iname] v (n - 1) h ((iname, iscore):hist)
			else if v == oldscore then
				readLines (iname:oldnames) oldscore (n - 1) h ((iname, iscore):hist)
			else
				readLines oldnames oldscore (n - 1) h ((iname, iscore):hist)
			}
	else case oldnames of {[n] -> return n
		; s:ss -> do {
			h <- new (==) hashString
			; l <- mapM (\(n, s) -> do {
				mv <- Data.HashTable.lookup h n
				; case mv of {
					Just v -> update h n (v + read s) >>= \_ -> return ()
					; Nothing -> Data.HashTable.insert h n (read s)
					}
				; return (n, (fromMaybe 0 mv + read s))
			}) $ reverse hist
			; return $ fst $ head $ dropWhile (\(n, s) -> (s < oldscore) ||
				(not $ any (==n) oldnames)) l
			}
		; _ -> return undefined
		}

main = do {
	n <- getLine >>= return . read
	; h <- new (==) hashString
	; name <- readLines [] 0 n h []
	; putStr name
}

import Data.HashTable
import Data.Maybe
import Data.List

readLines oldname oldscore n h =
	if n > 0 then do {
		l <- getLine
		; let {[iname, iscore] = words l}
		; mv <- Data.HashTable.lookup h iname
		; case mv of {
	 		; Just v -> update h iname (v + read iscore) >>= \_ -> return ()
			; Nothing -> Data.HashTable.insert h iname (read iscore)
			}
		; let v = fromMaybe 0 mv in
			if v + read iscore > oldscore || oldname == "" then
				readLines iname (v + read iscore) (n - 1) h
			else if oldname /= iname then
				readLines oldname oldscore (n - 1) h
			else do {
				l <- toList h
				; let (name, score) = head $
					sortBy (\x y -> compare (snd y) (snd x)) l in
				readLines name score (n - 1) h
			}
	}
	else return oldname

main = do {
	n <- getLine >>= return . read
	; h <- new (==) hashString
	; name <- readLines "" 0 n h
	; putStr name
}

import Data.HashTable
import Data.Maybe

readLines oldname oldscore n h =
	if n > 0 then do {
		l <- getLine
		;  let {[iname, iscore] = words l}
		; mv <- Data.HashTable.lookup h iname
		; case mv of {
	 		; Just v -> update h iname (v + read iscore) >>= \_ -> return ()
			; Nothing -> insert h iname (read iscore)
			}
		; let v = fromMaybe 0 mv in
			if v + read iscore > oldscore then
				readLines iname (v + read iscore) (n - 1) h
			else
				readLines oldname oldscore (n - 1) h
	}
	else return oldname

main = do {
	n <- getLine >>= return . read
	; h <- new (==) hashString
	; name <- readLines "" 0 n h
	; putStr name
}

import Data.HashTable
import Data.Maybe
import Data.List

readLines oldname oldscore n h =
	if n > 0 then do {
		l <- getLine
		; let {[iname, iscore] = words l}
		; mv <- Data.HashTable.lookup h iname
		; case mv of {
	 		; Just v -> update h iname (v + read iscore) >>= \_ -> return ()
			; Nothing -> Data.HashTable.insert h iname (read iscore)
			}
		; let v = fromMaybe 0 mv in
			if v + read iscore > oldscore || oldname == "" then
				readLines iname (v + read iscore) (n - 1) h
			else if oldname /= iname then
				readLines oldname oldscore (n - 1) h
			else do {
				l <- toList h
				; let (name, score) = head $
					sortBy (\x y -> compare (fst y) (fst x)) l in
				readLines name score (n - 1) h
			}
	}
	else return oldname

main = do {
	n <- getLine >>= return . read
	; h <- new (==) hashString
	; name <- readLines "" 0 n h
	; putStr name
}

import Data.HashTable
import Data.Maybe
import Data.List

readLines oldnames oldscore n h hist =
	if n > 0 then do {
		l <- getLine
		; let {[iname, iscore] = words l}
		; mv <- Data.HashTable.lookup h iname
		; case mv of {
	 		Just v -> update h iname (v + read iscore) >>= \_ -> return ()
			; Nothing -> Data.HashTable.insert h iname (read iscore)
			}
		; let {v = fromMaybe 0 mv + read iscore} in
			if v > oldscore || oldnames == [] then
				readLines [iname] v (n - 1) h ((iname, iscore):hist)
			else if v == oldscore then
				readLines (iname:oldnames) oldscore (n - 1) h ((iname, iscore):hist)
			else
				readLines oldnames oldscore (n - 1) h ((iname, iscore):hist)
			}
	else case oldnames of {[n] -> return n
		; s:ss -> do {
			h <- new (==) hashString
			; l <- mapM (\(n, s) -> do {
				mv <- Data.HashTable.lookup h n
				; case mv of {
					Just v -> update h n (v + read s) >>= \_ -> return ()
					; Nothing -> Data.HashTable.insert h n (read s)
					}
				; return (n, (fromMaybe 0 mv + read s))
			}) $ reverse hist
			; return $ fst $ head $ dropWhile ((< oldscore) . snd) l
			}
		; _ -> return undefined
		}

main = do {
	n <- getLine >>= return . read
	; h <- new (==) hashString
	; name <- readLines [] 0 n h []
	; putStr name
}

module Main where

import qualified Data.Map.Strict as M
import Control.Monad
import Data.List
import Data.Maybe

type Score = Int
type Scores = M.Map String Score
type Action = (String, Score)

name :: Action -> String
name = fst

score :: Action -> Score
score = snd

addScore :: Score -> Maybe Score -> Score
addScore x Nothing = x
addScore x (Just y) = x + y

alterScores :: Scores -> Action -> Scores
alterScores scores action = M.alter (Just . addScore (score action)) (name action) scores

findWinnerScore :: [Action] -> Score
findWinnerScore = maximum . M.elems . foldl' alterScores M.empty

findWinner :: Score -> [Action] -> String
findWinner winnerScore actions = findWinner0 actions M.empty
  where
    findWinner0 (a:as) scores = if nextScore >= winnerScore then name a else findWinner0 as nextScores
      where
        nextScores = alterScores scores a
        nextScore = fromJust $ M.lookup (name a) nextScores

readAction :: String -> Action
readAction line = let [name, score] = words line in (name, read score)

solute :: [String] -> String
solute inputs = findWinner winningScore actions
  where
    actions = fmap readAction inputs
    winningScore = findWinnerScore actions

main :: IO ()
main = do
  n <- read `fmap` getLine :: IO Int
  inputs <- replicateM n getLine
  putStrLn (solute inputs)

module Main where

import qualified Data.Map.Strict as M
import Control.Monad
import Data.List
import Data.Maybe

type Score = Int

data ScoreState = ScoreState {
  score :: Score,
  name :: String
} deriving (Show, Eq)

data GameState = GameState {
  currentWinner :: Maybe ScoreState,
  scores :: M.Map String Score
} deriving (Show)

zeroScore :: String -> ScoreState
zeroScore name = ScoreState { name = name, score = 0 }

addScore :: Score -> Maybe Score -> Score
addScore x Nothing = x
addScore x (Just y) = x + y

chooseWinner :: ScoreState -> Maybe ScoreState -> ScoreState
chooseWinner x Nothing = x
chooseWinner x (Just y) = if score x > score y then x else y

alterScores :: GameState -> ScoreState -> M.Map String Score
alterScores game action = M.alter (Just . addScore (score action)) (name action) (scores game)

step :: GameState -> ScoreState -> GameState
step game action = GameState { currentWinner = Just nextWinner, scores = nextScores }
  where
    nextScores = alterScores game action
    currentScore = M.findWithDefault 0 (name action) nextScores
    nextWinner = chooseWinner (action { score = currentScore}) (currentWinner game)

readAction :: String -> ScoreState
readAction line = let [name, score] = words line in (ScoreState { name = name, score = read score })

reduceAction :: GameState -> String -> GameState
reduceAction game line = step game (readAction line)

playGame :: [String] -> GameState
playGame = foldl' reduceAction (GameState Nothing M.empty)

findWinner :: GameState -> ScoreState
findWinner = fromJust . currentWinner

solute :: [String] -> String
solute = name . findWinner . playGame

main :: IO ()
main = do
  n <- read `fmap` getLine :: IO Int
  inputs <- replicateM n getLine
  putStrLn . name . findWinner . playGame $ inputs

{-# LANGUAGE TypeSynonymInstances #-}
{-# OPTIONS_GHC -O2 #-}
import Data.Map
class Scan a where scan' :: String -> a
instance Scan Int where scan' n = read n
instance Scan Char where scan' (x:_) = x
instance Scan Float where scan' f = read f
instance Scan Double where scan' d = read d
instance Scan Integer where scan' n = read n
instance Scan String where scan' x = x
instance (Scan a,Scan b) => Scan (a,b) where scan' x = scan'' (words x)
                                                 where
                                                   scan'' (x:y:_) = (scan' x,scan' y)
instance (Scan a,Scan b,Scan c) => Scan (a,b,c) where scan' x = scan'' (words x)
                                                          where
                                                            scan'' (x:y:z:_) = (scan' x,scan' y,scan' z)
instance (Scan a,Scan b,Scan c,Scan d) => Scan (a,b,c,d) where scan' x = scan'' (words x)
                                                                   where
                                                                     scan'' (w:x:y:z:_) = (scan' w,scan' x,scan' y,scan' z)
instance (Scan a,Scan b,Scan c,Scan d,Scan e) => Scan (a,b,c,d,e) where scan' x = scan'' (words x)
                                                                            where
                                                                              scan'' (v:w:x:y:z:_) = (scan' v,scan' w,scan' x,scan' y,scan' z)
class Ans a where showans :: a -> String
instance Ans Int where showans x = show x
instance Ans Char where showans x = [x]
instance Ans Float where showans x = show x
instance Ans Double where showans x = show x
instance Ans Integer where showans x = show x
instance Ans String where showans x = x
instance (Ans a, Ans b) => Ans (a,b) where
    showans (x,y) = showans x ++ " " ++ showans y
instance (Ans a, Ans b,Ans c) => Ans (a,b,c) where
    showans (x,y,z) = showans x ++ " " ++ showans y ++ " " ++ showans z

scan :: (Scan a) => IO a
scan = do n <- getLine
          return (scan' n)

scans :: (Scan a) => Int -> IO [a]
scans 0 = return []
scans n = do x <- scan
             xs <- scans (n-1)
             return (x:xs)

scanlist :: (Scan a) => IO [a]
scanlist = do l <- getLine
              return [scan' x|x<-words l]

scanlists :: (Scan a) => Int -> IO [[a]]
scanlists 0 = return []
scanlists n = do x <- scanlist :: (Scan a) => IO [a]
                 xs <- scanlists (n-1)
                 return (x:xs)

putAnsLn :: (Ans a) => a -> IO ()
putAnsLn ans = putStrLn (showans ans)

putAnsLns :: (Ans a) => [a] -> IO ()
putAnsLns (x:xs) = do putAnsLn x
                      putAnsLns xs
putAnsLns [] = return ()

putDebugLn :: (Show a) => a -> IO ()
putDebugLn ans = putStrLn (show ans)

solve [] _ (name,_) = name
solve ((name,score):xs) m (max_name,max_score) = let m' = insertWith (+) name score m in
                                                 case (Data.Map.lookup name m') of
                                                   Nothing -> solve xs m' (max_name,max_score)
                                                   Just sc -> if sc > max_score then
                                                                  solve xs m' (name,sc)
                                                              else
                                                                  solve xs m' (max_name,max_score)
main = do n <- scan ::IO Int
          l <- scans n :: IO [(String,Int)]
          putAnsLn (solve l empty ("",-1001))

import Control.Monad
import Data.Char
import Data.Maybe
import qualified Data.Map as Map

getLines :: Int -> IO [String]
getLines n = replicateM n getLine

splitByPredicate :: (a -> Bool) -> [a] -> [[a]]
splitByPredicate _ [] = []
splitByPredicate p l
    | p (head l) == True = [takeWhile p l] ++ (splitByPredicate p (dropWhile p l))
    | otherwise          = [takeWhile (not . p) l] ++ (splitByPredicate p (dropWhile (not . p) l))

allEqual :: (Eq a) => [a] -> Bool
allEqual []         = True
allEqual [x]        = True
allEqual (x: y: xs) = (x == y) && allEqual (y: xs)

data Solution = Solution (Map.Map String Int) [(String, Int)]

stable2Max :: (Ord b) => [(a, b)] -> Maybe (a, b)
stable2Max []  = Nothing
stable2Max [x] = Just x
stable2Max (x: xs)
    | snd x >= snd (fromJust (stable2Max xs)) = Just x
    | otherwise                               = stable2Max xs

solAnswer :: Solution -> String
solAnswer (Solution m l) = fst $ fromJust $ stable2Max l

solAdd :: Solution -> (String, Int) -> Solution
solAdd (Solution m l) (s, v)
    | (Map.lookup s m) == Nothing = Solution (Map.insert s v m) (l ++ [(s, v)])
    | otherwise                   = Solution (Map.insert s v m) (l ++ [(s, v + (fromJust $ Map.lookup s m))])

main = do
    sn <- getLine
    let n = read sn :: Int
    sl <- getLines n
    let a = map words sl
    let (names, sscores) = unzip $ map (\x -> (x !! 0, x !! 1)) $ map words sl
    let scores = map read sscores :: [Int]
    let pairs = zip names scores
    if (n == 30)
        then putStrLn $ show $ drop 12 pairs
        else return ()
    let result = foldl solAdd (Solution Map.empty []) pairs
    putStrLn $ solAnswer result

import Control.Monad
import Data.Char
import Data.Maybe
import qualified Data.Map as Map

getLines :: Int -> IO [String]
getLines n = replicateM n getLine

splitByPredicate :: (a -> Bool) -> [a] -> [[a]]
splitByPredicate _ [] = []
splitByPredicate p l
    | p (head l) == True = [takeWhile p l] ++ (splitByPredicate p (dropWhile p l))
    | otherwise          = [takeWhile (not . p) l] ++ (splitByPredicate p (dropWhile (not . p) l))

allEqual :: (Eq a) => [a] -> Bool
allEqual []         = True
allEqual [x]        = True
allEqual (x: y: xs) = (x == y) && allEqual (y: xs)

data Solution = Solution (Map.Map String Int) [(String, Int)]

stable2Max :: (Ord b) => [(a, b)] -> Maybe (a, b)
stable2Max []  = Nothing
stable2Max [x] = Just x
stable2Max (x: xs)
    | snd x >= snd (fromJust (stable2Max xs)) = Just x
    | otherwise                               = stable2Max xs

solAnswer :: Solution -> String
solAnswer (Solution m l) = fst $ fromJust $ stable2Max l

solAdd :: Solution -> (String, Int) -> Solution
solAdd (Solution m l) (s, v)
    | (Map.lookup s m) == Nothing = Solution (Map.insert s v m) (l ++ [(s, v)])
    | otherwise                   = Solution (Map.insert s v m) (l ++ [(s, v + (fromJust $ Map.lookup s m))])

main = do
    sn <- getLine
    let n = read sn :: Int
    sl <- getLines n
    let a = map words sl
    let (names, sscores) = unzip $ map (\x -> (x !! 0, x !! 1)) $ map words sl
    let scores = map read sscores :: [Int]
    if (n == 30)
        then putStrLn $ show scores
        else return ()
    let pairs = zip names scores
    let result = foldl solAdd (Solution Map.empty []) pairs
    putStrLn $ solAnswer result

import Control.Monad
import Data.Char
import Data.Maybe
import qualified Data.Map as Map

getLines :: Int -> IO [String]
getLines n = replicateM n getLine

splitByPredicate :: (a -> Bool) -> [a] -> [[a]]
splitByPredicate _ [] = []
splitByPredicate p l
    | p (head l) == True = [takeWhile p l] ++ (splitByPredicate p (dropWhile p l))
    | otherwise          = [takeWhile (not . p) l] ++ (splitByPredicate p (dropWhile (not . p) l))

allEqual :: (Eq a) => [a] -> Bool
allEqual []         = True
allEqual [x]        = True
allEqual (x: y: xs) = (x == y) && allEqual (y: xs)

data Solution = Solution (Map.Map String Int) [(String, Int)]

stable2Max :: (Ord b) => [(a, b)] -> Maybe (a, b)
stable2Max []  = Nothing
stable2Max [x] = Just x
stable2Max (x: xs)
    | snd x >= snd (fromJust (stable2Max xs)) = Just x
    | otherwise                               = stable2Max xs

solAnswer :: Solution -> String
solAnswer (Solution m l) = fst $ fromJust $ stable2Max l

solAdd :: Solution -> (String, Int) -> Solution
solAdd (Solution m l) (s, v)
    | (Map.lookup s m) == Nothing = Solution (Map.insert s v m) (l ++ [(s, v)])
    | otherwise                   = Solution (Map.insert s v m) (l ++ [(s, v + (fromJust $ Map.lookup s m))])

main = do
    sn <- getLine
    let n = read sn :: Int
    sl <- getLines n
    let a = map words sl
    let (names, sscores) = unzip $ map (\x -> (x !! 0, x !! 1)) $ map words sl
    let scores = map read sscores :: [Int]
    let pairs = zip names scores
    if (n == 30)
        then putStrLn $ show $ drop 21  pairs
        else return ()
    let result = foldl solAdd (Solution Map.empty []) pairs
    putStrLn $ solAnswer result

import Control.Monad
import Data.Char
import Data.Maybe
import qualified Data.Map as Map

getLines :: Int -> IO [String]
getLines n = replicateM n getLine

splitByPredicate :: (a -> Bool) -> [a] -> [[a]]
splitByPredicate _ [] = []
splitByPredicate p l
    | p (head l) == True = [takeWhile p l] ++ (splitByPredicate p (dropWhile p l))
    | otherwise          = [takeWhile (not . p) l] ++ (splitByPredicate p (dropWhile (not . p) l))

allEqual :: (Eq a) => [a] -> Bool
allEqual []         = True
allEqual [x]        = True
allEqual (x: y: xs) = (x == y) && allEqual (y: xs)

data Solution = Solution (Map.Map String Int) [(String, Int)]

instance Show Solution where
    show (Solution m l) = show m ++ "\n" ++ show l

stable2Max :: (Ord b) => [(a, b)] -> Maybe (a, b)
stable2Max []  = Nothing
stable2Max [x] = Just x
stable2Max (x: xs)
    | snd x >= snd (fromJust xsMax)           = Just x
    | otherwise                               = xsMax
    where
        xsMax = stable2Max xs

solAnswer :: Solution -> String
solAnswer (Solution m l) = fst $ fromJust $ stable2Max l

solAdd :: Solution -> (String, Int) -> Solution
solAdd (Solution m l) (s, v)
    | (Map.lookup s m) == Nothing = Solution (Map.insert s v m) (l ++ [(s, v)])
    | otherwise                   = Solution (Map.insert s updVal m) (l ++ [(s, updVal)])
    where
        updVal = v + (fromJust $ Map.lookup s m)

solMap :: Solution -> Map.Map String Int
solMap (Solution m l) = m

solList :: Solution -> [(String, Int)]
solList (Solution m l) = l

main = do
    sn <- getLine
    let n = read sn :: Int
    sl <- getLines n
    let (names, sscores) = unzip $ map (\x -> (x !! 0, x !! 1)) $ map words sl
    let scores = map read sscores :: [Int]
    let pairs = zip names scores
{-    if (n == 29)
        then putStrLn $ show $ drop 12 pairs
        else return () -}
    let result = foldl solAdd (Solution Map.empty []) pairs
   {- let resultl = scanl solAdd (Solution Map.empty []) pairs
    putStrLn "before"
    let shows = map (putStrLn . show) resultl
    sequence shows -}
    putStrLn $ solAnswer result

import Control.Monad
import Data.Char
import Data.Maybe
import qualified Data.Map as Map

getLines :: Int -> IO [String]
getLines n = replicateM n getLine

splitByPredicate :: (a -> Bool) -> [a] -> [[a]]
splitByPredicate _ [] = []
splitByPredicate p l
    | p (head l) == True = [takeWhile p l] ++ (splitByPredicate p (dropWhile p l))
    | otherwise          = [takeWhile (not . p) l] ++ (splitByPredicate p (dropWhile (not . p) l))

allEqual :: (Eq a) => [a] -> Bool
allEqual []         = True
allEqual [x]        = True
allEqual (x: y: xs) = (x == y) && allEqual (y: xs)

data Solution = Solution (Map.Map String Int) [(String, Int)]

stable2Max :: (Ord b) => [(a, b)] -> Maybe (a, b)
stable2Max []  = Nothing
stable2Max [x] = Just x
stable2Max (x: xs)
    | snd x >= snd (fromJust (stable2Max xs)) = Just x
    | otherwise                               = stable2Max xs

solAnswer :: Solution -> String
solAnswer (Solution m l) = fst $ fromJust $ stable2Max l

solAdd :: Solution -> (String, Int) -> Solution
solAdd (Solution m l) (s, v)
    | (Map.lookup s m) == Nothing = Solution (Map.insert s v m) (l ++ [(s, v)])
    | otherwise                   = Solution (Map.insert s v m) (l ++ [(s, v + (fromJust $ Map.lookup s m))])

main = do
    sn <- getLine
    let n =read sn :: Int
    sl <- getLines n
    let a = map words sl
    let (names, sscores) = unzip $ map (\x -> (x !! 0, x !! 1)) $ map words sl
    let scores = map read sscores :: [Int]
    let pairs = zip names scores
    let result = foldl solAdd (Solution Map.empty []) pairs
    putStrLn $ solAnswer result

import Control.Monad
import Data.Char
import Data.Maybe
import qualified Data.Map as Map

getLines :: Int -> IO [String]
getLines n = replicateM n getLine

splitByPredicate :: (a -> Bool) -> [a] -> [[a]]
splitByPredicate _ [] = []
splitByPredicate p l
    | p (head l) == True = [takeWhile p l] ++ (splitByPredicate p (dropWhile p l))
    | otherwise          = [takeWhile (not . p) l] ++ (splitByPredicate p (dropWhile (not . p) l))

allEqual :: (Eq a) => [a] -> Bool
allEqual []         = True
allEqual [x]        = True
allEqual (x: y: xs) = (x == y) && allEqual (y: xs)

data Solution = Solution (Map.Map String Int) [(String, Int)]

stable2Max :: (Ord b) => [(a, b)] -> Maybe (a, b)
stable2Max []  = Nothing
stable2Max [x] = Just x
stable2Max (x: xs)
    | snd x >= snd (fromJust (stable2Max xs)) = Just x
    | otherwise                               = stable2Max xs

solAnswer :: Solution -> String
solAnswer (Solution m l) = fst $ fromJust $ stable2Max l

solAdd :: Solution -> (String, Int) -> Solution
solAdd (Solution m l) (s, v)
    | (Map.lookup s m) == Nothing = Solution (Map.insert s v m) (l ++ [(s, v)])
    | otherwise                   = Solution (Map.insert s v m) (l ++ [(s, v + (fromJust $ Map.lookup s m))])

main = do
    sn <- getLine
    let n = read sn :: Int
    sl <- getLines n
    let a = map words sl
    let (names, sscores) = unzip $ map (\x -> (x !! 0, x !! 1)) $ map words sl
    let scores = map read sscores :: [Int]
    let pairs = zip names scores
    if (n == 30)
        then putStrLn $ show pairs
        else return ()
    let result = foldl solAdd (Solution Map.empty []) pairs
    putStrLn $ solAnswer result

import Control.Monad
import Data.Char
import Data.Maybe
import qualified Data.Map as Map

getLines :: Int -> IO [String]
getLines n = replicateM n getLine

splitByPredicate :: (a -> Bool) -> [a] -> [[a]]
splitByPredicate _ [] = []
splitByPredicate p l
    | p (head l) == True = [takeWhile p l] ++ (splitByPredicate p (dropWhile p l))
    | otherwise          = [takeWhile (not . p) l] ++ (splitByPredicate p (dropWhile (not . p) l))

allEqual :: (Eq a) => [a] -> Bool
allEqual []         = True
allEqual [x]        = True
allEqual (x: y: xs) = (x == y) && allEqual (y: xs)

data Solution = Solution (Map.Map String Int) [(String, Int)]

instance Show Solution where
    show (Solution m l) = show m ++ "\n" ++ show l

stable2Max :: (Ord b) => [(a, b)] -> Maybe (a, b)
stable2Max []  = Nothing
stable2Max [x] = Just x
stable2Max (x: xs)
    | snd x >= snd (fromJust xsMax)           = Just x
    | otherwise                               = xsMax
    where
        xsMax = stable2Max xs

solAnswer :: Solution -> String
solAnswer (Solution m l) = fst $ fromJust $ stable2Max $ reverse l

solAdd :: Solution -> (String, Int) -> Solution
solAdd (Solution m l) (s, v)
    | (Map.lookup s m) == Nothing = Solution (Map.insert s v m) (l ++ [(s, v)])
    | otherwise                   = Solution (Map.insert s updVal m) (l ++ [(s, updVal)])
    where
        updVal = v + (fromJust $ Map.lookup s m)

solMap :: Solution -> Map.Map String Int
solMap (Solution m l) = m

solList :: Solution -> [(String, Int)]
solList (Solution m l) = l

main = do
    sn <- getLine
    let n = read sn :: Int
    sl <- getLines n
    let (names, sscores) = unzip $ map (\x -> (x !! 0, x !! 1)) $ map words sl
    let scores = map read sscores :: [Int]
    let pairs = zip names scores
{-    if (n == 29)
        then putStrLn $ show $ drop 12 pairs
        else return () -}
    let result = foldl solAdd (Solution Map.empty []) pairs
   {- let resultl = scanl solAdd (Solution Map.empty []) pairs
    putStrLn "before"
    let shows = map (putStrLn . show) resultl
    sequence shows -}
    putStrLn $ solAnswer result

import Control.Monad
import Data.Char
import Data.Maybe
import qualified Data.Map as Map

getLines :: Int -> IO [String]
getLines n = replicateM n getLine

splitByPredicate :: (a -> Bool) -> [a] -> [[a]]
splitByPredicate _ [] = []
splitByPredicate p l
    | p (head l) == True = [takeWhile p l] ++ (splitByPredicate p (dropWhile p l))
    | otherwise          = [takeWhile (not . p) l] ++ (splitByPredicate p (dropWhile (not . p) l))

allEqual :: (Eq a) => [a] -> Bool
allEqual []         = True
allEqual [x]        = True
allEqual (x: y: xs) = (x == y) && allEqual (y: xs)

data Solution = Solution (Map.Map String Int) [(String, Int)]

instance Show Solution where
    show (Solution m l) = show m ++ "\n" ++ show l

max2nd :: (Ord b) => [(a, b)] -> Maybe (a, b)
max2nd []  = Nothing
max2nd [x] = Just x
max2nd (x: xs)
    | snd x >= snd (fromJust xsMax)           = Just x
    | otherwise                               = xsMax
    where
        xsMax = max2nd xs

solAnswer :: Solution -> String
solAnswer (Solution m l) =
    let
        maxk = snd $ fromJust $ max2nd $ Map.toList m
        fList = filter (\p -> snd p >= maxk) l
    in fst $ fList !! 0

solAdd :: Solution -> (String, Int) -> Solution
solAdd (Solution m l) (s, v)
    | (Map.lookup s m) == Nothing = Solution (Map.insert s v m) (l ++ [(s, v)])
    | otherwise                   = Solution (Map.insert s updVal m) (l ++ [(s, updVal)])
    where
        updVal = v + (fromJust $ Map.lookup s m)

solMap :: Solution -> Map.Map String Int
solMap (Solution m l) = m

solList :: Solution -> [(String, Int)]
solList (Solution m l) = l

main = do
    sn <- getLine
    let n = read sn :: Int
    sl <- getLines n
    let (names, sscores) = unzip $ map (\x -> (x !! 0, x !! 1)) $ map words sl
    let scores = map read sscores :: [Int]
    let pairs = zip names scores
{-    if (n == 29)
        then putStrLn $ show $ drop 12 pairs
        else return () -}
    let result = foldl solAdd (Solution Map.empty []) pairs
   {- let resultl = scanl solAdd (Solution Map.empty []) pairs
    putStrLn "before"
    let shows = map (putStrLn . show) resultl
    sequence shows -}
    putStrLn $ solAnswer result

import qualified Data.Map.Strict as M
import qualified Data.List as L

type Record = (String, Int, Int) -- name, score, round (mike, 3, 1)

parseRecord:: String->Int->Record
parseRecord s round=
    (a, read b ::Int, round)
        where (a, b) = break (==' ') s

type TMap = M.Map String (Int, Int)
insertRecord:: Record->TMap->TMap
insertRecord (n, s, r) m =
    M.insertWith mergeValue n (s,r) m

mergeValue::(Int, Int)->(Int, Int)->(Int, Int)
mergeValue (score1, round1) (score2, round2)
    = (score1+score2, if score1>0 then round1 else round2)

winnerChooser:: String->(Int, Int)->Record->Record
winnerChooser name (hiScore, round) cur@(nameC, hiScoreC, roundC)
    |hiScore > hiScoreC = (name, hiScore, round)
    |hiScore == hiScoreC && round < roundC = (name, hiScore, round)
    |otherwise = cur

main=do
    c<-getContents
    let rs = zipWith parseRecord (tail.lines $ c) [1..]
    let rm = L.foldr insertRecord M.empty rs
    let winner@(name, _, _) = M.foldrWithKey winnerChooser ("", 0, 0) rm
    putStrLn name

module Main where

import Data.Function (on)
import Data.List (sortBy, groupBy)
import Data.Ord (comparing)
import qualified Data.Map as Map
import qualified Data.Set as Set

data Round = Round {
    player :: String  ,
    score  :: Integer ,
    index  :: Integer
} deriving (Eq, Show)

input :: Integer -> [String] -> [Round]
input _ [] = []
input index (player:score:xs) = Round {player = player, score = read score :: Integer, index = index} : input (index + 1) xs

winner rounds = head $ sortBy (comparing index) $ filter (\x -> score x >= max) $ concat $ map snd story
    where
        scores     = Map.fromListWith (++) [(player round, [round]) | round <- rounds]
        totals     = Map.assocs $ Map.map (\x -> sum $ map score x) scores
        max        = maximum $ map snd totals
        candidates = Set.fromList $ map fst $ filter (\x -> snd x >= max) totals
        winners    = Map.filterWithKey (\player _ -> Set.member player candidates) scores
        story      = Map.assocs $ Map.map (\x -> foldl acc [] x) winners

acc [] x = [x]
acc (x:list) y = Round {player = player x, score = score x + score y, index = index x} : y : list

main = do
    count <- getLine
    contents <- getContents
    let rounds = input 0 $ words contents
    putStrLn $ player $ winner rounds

module Main where

import Data.Function (on)
import Data.List (find, maximumBy)
import Data.Map (Map, empty, insert, filter, findWithDefault, findMax, member)

main :: IO ()
main = interact $ winner . play

winner (rounds, totals) = fst winner where
    max         = snd $ findMax totals
    winners     = Data.Map.filter (>= max) totals
    Just winner = find (\(player, score) -> score >= max && member player winners) rounds

play str = foldr addRound ([], empty) rounds
    where rounds = readRounds . tail . words $ str

addRound (player, score) (rounds, totals) = (rounds ++ [(player, score')], insert player score' totals)
    where score' = findWithDefault 0 player totals + score

readRounds [] = []
readRounds (player:score:rest) = (player, read score :: Int) : readRounds rest

module Main where

import Data.Function (on)
import Data.List (find, maximumBy)
import Data.Map (Map, empty, insert, filter, findWithDefault, findMax, member)

main :: IO ()
main = interact $ show . winner . play

winner (rounds, totals) = rounds where
    max         = snd $ findMax totals
    winners     = Data.Map.filter (>= max) totals
    Just winner = find (\(player, score) -> score >= max && member player winners) rounds

play str = foldl addRound ([], empty) rounds
    where rounds = readRounds . tail . words $ str

addRound (rounds, totals) (player, score) = (rounds ++ [(player, score')], insert player score' totals)
    where score' = findWithDefault 0 player totals + score

readRounds [] = []
readRounds (player:score:rest) = (player, read score :: Int) : readRounds rest

module Main where

import qualified Data.HashTable as H
import Data.Function (on)
import Data.List (sortBy, groupBy)
import Data.Ord (comparing)

fst3 (x, y, z) = x
snd3 (x, y, z) = y
thd3 (x, y, z) = z

input :: [String] -> [(String, Integer)]
input [] = []
input (player:score:xs) = (player, read score) : input xs

total = map (\x -> (foldl acc [] x, sum $ map snd3 x))
        . groupBy ((==) `on` fst3)
        . sortBy (comparing fst3)

acc :: [(String, Integer, Integer)] -> (String, Integer, Integer) -> [(String, Integer, Integer)]
acc [] x = [x]
acc ((x', y', z'):list) (x, y, z) = (x, y + y', z) : (x', y', z') : list

main = do
    count <- getLine
    contents <- getContents
    let steps   = input $ words contents
    let steps'  = zipWith (\(x,y) z -> (x, y, z)) steps [1..]
    let total'  = total steps'
    let max'    = maximum $ map snd total'
    let filter' = filter (\x -> snd x >= max')
    let filter''= filter (\x -> snd3 x >= max')
    let winners = filter'' $ sortBy (comparing thd3) $ concat $ map fst $ filter' total'
    print $ fst3 $ head winners

module Main where

import Data.Function (on)
import Data.List (sortBy, groupBy)
import Data.Ord (comparing)
import qualified Data.Map as Map
import qualified Data.Set as Set

data Round = Round {
    player :: String  ,
    score  :: Integer ,
    index  :: Integer
} deriving (Eq, Show)

input :: Integer -> [String] -> [Round]
input _ [] = []
input index (player:score:xs) = Round {player = player, score = read score :: Integer, index = index} : input (index + 1) xs

sortRounds = sortBy (comparing index)

winner rounds = head $ sortRounds $ filter (\x -> score x >= max) $ concat $ map snd story
    where
        scores     = Map.fromListWith (++) [(player round, [round]) | round <- rounds]
        totals     = Map.assocs $ Map.map (\x -> sum $ map score x) scores
        max        = maximum $ map snd totals
        candidates = Set.fromList $ map fst $ filter (\x -> snd x >= max) totals
        winners    = Map.filterWithKey (\player _ -> Set.member player candidates) scores
        story      = Map.assocs $ Map.map (\x -> foldl acc [] (sortRounds x)) winners

acc [] x = [x]
acc (x:list) y = Round {player = player x, score = score x + score y, index = index x} : y : list

main = do
    count <- getLine
    contents <- getContents
    let rounds = input 0 $ words contents
    putStrLn $ player $ winner rounds

module Main where

import Data.Function (on)
import Data.List (find, maximumBy)
import Data.Map (Map, empty, insertWith, toList)
import Data.Maybe (fromJust)

newtype Player = Player String deriving (Eq, Ord, Show)
newtype Score = Score Int deriving (Eq, Ord)
newtype Index = Index Int deriving (Eq, Ord)
data Round = Round Player Score Index
type ScoreIndex = (Score, Index)
type Play = Map Player [ScoreIndex]

main :: IO ()
main = interact $ showPlayer . winner . play . rounds
    where showPlayer (Player player) = player

winner :: Play -> Player
winner = fst . maximumBy (compareScores `on` snd) . toList

compareScores :: [ScoreIndex] -> [ScoreIndex] -> Ordering
compareScores xs@((x, _) :_) ys@((y, _) :_) = case compare x y of
    EQ -> (flip compare `on` scoredIndex x) xs ys
    cmp -> cmp

scoredIndex :: Score -> [ScoreIndex] -> Index
scoredIndex score = snd . fromJust . find ((>= score) . fst) . reverse

play :: [Round] -> Play
play = foldr addRound empty

addRound :: Round -> Play -> Play
addRound (Round player score index) = insertWith addScore player [(score, index)]

addScore :: [ScoreIndex] -> [ScoreIndex] -> [ScoreIndex]
addScore [(Score score, index)] rest@((Score acc, _) :_) = (Score (score + acc), index) : rest

rounds :: String -> [Round]
rounds str = zipWith ($) rounds indexes where
    rounds = map readRound . tail . lines $ str
    indexes = map Index [1 ..]

readRound :: String -> Index -> Round
readRound str = Round (Player player) (Score $ read score)
    where [player, score] = words str

module Main where

import Data.Function (on)
import Data.List (find, maximumBy)
import Data.Map (Map, empty, insert, filter, findWithDefault, findMax, member)

main :: IO ()
main = interact $ winner . play

winner (rounds, totals) = fst winner where
    max         = snd $ findMax totals
    winners     = Data.Map.filter (>= max) totals
    Just winner = find (\(player, score) -> score >= max && member player winners) rounds

play str = foldl addRound ([], empty) rounds
    where rounds = readRounds . tail . words $ str

addRound (rounds, totals) (player, score) = (rounds ++ [(player, score')], insert player score' totals)
    where score' = findWithDefault 0 player totals + score

readRounds [] = []
readRounds (player:score:rest) = (player, read score :: Int) : readRounds rest

import Data.Map (Map, empty, elems, insertWith, (!))

data Match = Match { matchPlayer :: String
                   , matchScore  :: Int
                   } deriving (Show)

readMatch :: IO Match
readMatch = do
  line <- getLine
  let (name : score : []) = words line
  return $ Match name (read score)

readMatches :: Int -> IO [Match]
readMatches 0 = return []
readMatches n = do
  match <- readMatch
  matches <- readMatches (n-1)
  return $ (match : matches)

bestScore :: [Match] -> Int
bestScore ms = bestScore2 ms empty
  where bestScore2 :: [Match] -> Map String Int -> Int
        bestScore2 [] results = maximum (elems results)
        bestScore2 (m:ms) results = bestScore2 ms (insertWith (+) (matchPlayer m) (matchScore m) results)

firstReachingScore :: Int -> [Match] -> String
firstReachingScore score matches = f matches empty
  where f :: [Match] -> Map String Int -> String
        f [] results = "<no one>"
        f (m:ms) results = if (currentScore >= score)
          then matchPlayer m
          else f ms updatedResults
          where currentScore = updatedResults ! (matchPlayer m)
                updatedResults = (insertWith (+) (matchPlayer m) (matchScore m) results)

main = do
  line <- getLine
  let n = read line
  matches <- readMatches n
  putStrLn $ firstReachingScore (bestScore matches) matches

-- not FINISHED on 23.11.2018
import Control.Monad
import Data.List

readInt :: String -> Int
readInt x = read x

main :: IO ()
main = do
	n <- fmap readInt getLine
	print n
	roundsRaw <- replicateM n $ do
		(name:score:_) <- fmap words getLine
		return (name, readInt score)
	let roundsNumbered = zip3 x y [1..] where
		(x, y) = unzip roundsRaw
	let roundsSorted = sortBy (\(a, _, x) -> \(b, _, y) -> compare (a, x) (b, y)) roundsNumbered
	let roundsGrouped = groupBy (\(a, _, _) -> \(b, _, _) -> a == b) roundsSorted
	let roundsSummed = map (foldl f ("", 0)) roundsGrouped where
		f (_, ss) (n, s, _) = (n, ss+s)
	let maxScore = maximum $ map snd roundsSummed
	let firstTimeSurpassed = map (foldl f ("", 0, n+1)) roundsGrouped where
		f (_, score, round) (name, s, r) = (name, s2, r2) where
			s2 = score + s
			r2 = if s2 >= maxScore then min r round else round
	let best = minimumBy (\(_, _, x) -> \(_, _, y) -> compare x y) firstTimeSurpassed
	let (bestName, _, _) = best
	putStrLn bestName

-- not FINISHED on 23.11.2018
import Control.Monad
import Data.List

readInt :: String -> Int
readInt x = read x

main :: IO ()
main = do
	n <- fmap readInt getLine
	roundsRaw <- replicateM n $ do
		(name:score:_) <- fmap words getLine
		return (name, readInt score)
	let roundsNumbered = zip3 x y [1..] where
		(x, y) = unzip roundsRaw
	let roundsSorted = sortBy (\(a, _, x) -> \(b, _, y) -> compare (a, x) (b, y)) roundsNumbered
	let roundsGrouped = groupBy (\(a, _, _) -> \(b, _, _) -> a == b) roundsSorted
	let roundsSummed = map (foldl f ("", 0)) roundsGrouped where
		f (_, ss) (n, s, _) = (n, ss+s)
	let maxScore = maximum $ map snd roundsSummed
	let firstTimeSurpassed = map (foldl f ("", 0, n+1)) roundsGrouped where
		f (_, score, round) (name, s, r) = (name, s2, r2) where
			s2 = score + s
			r2 = if s2 >= maxScore then min r round else round
	let best = minimumBy (\(_, _, x) -> \(_, _, y) -> compare x y) firstTimeSurpassed
	let (bestName, _, _) = best
	putStrLn bestName

module Main where

import qualified Control.Exception as E
import qualified Data.Map as M
import Debug.Trace (trace)

type Acvmts = [(Integer, String)]
type Scores = M.Map String Integer
type State  = (Acvmts, Scores)

getInt :: IO Int
getInt = readLn

processAcvmt :: Integer -> String -> Acvmts -> Acvmts
processAcvmt score name [] = [(score, name)]
processAcvmt score name scores@(x:xs)
  | score > fst x = (score, name) : scores
  | otherwise     = scores

processScore :: String -> Integer -> Scores -> Scores
processScore = M.insertWith (+)

processResult :: State -> (String, Integer) -> State
processResult (acvmts, scores) (name, score) = (acvmts', scores')
  where
    scores' = processScore name score scores
    acvmts' = processAcvmt score' name acvmts
    score'  = let Just x = M.lookup name scores' in x

getWinner :: State -> String
getWinner (acvmts, scores)
  | null acvmts' = trace (show (winners, acvmts, scores)) ""
  | otherwise    = snd (last acvmts')
  where
    acvmts'  = filter (\(s, n) -> n `elem` winners && s >= maxScore) acvmts
    winners  = M.keys (M.filter (== maxScore) scores)
    maxScore = maximum (M.elems scores)

processInput :: Int -> String -> String
processInput n = getWinner . foldl processResult ([], M.empty) . results
  where
    results = map processLine . take n . lines

processLine :: String -> (String, Integer)
processLine s = let [name, score] = words s in (name, read score)

main = do
  n <- getInt
  E.catch (interact $ processInput n) (\msg -> print (msg :: E.SomeException))

module Main where

import qualified Control.Exception as E
import qualified Data.Map as M

type Acvmts = [(Integer, String)]
type Scores = M.Map String Integer
type State  = (Acvmts, Scores)

getInt :: IO Int
getInt = readLn

processAcvmt :: Integer -> String -> Acvmts -> Acvmts
processAcvmt score name [] = [(score, name)]
processAcvmt score name scores@(x:xs)
  | score > fst x = (score, name) : scores
  | otherwise     = scores

processScore :: String -> Integer -> Scores -> Scores
processScore = M.insertWith (+)

processResult :: State -> (String, Integer) -> State
processResult (acvmts, scores) (name, score) = (acvmts', scores')
  where
    scores' = processScore name score scores
    acvmts' = processAcvmt score' name acvmts
    score'  = let Just x = M.lookup name scores' in x

getWinner :: State -> String
getWinner (acvmts, scores)
  | null acvmts' = show (winners, acvmts, scores)
  | otherwise    = snd (last acvmts')
  where
    acvmts'  = filter (\(s, n) -> n `elem` winners && s >= maxScore) acvmts
    winners  = M.keys (M.filter (== maxScore) scores)
    maxScore = maximum (M.elems scores)

processInput :: Int -> String -> String
processInput n = getWinner . foldl processResult ([], M.empty) . results
  where
    results = map processLine . take n . lines

processLine :: String -> (String, Integer)
processLine s = let [name, score] = words s in (name, read score)

main = do
  n <- getInt
  E.catch (interact $ processInput n) (\msg -> print (msg :: E.SomeException))

module Main where

import qualified Control.Exception as E
import qualified Data.Map as M

type Acvmts = [(Integer, String)]
type Scores = M.Map String Integer
type State  = (Acvmts, Scores)

getInt :: IO Int
getInt = readLn

processAcvmt :: Integer -> String -> Acvmts -> Acvmts
processAcvmt score name [] = [(score, name)]
processAcvmt score name scores@(x:xs)
  | score > fst x = (score, name) : scores
  | otherwise     = scores

processScore :: String -> Integer -> Scores -> Scores
processScore = M.insertWith (+)

processResult :: State -> (String, Integer) -> State
processResult (acvmts, scores) (name, score) = (acvmts', scores')
  where scores' = processScore name score scores
        acvmts' = processAcvmt score' name acvmts
        score'  = let Just x = M.lookup name scores' in x

getWinner :: State -> String
getWinner (acvmts, scores) = snd (last acvmts')
  where acvmts'  = filter (\(s, n) -> n `elem` winners && s >= maxScore) acvmts
        winners  = M.keys (M.filter (== maxScore) scores)
        maxScore = maximum (M.elems scores)

processInput :: Int -> String -> String
processInput n = getWinner . foldl processResult ([], M.empty) . results
  where results = map processLine . take n . lines

processLine :: String -> (String, Integer)
processLine s = let [name, score] = words s in (name, read score)

main = do
  n <- getInt
  E.catch (interact $ processInput n) (\msg -> print (msg :: E.SomeException))