Problem:
Score: 300 points

Problem Statement

In Republic of Atcoder, there are N prefectures, and a total of M cities that belong to those prefectures.

City i is established in year Y_i and belongs to Prefecture P_i.

You can assume that there are no multiple cities that are established in the same year.

It is decided to allocate a 12-digit ID number to each city.

If City i is the x-th established city among the cities that belong to Prefecture i, the first six digits of the ID number of City i is P_i, and the last six digits of the ID number is x.

Here, if P_i or x (or both) has less than six digits, zeros are added to the left until it has six digits.

Find the ID numbers for all the cities.

Note that there can be a prefecture with no cities.

Constraints

1 \leq N \leq 10^5

1 \leq M \leq 10^5

1 \leq P_i \leq N

1 \leq Y_i \leq 10^9

Y_i are all different.

All values in input are integers.

Input

Input is given from Standard Input in the following format:

N M
P_1 Y_1
:
P_M Y_M

Output

Print the ID numbers for all the cities, in ascending order of indices (City 1, City 2, ...).

Sample Input 1

2 3
1 32
2 63
1 12

Sample Output 1

000001000002
000002000001
000001000001

As City 1 is the second established city among the cities that belong to Prefecture 1, its ID number is 000001000002.

As City 2 is the first established city among the cities that belong to Prefecture 2, its ID number is 000002000001.

As City 3 is the first established city among the cities that belong to Prefecture 1, its ID number is 000001000001.

Sample Input 2

2 3
2 55
2 77
2 99

Sample Output 2

000002000001
000002000002
000002000003

Solution in Haskell (GHC 7.10.3) (judge verdict: Accepted)

{-# OPTIONS_GHC -O2 -funbox-strict-fields #-}
import           Control.Monad.ST
import           Control.Monad.State.Strict
import           Data.Bits                   (shiftR)
import qualified Data.ByteString.Char8       as B
import qualified Data.ByteString.Unsafe      as B
import           Data.Char                   (isSpace)
import           Data.STRef
import qualified Data.Vector.Unboxed         as V
import qualified Data.Vector.Unboxed.Mutable as VM

main :: IO ()
main = do
  [n, m] <- map read . words <$> getLine
  pys <- V.unfoldrN m parseInt2 <$> B.getContents
  putStr $ solve n m pys

solve :: Int -> Int -> V.Vector (Int, Int) -> String
solve _ m pys = unlines . map (tail . show) $ V.toList ids
  where
    ids = runST $ do
      v <- VM.new m :: ST s (VM.STVector s Int)
      cr <- newSTRef 1 :: ST s (STRef s Int)
      VM.write v (get3 (pyis V.! 0)) (encodeId (get1 (pyis V.! 0)) 1)
      forM_ [1 .. m - 1] $ \i -> do
        if get1 (pyis V.! i) /= get1 (pyis V.! (i - 1))
          then writeSTRef cr 1
          else modifySTRef cr (+ 1)
        c <- readSTRef cr
        VM.write v (get3 (pyis V.! i)) (encodeId (get1 (pyis V.! i)) c)
      V.freeze v
    pyis = sort' . V.zip pys $ V.enumFromN 0 m :: V.Vector ((Int, Int), Int)

get1 :: ((a, a), a) -> a
get1 = fst . fst

-- get2 :: ((a, a), a) -> a
-- get2 = snd . fst

get3 :: ((a, a), a) -> a
get3 = snd

encodeId :: Int -> Int -> Int
encodeId p r = 1000000000000 + p * 1000000 + r

sort' :: (Ord a, V.Unbox a) => V.Vector a -> V.Vector a
sort' = V.modify (\v -> quicksort v 0 (VM.length v))

-- https://github.com/as-capabl/haskell-qsort-pfm/blob/master/src/UV.hs
quicksort :: (Ord a, V.Unbox a) => VM.STVector s a -> Int -> Int -> ST s ()
quicksort work iStart iEnd
    | iEnd - iStart <= 1 = return ()
    | otherwise = do
        pivot <- VM.unsafeRead work (((iEnd - iStart) `shiftR` 1) + iStart)
        med <- divide pivot iStart (iEnd - 1)
        quicksort work iStart med
        quicksort work med iEnd
  where
    divide pivot iS' iE'
        | iS' > iE' = return iS'
        | otherwise = do
            lower <- shrinkLower pivot iS' iE'
            higher <- shrinkHigher pivot lower iE'
            if lower >= higher
              then do
                return lower
              else do
                swapWork lower higher
                divide pivot (lower + 1) (higher - 1)

    shrinkLower pivot iS' iE'
        | iS' > iE' = return iS'
        | otherwise = do
            x <- VM.unsafeRead work iS'
            if x >= pivot
              then
                return iS'
              else
                shrinkLower pivot (iS' + 1) iE'

    shrinkHigher pivot iS' iE'
        | iS' > iE' = return iE'
        | otherwise = do
            x <- VM.unsafeRead work iE'
            if x <= pivot
              then
                return iE'
              else
                shrinkHigher pivot iS' (iE' - 1)

    swapWork i j = VM.unsafeSwap work i j

type Parser a = B.ByteString -> Maybe (a, B.ByteString)

parseInt2 :: Parser (Int, Int)
parseInt2 = runStateT $
  (,) <$> StateT (B.readInt . B.dropWhile isSpace)
  <*> StateT (B.readInt . B.unsafeTail)