import Data.List(sort,sortBy,intersect)

-- |  The 'isSorted' predicate returns 'True' if the elements of a list occur
-- in non-descending order,  equivalent to @'isSortedBy' ('<=')@.
isSorted :: Ord a => [a] -> Bool
isSorted = isSortedBy (<=)

-- |  The 'isSortedBy' function returns 'True' iff the predicate returns true
-- for all adjacent pairs of elements in the list.
isSortedBy :: (a -> a -> Bool) -> [a] -> Bool
isSortedBy lte = loop
  where
    loop []       = True
    loop [_]      = True
    loop (x:y:zs) = (x `lte` y) && loop (y:zs)

-- |  The 'member' function returns 'True' if the element appears in the
-- ordered list.
member :: Ord a => a -> [a] -> Bool
member = memberBy compare

-- |  The 'memberBy' function is the non-overloaded version of 'member'.
memberBy :: (a -> a -> Ordering) -> a -> [a] -> Bool
memberBy cmp x = loop
  where
    loop []     = False
    loop (y:ys) = case cmp x y of
                    LT -> False
                    EQ -> True
                    GT -> loop ys

-- |  The 'has' function returns 'True' if the element appears in the list;
-- it is equivalent to 'member' except the order of the arguments is reversed,
-- making it a function from an ordered list to its characteristic function.
has :: Ord a => [a] -> a -> Bool
has xs y = memberBy compare y xs

-- |  The 'hasBy' function is the non-overloaded version of 'has'.
hasBy :: (a -> a -> Ordering) -> [a] -> a -> Bool
hasBy cmp xs y = memberBy cmp y xs

-- |  The 'insertBag' function inserts an element into a list.  If the element
-- is already there,  then another copy of the element is inserted.
insertBag :: Ord a => a -> [a] -> [a]
insertBag = insertBagBy compare

-- |  The 'insertBagBy' function is the non-overloaded version of 'insertBag'.
insertBagBy :: (a -> a -> Ordering) -> a -> [a] -> [a]
insertBagBy cmp = loop
  where
    loop x [] = [x]
    loop x (y:ys)
      = case cmp x y of
         GT -> y:loop x ys
         _  -> x:y:ys

-- |  The 'insertSet' function inserts an element into an ordered list.
-- If the element is already there,  then the element replaces the existing
-- element.
insertSet :: Ord a => a -> [a] -> [a]
insertSet = insertSetBy compare

-- |  The 'insertSetBy' function is the non-overloaded version of 'insertSet'.
insertSetBy :: (a -> a -> Ordering) -> a -> [a] -> [a]
insertSetBy cmp = loop
  where
    loop x [] = [x]
    loop x (y:ys) = case cmp x y of
            LT -> x:y:ys
            EQ -> x:ys
            GT -> y:loop x ys

{-
-- This function is moderately interesting,  as it encompasses all the
-- "Venn diagram" functions on two sets. (though not merge;  which isn't
-- a set function)

-- However, it doesn't seem that useful,  considering that of the 8 possible
-- functions,  there are only 4 interesting variations:  isect, union, minus,
-- and xunion.  Due to interactions with GHC's optimizer,  coded separately,
-- these have a smaller combined object code size than the object code size
-- for genSectBy.  (Or,  turn off certain optimizations and lose speed.)

-- Each individual object code can be recovered from genSectBy via GHC's
-- inliner and constant propagation;  but this doesn't save much in terms
-- of source code size and reduces portability.

-- Note that the Static Argument Transformation is necessary for this to work
-- correctly;  inlining genSectBy allows for cmp and p to be inlined as well,
-- or at least eliminate some indirect jumps.  All of the *By functions in
-- this module follow this idiom for this reason.

genSectBy :: (a -> a -> Ordering)
          -> (Bool -> Bool -> Bool)
          -> [a] -> [a] -> [a]
genSectBy cmp p = loop
  where
    loop [] ys | p False True = ys
               | otherwise    = []
    loop xs [] | p True False = xs
               | otherwise    = []
    loop (x:xs) (y:ys)
      = case cmp x y of
          LT | p True False -> x : loop xs (y:ys)
             | otherwise    ->     loop xs (y:ys)
          EQ | p True True  -> x : loop xs ys
             | otherwise    ->     loop xs ys
          GT | p False True -> y : loop (x:xs) ys
             | otherwise    ->     loop (x:xs) ys

-- Here's another variation that was suggested to me.  It is more general
-- than genSectBy, as it can implement a merge; but it cannot implement
-- a left-biased merge

foldrMergeBy :: (a -> b -> Ordering)
             -> (a -> c -> c) -> (b -> c -> c) -> (a -> b -> c -> c) -> c
             -> [a] -> [b] -> c
foldrMergeBy cmp addA addB unify z = loop
  where
    loop xs [] = foldr addA z xs
    loop [] ys = foldr addB z ys
    loop (x:xs) (y:ys)
      = case cmp x y of
          LT -> x `addA` loop  xs (y:ys)
          EQ -> unify x y (loop xs ys)
          GT -> y `addB` loop (x:xs) ys
-}

-- |  The 'isect' function computes the intersection of two ordered lists.
-- An element occurs in the output as many times as the minimum number of
-- occurrences in either input.  If either input is a set,  then the output
-- is a set.
--
-- > isect [ 1,2, 3,4 ] [ 3,4, 5,6 ]   == [ 3,4 ]
-- > isect [ 1, 2,2,2 ] [ 1,1,1, 2,2 ] == [ 1, 2,2 ]
isect :: Ord a => [a] -> [a] -> [a]
isect = isectBy compare

-- |  The 'isectBy' function is the non-overloaded version of 'isect'.
isectBy :: (a -> b -> Ordering) -> [a] -> [b] -> [a]
isectBy cmp = loop
  where
     loop [] _ys  = []
     loop _xs []  = []
     loop (x:xs) (y:ys)
       = case cmp x y of
          LT ->     loop xs (y:ys)
          EQ -> x : loop xs ys
          GT ->     loop (x:xs) ys

-- |  The 'union' function computes the union of two ordered lists.
-- An element occurs in the output as many times as the maximum number
-- of occurrences in either input.  The output is a set if and only if
-- both inputs are sets.
--
-- > union [ 1,2, 3,4 ] [ 3,4, 5,6 ]   == [ 1,2, 3,4, 5,6 ]
-- > union [ 1, 2,2,2 ] [ 1,1,1, 2,2 ] == [ 1,1,1, 2,2,2 ]
union :: Ord a => [a] -> [a] -> [a]
union = unionBy compare

-- |  The 'unionBy' function is the non-overloaded version of 'union'.
unionBy :: (a -> a -> Ordering) -> [a] -> [a] -> [a]
unionBy cmp = loop
  where
     loop [] ys = ys
     loop xs [] = xs
     loop (x:xs) (y:ys)
       = case cmp x y of
          LT -> x : loop xs (y:ys)
          EQ -> x : loop xs ys
          GT -> y : loop (x:xs) ys

-- |  The 'minus' function computes the difference of two ordered lists.
-- An element occurs in the output as many times as it occurs in
-- the first input, minus the number of occurrences in the second input.
-- If the first input is a set,  then the output is a set.
--
-- > minus [ 1,2, 3,4 ] [ 3,4, 5,6 ]   == [ 1,2 ]
-- > minus [ 1, 2,2,2 ] [ 1,1,1, 2,2 ] == [ 2 ]
minus :: Ord a => [a] -> [a] -> [a]
minus = minusBy compare

-- |  The 'minusBy' function is the non-overloaded version of 'minus'.
minusBy :: (a -> b -> Ordering) -> [a] -> [b] -> [a]
minusBy cmp = loop
  where
     loop [] _ys = []
     loop xs [] = xs
     loop (x:xs) (y:ys)
       = case cmp x y of
          LT -> x : loop xs (y:ys)
          EQ ->     loop xs ys
          GT ->     loop (x:xs) ys

-- |  The 'minus'' function computes the difference of two ordered lists.
-- The result consists of elements from the first list that do not appear
-- in the second list.  If the first input is a set, then the output is
-- a set.
--
-- > minus' [ 1,2, 3,4 ] [ 3,4, 5,6 ]   == [ 1,2 ]
-- > minus' [ 1, 2,2,2 ] [ 1,1,1, 2,2 ] == []
-- > minus' [ 1,1, 2,2 ] [ 2 ]          == [ 1,1 ]
minus' :: Ord a => [a] -> [a] -> [a]
minus' = minusBy' compare

-- |  The 'minusBy'' function is the non-overloaded version of 'minus''.
minusBy' :: (a -> b -> Ordering) -> [a] -> [b] -> [a]
minusBy' cmp = loop
  where
     loop [] _ys = []
     loop xs [] = xs
     loop (x:xs) (y:ys)
       = case cmp x y of
          LT -> x : loop xs (y:ys)
          EQ ->     loop xs (y:ys)
          GT ->     loop (x:xs) ys

-- |  The 'xunion' function computes the exclusive union of two ordered lists.
-- An element occurs in the output as many times as the absolute difference
-- between the number of occurrences in the inputs.  If both inputs
-- are sets,  then the output is a set.
--
-- > xunion [ 1,2, 3,4 ] [ 3,4, 5,6 ]   == [ 1,2, 5,6 ]
-- > xunion [ 1, 2,2,2 ] [ 1,1,1, 2,2 ] == [ 1,1, 2 ]
xunion :: Ord a => [a] -> [a] -> [a]
xunion = xunionBy compare

-- |  The 'xunionBy' function is the non-overloaded version of 'xunion'.
xunionBy :: (a -> a -> Ordering) -> [a] -> [a] -> [a]
xunionBy cmp = loop
  where
     loop [] ys = ys
     loop xs [] = xs
     loop (x:xs) (y:ys)
       = case cmp x y of
          LT -> x : loop xs (y:ys)
          EQ ->     loop xs ys
          GT -> y : loop (x:xs) ys

-- |  The 'merge' function combines all elements of two ordered lists.
-- An element occurs in the output as many times as the sum of the
-- occurrences in both lists.   The output is a set if and only if
-- the inputs are disjoint sets.
--
-- > merge [ 1,2, 3,4 ] [ 3,4, 5,6 ]   == [ 1,2,  3,3,4,4,  5,6 ]
-- > merge [ 1, 2,2,2 ] [ 1,1,1, 2,2 ] == [ 1,1,1,1,  2,2,2,2,2 ]
merge :: Ord a => [a] -> [a] -> [a]
merge = mergeBy compare

-- |  The 'mergeBy' function is the non-overloaded version of 'merge'.
mergeBy :: (a -> a -> Ordering) -> [a] -> [a] -> [a]
mergeBy cmp = loop
  where
    loop [] ys  = ys
    loop xs []  = xs
    loop (x:xs) (y:ys)
      = case cmp x y of
         GT -> y : loop (x:xs) ys
         _  -> x : loop xs (y:ys)

-- |  The 'subset' function returns true if the first list is a sub-list
-- of the second.
subset :: Ord a => [a] -> [a] -> Bool
subset = subsetBy compare

-- |  The 'subsetBy' function is the non-overloaded version of 'subset'.
subsetBy :: (a -> a -> Ordering) -> [a] -> [a] -> Bool
subsetBy cmp = loop
  where
    loop [] _ys = True
    loop _xs [] = False
    loop (x:xs) (y:ys)
      = case cmp x y of
         LT -> False
         EQ -> loop xs ys
         GT -> loop (x:xs) ys

{-
-- This is Ian Lynagh's mergesort implementation,  which appeared as
-- Data.List.sort, with the static argument transformation applied.
-- It's not clear whether this modification is truly worthwhile or not.

sort :: Ord a => [a] -> [a]
sort = sortBy compare

sortBy :: (a -> a -> Ordering) -> [a] -> [a]
sortBy cmp = foldt (mergeBy cmp) [] . map (\x -> [x])
-}

-- |  The 'sortOn' function provides the decorate-sort-undecorate idiom,
-- also known as the \"Schwartzian transform\".
sortOn :: Ord b => (a -> b) -> [a] -> [a]
sortOn f  = map snd . sortOn' fst .  map (\x -> let y = f x in y `seq` (y, x))

-- |  This variant of 'sortOn' recomputes the sorting key every comparison.
-- This can be better for functions that are cheap to compute.
-- This is definitely better for projections,  as the decorate-sort-undecorate
-- saves nothing and adds two traversals of the list and extra memory
-- allocation.
sortOn' :: Ord b => (a -> b) -> [a] -> [a]
sortOn' f = sortBy (\x y -> compare (f x) (f y))

-- |  The 'nubSort' function is equivalent to @'nub' '.' 'sort'@,  except
-- that duplicates are removed as it sorts. It is essentially the same
-- implementation as @Data.List.sort@, with 'merge' replaced by 'union'.
-- Thus the performance of 'nubSort' should better than or nearly equal
-- to 'sort' alone.  It is faster than both 'sort' and @'nub' '.' 'sort'@
-- when the input contains significant quantities of duplicated elements.
nubSort :: Ord a => [a] -> [a]
nubSort = nubSortBy compare

-- |  The 'nubSortBy' function is the non-overloaded version of 'nubSort'.
nubSortBy :: (a -> a -> Ordering) -> [a] -> [a]
nubSortBy cmp = foldt' (unionBy cmp) [] . runs
  where
    -- 'runs' partitions the input into sublists that are monotonic,
    -- contiguous,  and non-overlapping.   Descending runs are reversed
    -- and adjacent duplicates are eliminated,  so every run returned is
    -- strictly ascending.

    runs (a:b:xs)
      = case cmp a b of
          LT -> asc b (a:) xs
          EQ -> runs (a:xs)
          GT -> desc b [a] xs
    runs xs = [xs]

    desc a as []  = [a:as]
    desc a as (b:bs)
      = case cmp a b of
          LT -> (a:as) : runs (b:bs)
          EQ -> desc a as bs
          GT -> desc b (a:as) bs

    asc a as [] = [as [a]]
    asc a as (b:bs)
      = case cmp a b of
         LT -> asc b (\ys -> as (a:ys)) bs
         EQ -> asc a as bs
         GT -> as [a] : runs (b:bs)

-- |  The 'nubSortOn' function provides decorate-sort-undecorate for 'nubSort'.
nubSortOn :: Ord b => (a -> b) -> [a] -> [a]
nubSortOn f = map snd . nubSortOn' fst . map (\x -> let y = f x in y `seq` (y, x))

-- |  This variant of 'nubSortOn' recomputes the sorting key for each comparison
nubSortOn' :: Ord b => (a -> b) -> [a] -> [a]
nubSortOn' f = nubSortBy (\x y -> compare (f x) (f y))

-- | On ordered lists,  'nub' is equivalent to 'Data.List.nub', except that
-- it runs in linear time instead of quadratic.   On unordered lists it also
-- removes elements that are smaller than any preceding element.
--
-- > nub [1,1,1,2,2] == [1,2]
-- > nub [2,0,1,3,3] == [2,3]
-- > nub = nubBy (<)
nub :: Ord a => [a] -> [a]
nub = nubBy (<)

-- | The 'nubBy' function is the greedy algorithm that returns a
-- sublist of its input such that:
--
-- > isSortedBy pred (nubBy pred xs) == True
--
-- This is true for all lists,  not just ordered lists,  and all binary
-- predicates,  not just total orders.   On infinite lists,  this statement
-- is true in a certain mathematical sense,  but not a computational one.
nubBy :: (a -> a -> Bool) -> [a] -> [a]
nubBy p []     = []
nubBy p (x:xs) = x : loop x xs
  where
    loop _ [] = []
    loop x (y:ys)
       | p x y     = y : loop y ys
       | otherwise = loop x ys

-- | The function @'foldt'' plus zero@ computes the sum of a list
-- using a balanced tree of operations.  'foldt'' necessarily diverges
-- on infinite lists, hence it is a stricter variant of 'foldt'.
-- 'foldt'' is used in the implementation of 'sort' and 'nubSort'.
foldt' :: (a -> a -> a) -> a -> [a] -> a
foldt' plus zero xs
  = case xs of
      []    -> zero
      (_:_) -> loop xs
  where
    loop [x] = x
    loop xs  = loop (pairs xs)

    pairs (x:y:zs) = plus x y : pairs zs
    pairs zs       = zs

-- | The function @'foldt' plus zero@ computes the sum of a list using
-- a sequence of balanced trees of operations.   Given an appropriate @plus@
-- operator,  this function can be productive on an infinite list, hence it
-- is lazier than 'foldt''.   'foldt' is used in the implementation of
-- 'mergeAll' and 'unionAll'.
foldt :: (a -> a -> a) -> a -> [a] -> a
foldt plus zero = loop
  where
    loop []     = zero
    loop (x:xs) = x `plus` loop (pairs xs)

    pairs (x:y:zs) = plus x y : pairs zs
    pairs zs       = zs

-- helper functions used in 'mergeAll' and 'unionAll'

data People a = VIP a (People a) | Crowd [a]

serve (VIP x xs) = x:serve xs
serve (Crowd xs) = xs

vips xss = [ VIP x (Crowd xs) | (x:xs) <- xss ]

-- | The 'mergeAll' function merges a (potentially) infinite number of
-- ordered lists, under the assumption that the heads of the inner lists
-- are sorted.  An element is duplicated in the result as many times as
-- the total number of occurrences in all inner lists.
--
-- The 'mergeAll' function is closely related to @'foldr' 'merge' []@.
-- The former does not assume that the outer list is finite, whereas
-- the latter does not assume that the heads of the inner lists are sorted.
-- When both sets of assumptions are met,  these two functions are
-- equivalent.
--
-- This implementation of 'mergeAll'  uses a tree of comparisons, and is
-- based on input from Dave Bayer, Heinrich Apfelmus, Omar Antolin Camarena,
-- and Will Ness.  See @CHANGES@ for details.
mergeAll :: Ord a => [[a]] -> [a]
mergeAll = mergeAllBy compare

-- | The 'mergeAllBy' function is the non-overloaded variant of the 'mergeAll'
-- function.
mergeAllBy :: (a -> a -> Ordering) -> [[a]] -> [a]
mergeAllBy cmp = serve . foldt merge' (Crowd []) . vips
  where
    merge' (VIP x xs) ys = VIP x (merge' xs ys)
    merge' (Crowd []) ys = ys
    merge' (Crowd xs) (Crowd ys) = Crowd (mergeBy cmp xs ys)
    merge' xs@(Crowd (x:xt)) ys@(VIP y yt)
      = case cmp x y of
         GT -> VIP y (merge' xs yt)
         _  -> VIP x (merge' (Crowd xt) ys)

-- | The 'unionAll' computes the union of a (potentially) infinite number
-- of lists,  under the assumption that the heads of the inner lists
-- are sorted.  The result will duplicate an element as many times as
-- the maximum number of occurrences in any single list.  Thus, the result
-- is a set if and only if every inner list is a set.
--
-- The 'unionAll' function is closely related to @'foldr' 'union' []@.
-- The former does not assume that the outer list is finite, whereas
-- the latter does not assume that the heads of the inner lists are sorted.
-- When both sets of assumptions are met,  these two functions are
-- equivalent.
--
-- Note that there is no simple way to express 'unionAll' in terms of
-- 'mergeAll' or vice versa on arbitrary valid inputs.  They are related
-- via 'nub' however,  as @'nub' . 'mergeAll' == 'unionAll' . 'map' 'nub'@.
-- If every list is a set,  then @map nub == id@,  and in this special case
-- (and only in this special case) does @nub . mergeAll == unionAll@.
--
-- This implementation of 'unionAll'  uses a tree of comparisons, and is
-- based on input from Dave Bayer, Heinrich Apfelmus, Omar Antolin Camarena,
-- and Will Ness.  See @CHANGES@ for details.
unionAll :: Ord a => [[a]] -> [a]
unionAll = unionAllBy compare

-- | The 'unionAllBy' function is the non-overloaded variant of the 'unionAll'
-- function.
unionAllBy :: (a -> a -> Ordering) -> [[a]] -> [a]
unionAllBy cmp = serve . foldt union' (Crowd []) . vips
  where
    msg = "Data.List.Ordered.unionAllBy:  the heads of the lists are not sorted"

    union' (VIP x xs) ys
       = VIP x $ case ys of
                  Crowd _ -> union' xs ys
                  VIP y yt -> case cmp x y of
                               LT -> union' xs ys
                               EQ -> union' xs yt
                               GT -> error msg
    union' (Crowd []) ys = ys
    union' (Crowd xs) (Crowd ys) = Crowd (unionBy cmp xs ys)
    union' xs@(Crowd (x:xt)) ys@(VIP y yt)
       = case cmp x y of
           LT -> VIP x (union' (Crowd xt) ys)
           EQ -> VIP x (union' (Crowd xt) yt)
           GT -> VIP y (union' xs yt)

main :: IO ()
main = do
  c <- getContents
  let l = (map (read :: String -> Int) . words) c
  let (n : m : k : ll) = l
  let a = [(0, 1, y, 0) | y <- [1..n]] ++ [(0, 2, y, 0) | y <- [1..m]] ++ mt ll 1
  let b = reverse a
  let b1 = filter (\(i, x, y, z) -> case x of {1 -> True; _ -> False}) b
  let b2 = filter (\(i, x, y, z) -> case x of {2 -> True; _ -> False}) b
  let c1 = nubSortBy fc b1
  let c2 = nubSortBy fc b2
  let c = [[q | (i2,x2,y2,z2) <- c2, let i = y1, let j = y2, let q = case compare i1 i2 of {GT -> z1; EQ -> z1; LT -> z2}] | (i1,x1,y1,z1) <- c1]
  putStrLn $ unlines . map (unwords . (map show)) $ c

fc :: (Int,Int,Int,Int) -> (Int,Int,Int,Int) -> Ordering
fc (i1,x1,y1,z1) (i2,x2,y2,z2) = compare y1 y2

mt :: [Int] -> Int -> [(Int, Int, Int, Int)]
mt [] _ = []
mt (a : b : c : ll) n = (n,a,b,c) : mt ll (n+1)

import Data.List(sort,sortBy,intersect)

-- |  The 'isSorted' predicate returns 'True' if the elements of a list occur
-- in non-descending order,  equivalent to @'isSortedBy' ('<=')@.
isSorted :: Ord a => [a] -> Bool
isSorted = isSortedBy (<=)

-- |  The 'isSortedBy' function returns 'True' iff the predicate returns true
-- for all adjacent pairs of elements in the list.
isSortedBy :: (a -> a -> Bool) -> [a] -> Bool
isSortedBy lte = loop
  where
    loop []       = True
    loop [_]      = True
    loop (x:y:zs) = (x `lte` y) && loop (y:zs)

-- |  The 'member' function returns 'True' if the element appears in the
-- ordered list.
member :: Ord a => a -> [a] -> Bool
member = memberBy compare

-- |  The 'memberBy' function is the non-overloaded version of 'member'.
memberBy :: (a -> a -> Ordering) -> a -> [a] -> Bool
memberBy cmp x = loop
  where
    loop []     = False
    loop (y:ys) = case cmp x y of
                    LT -> False
                    EQ -> True
                    GT -> loop ys

-- |  The 'has' function returns 'True' if the element appears in the list;
-- it is equivalent to 'member' except the order of the arguments is reversed,
-- making it a function from an ordered list to its characteristic function.
has :: Ord a => [a] -> a -> Bool
has xs y = memberBy compare y xs

-- |  The 'hasBy' function is the non-overloaded version of 'has'.
hasBy :: (a -> a -> Ordering) -> [a] -> a -> Bool
hasBy cmp xs y = memberBy cmp y xs

-- |  The 'insertBag' function inserts an element into a list.  If the element
-- is already there,  then another copy of the element is inserted.
insertBag :: Ord a => a -> [a] -> [a]
insertBag = insertBagBy compare

-- |  The 'insertBagBy' function is the non-overloaded version of 'insertBag'.
insertBagBy :: (a -> a -> Ordering) -> a -> [a] -> [a]
insertBagBy cmp = loop
  where
    loop x [] = [x]
    loop x (y:ys)
      = case cmp x y of
         GT -> y:loop x ys
         _  -> x:y:ys

-- |  The 'insertSet' function inserts an element into an ordered list.
-- If the element is already there,  then the element replaces the existing
-- element.
insertSet :: Ord a => a -> [a] -> [a]
insertSet = insertSetBy compare

-- |  The 'insertSetBy' function is the non-overloaded version of 'insertSet'.
insertSetBy :: (a -> a -> Ordering) -> a -> [a] -> [a]
insertSetBy cmp = loop
  where
    loop x [] = [x]
    loop x (y:ys) = case cmp x y of
            LT -> x:y:ys
            EQ -> x:ys
            GT -> y:loop x ys

{-
-- This function is moderately interesting,  as it encompasses all the
-- "Venn diagram" functions on two sets. (though not merge;  which isn't
-- a set function)

-- However, it doesn't seem that useful,  considering that of the 8 possible
-- functions,  there are only 4 interesting variations:  isect, union, minus,
-- and xunion.  Due to interactions with GHC's optimizer,  coded separately,
-- these have a smaller combined object code size than the object code size
-- for genSectBy.  (Or,  turn off certain optimizations and lose speed.)

-- Each individual object code can be recovered from genSectBy via GHC's
-- inliner and constant propagation;  but this doesn't save much in terms
-- of source code size and reduces portability.

-- Note that the Static Argument Transformation is necessary for this to work
-- correctly;  inlining genSectBy allows for cmp and p to be inlined as well,
-- or at least eliminate some indirect jumps.  All of the *By functions in
-- this module follow this idiom for this reason.

genSectBy :: (a -> a -> Ordering)
          -> (Bool -> Bool -> Bool)
          -> [a] -> [a] -> [a]
genSectBy cmp p = loop
  where
    loop [] ys | p False True = ys
               | otherwise    = []
    loop xs [] | p True False = xs
               | otherwise    = []
    loop (x:xs) (y:ys)
      = case cmp x y of
          LT | p True False -> x : loop xs (y:ys)
             | otherwise    ->     loop xs (y:ys)
          EQ | p True True  -> x : loop xs ys
             | otherwise    ->     loop xs ys
          GT | p False True -> y : loop (x:xs) ys
             | otherwise    ->     loop (x:xs) ys

-- Here's another variation that was suggested to me.  It is more general
-- than genSectBy, as it can implement a merge; but it cannot implement
-- a left-biased merge

foldrMergeBy :: (a -> b -> Ordering)
             -> (a -> c -> c) -> (b -> c -> c) -> (a -> b -> c -> c) -> c
             -> [a] -> [b] -> c
foldrMergeBy cmp addA addB unify z = loop
  where
    loop xs [] = foldr addA z xs
    loop [] ys = foldr addB z ys
    loop (x:xs) (y:ys)
      = case cmp x y of
          LT -> x `addA` loop  xs (y:ys)
          EQ -> unify x y (loop xs ys)
          GT -> y `addB` loop (x:xs) ys
-}

-- |  The 'isect' function computes the intersection of two ordered lists.
-- An element occurs in the output as many times as the minimum number of
-- occurrences in either input.  If either input is a set,  then the output
-- is a set.
--
-- > isect [ 1,2, 3,4 ] [ 3,4, 5,6 ]   == [ 3,4 ]
-- > isect [ 1, 2,2,2 ] [ 1,1,1, 2,2 ] == [ 1, 2,2 ]
isect :: Ord a => [a] -> [a] -> [a]
isect = isectBy compare

-- |  The 'isectBy' function is the non-overloaded version of 'isect'.
isectBy :: (a -> b -> Ordering) -> [a] -> [b] -> [a]
isectBy cmp = loop
  where
     loop [] _ys  = []
     loop _xs []  = []
     loop (x:xs) (y:ys)
       = case cmp x y of
          LT ->     loop xs (y:ys)
          EQ -> x : loop xs ys
          GT ->     loop (x:xs) ys

-- |  The 'union' function computes the union of two ordered lists.
-- An element occurs in the output as many times as the maximum number
-- of occurrences in either input.  The output is a set if and only if
-- both inputs are sets.
--
-- > union [ 1,2, 3,4 ] [ 3,4, 5,6 ]   == [ 1,2, 3,4, 5,6 ]
-- > union [ 1, 2,2,2 ] [ 1,1,1, 2,2 ] == [ 1,1,1, 2,2,2 ]
union :: Ord a => [a] -> [a] -> [a]
union = unionBy compare

-- |  The 'unionBy' function is the non-overloaded version of 'union'.
unionBy :: (a -> a -> Ordering) -> [a] -> [a] -> [a]
unionBy cmp = loop
  where
     loop [] ys = ys
     loop xs [] = xs
     loop (x:xs) (y:ys)
       = case cmp x y of
          LT -> x : loop xs (y:ys)
          EQ -> x : loop xs ys
          GT -> y : loop (x:xs) ys

-- |  The 'minus' function computes the difference of two ordered lists.
-- An element occurs in the output as many times as it occurs in
-- the first input, minus the number of occurrences in the second input.
-- If the first input is a set,  then the output is a set.
--
-- > minus [ 1,2, 3,4 ] [ 3,4, 5,6 ]   == [ 1,2 ]
-- > minus [ 1, 2,2,2 ] [ 1,1,1, 2,2 ] == [ 2 ]
minus :: Ord a => [a] -> [a] -> [a]
minus = minusBy compare

-- |  The 'minusBy' function is the non-overloaded version of 'minus'.
minusBy :: (a -> b -> Ordering) -> [a] -> [b] -> [a]
minusBy cmp = loop
  where
     loop [] _ys = []
     loop xs [] = xs
     loop (x:xs) (y:ys)
       = case cmp x y of
          LT -> x : loop xs (y:ys)
          EQ ->     loop xs ys
          GT ->     loop (x:xs) ys

-- |  The 'minus'' function computes the difference of two ordered lists.
-- The result consists of elements from the first list that do not appear
-- in the second list.  If the first input is a set, then the output is
-- a set.
--
-- > minus' [ 1,2, 3,4 ] [ 3,4, 5,6 ]   == [ 1,2 ]
-- > minus' [ 1, 2,2,2 ] [ 1,1,1, 2,2 ] == []
-- > minus' [ 1,1, 2,2 ] [ 2 ]          == [ 1,1 ]
minus' :: Ord a => [a] -> [a] -> [a]
minus' = minusBy' compare

-- |  The 'minusBy'' function is the non-overloaded version of 'minus''.
minusBy' :: (a -> b -> Ordering) -> [a] -> [b] -> [a]
minusBy' cmp = loop
  where
     loop [] _ys = []
     loop xs [] = xs
     loop (x:xs) (y:ys)
       = case cmp x y of
          LT -> x : loop xs (y:ys)
          EQ ->     loop xs (y:ys)
          GT ->     loop (x:xs) ys

-- |  The 'xunion' function computes the exclusive union of two ordered lists.
-- An element occurs in the output as many times as the absolute difference
-- between the number of occurrences in the inputs.  If both inputs
-- are sets,  then the output is a set.
--
-- > xunion [ 1,2, 3,4 ] [ 3,4, 5,6 ]   == [ 1,2, 5,6 ]
-- > xunion [ 1, 2,2,2 ] [ 1,1,1, 2,2 ] == [ 1,1, 2 ]
xunion :: Ord a => [a] -> [a] -> [a]
xunion = xunionBy compare

-- |  The 'xunionBy' function is the non-overloaded version of 'xunion'.
xunionBy :: (a -> a -> Ordering) -> [a] -> [a] -> [a]
xunionBy cmp = loop
  where
     loop [] ys = ys
     loop xs [] = xs
     loop (x:xs) (y:ys)
       = case cmp x y of
          LT -> x : loop xs (y:ys)
          EQ ->     loop xs ys
          GT -> y : loop (x:xs) ys

-- |  The 'merge' function combines all elements of two ordered lists.
-- An element occurs in the output as many times as the sum of the
-- occurrences in both lists.   The output is a set if and only if
-- the inputs are disjoint sets.
--
-- > merge [ 1,2, 3,4 ] [ 3,4, 5,6 ]   == [ 1,2,  3,3,4,4,  5,6 ]
-- > merge [ 1, 2,2,2 ] [ 1,1,1, 2,2 ] == [ 1,1,1,1,  2,2,2,2,2 ]
merge :: Ord a => [a] -> [a] -> [a]
merge = mergeBy compare

-- |  The 'mergeBy' function is the non-overloaded version of 'merge'.
mergeBy :: (a -> a -> Ordering) -> [a] -> [a] -> [a]
mergeBy cmp = loop
  where
    loop [] ys  = ys
    loop xs []  = xs
    loop (x:xs) (y:ys)
      = case cmp x y of
         GT -> y : loop (x:xs) ys
         _  -> x : loop xs (y:ys)

-- |  The 'subset' function returns true if the first list is a sub-list
-- of the second.
subset :: Ord a => [a] -> [a] -> Bool
subset = subsetBy compare

-- |  The 'subsetBy' function is the non-overloaded version of 'subset'.
subsetBy :: (a -> a -> Ordering) -> [a] -> [a] -> Bool
subsetBy cmp = loop
  where
    loop [] _ys = True
    loop _xs [] = False
    loop (x:xs) (y:ys)
      = case cmp x y of
         LT -> False
         EQ -> loop xs ys
         GT -> loop (x:xs) ys

{-
-- This is Ian Lynagh's mergesort implementation,  which appeared as
-- Data.List.sort, with the static argument transformation applied.
-- It's not clear whether this modification is truly worthwhile or not.

sort :: Ord a => [a] -> [a]
sort = sortBy compare

sortBy :: (a -> a -> Ordering) -> [a] -> [a]
sortBy cmp = foldt (mergeBy cmp) [] . map (\x -> [x])
-}

-- |  The 'sortOn' function provides the decorate-sort-undecorate idiom,
-- also known as the \"Schwartzian transform\".
sortOn :: Ord b => (a -> b) -> [a] -> [a]
sortOn f  = map snd . sortOn' fst .  map (\x -> let y = f x in y `seq` (y, x))

-- |  This variant of 'sortOn' recomputes the sorting key every comparison.
-- This can be better for functions that are cheap to compute.
-- This is definitely better for projections,  as the decorate-sort-undecorate
-- saves nothing and adds two traversals of the list and extra memory
-- allocation.
sortOn' :: Ord b => (a -> b) -> [a] -> [a]
sortOn' f = sortBy (\x y -> compare (f x) (f y))

-- |  The 'nubSort' function is equivalent to @'nub' '.' 'sort'@,  except
-- that duplicates are removed as it sorts. It is essentially the same
-- implementation as @Data.List.sort@, with 'merge' replaced by 'union'.
-- Thus the performance of 'nubSort' should better than or nearly equal
-- to 'sort' alone.  It is faster than both 'sort' and @'nub' '.' 'sort'@
-- when the input contains significant quantities of duplicated elements.
nubSort :: Ord a => [a] -> [a]
nubSort = nubSortBy compare

-- |  The 'nubSortBy' function is the non-overloaded version of 'nubSort'.
nubSortBy :: (a -> a -> Ordering) -> [a] -> [a]
nubSortBy cmp = foldt' (unionBy cmp) [] . runs
  where
    -- 'runs' partitions the input into sublists that are monotonic,
    -- contiguous,  and non-overlapping.   Descending runs are reversed
    -- and adjacent duplicates are eliminated,  so every run returned is
    -- strictly ascending.

    runs (a:b:xs)
      = case cmp a b of
          LT -> asc b (a:) xs
          EQ -> runs (a:xs)
          GT -> desc b [a] xs
    runs xs = [xs]

    desc a as []  = [a:as]
    desc a as (b:bs)
      = case cmp a b of
          LT -> (a:as) : runs (b:bs)
          EQ -> desc a as bs
          GT -> desc b (a:as) bs

    asc a as [] = [as [a]]
    asc a as (b:bs)
      = case cmp a b of
         LT -> asc b (\ys -> as (a:ys)) bs
         EQ -> asc a as bs
         GT -> as [a] : runs (b:bs)

-- |  The 'nubSortOn' function provides decorate-sort-undecorate for 'nubSort'.
nubSortOn :: Ord b => (a -> b) -> [a] -> [a]
nubSortOn f = map snd . nubSortOn' fst . map (\x -> let y = f x in y `seq` (y, x))

-- |  This variant of 'nubSortOn' recomputes the sorting key for each comparison
nubSortOn' :: Ord b => (a -> b) -> [a] -> [a]
nubSortOn' f = nubSortBy (\x y -> compare (f x) (f y))

-- | On ordered lists,  'nub' is equivalent to 'Data.List.nub', except that
-- it runs in linear time instead of quadratic.   On unordered lists it also
-- removes elements that are smaller than any preceding element.
--
-- > nub [1,1,1,2,2] == [1,2]
-- > nub [2,0,1,3,3] == [2,3]
-- > nub = nubBy (<)
nub :: Ord a => [a] -> [a]
nub = nubBy (<)

-- | The 'nubBy' function is the greedy algorithm that returns a
-- sublist of its input such that:
--
-- > isSortedBy pred (nubBy pred xs) == True
--
-- This is true for all lists,  not just ordered lists,  and all binary
-- predicates,  not just total orders.   On infinite lists,  this statement
-- is true in a certain mathematical sense,  but not a computational one.
nubBy :: (a -> a -> Bool) -> [a] -> [a]
nubBy p []     = []
nubBy p (x:xs) = x : loop x xs
  where
    loop _ [] = []
    loop x (y:ys)
       | p x y     = y : loop y ys
       | otherwise = loop x ys

-- | The function @'foldt'' plus zero@ computes the sum of a list
-- using a balanced tree of operations.  'foldt'' necessarily diverges
-- on infinite lists, hence it is a stricter variant of 'foldt'.
-- 'foldt'' is used in the implementation of 'sort' and 'nubSort'.
foldt' :: (a -> a -> a) -> a -> [a] -> a
foldt' plus zero xs
  = case xs of
      []    -> zero
      (_:_) -> loop xs
  where
    loop [x] = x
    loop xs  = loop (pairs xs)

    pairs (x:y:zs) = plus x y : pairs zs
    pairs zs       = zs

-- | The function @'foldt' plus zero@ computes the sum of a list using
-- a sequence of balanced trees of operations.   Given an appropriate @plus@
-- operator,  this function can be productive on an infinite list, hence it
-- is lazier than 'foldt''.   'foldt' is used in the implementation of
-- 'mergeAll' and 'unionAll'.
foldt :: (a -> a -> a) -> a -> [a] -> a
foldt plus zero = loop
  where
    loop []     = zero
    loop (x:xs) = x `plus` loop (pairs xs)

    pairs (x:y:zs) = plus x y : pairs zs
    pairs zs       = zs

-- helper functions used in 'mergeAll' and 'unionAll'

data People a = VIP a (People a) | Crowd [a]

serve (VIP x xs) = x:serve xs
serve (Crowd xs) = xs

vips xss = [ VIP x (Crowd xs) | (x:xs) <- xss ]

-- | The 'mergeAll' function merges a (potentially) infinite number of
-- ordered lists, under the assumption that the heads of the inner lists
-- are sorted.  An element is duplicated in the result as many times as
-- the total number of occurrences in all inner lists.
--
-- The 'mergeAll' function is closely related to @'foldr' 'merge' []@.
-- The former does not assume that the outer list is finite, whereas
-- the latter does not assume that the heads of the inner lists are sorted.
-- When both sets of assumptions are met,  these two functions are
-- equivalent.
--
-- This implementation of 'mergeAll'  uses a tree of comparisons, and is
-- based on input from Dave Bayer, Heinrich Apfelmus, Omar Antolin Camarena,
-- and Will Ness.  See @CHANGES@ for details.
mergeAll :: Ord a => [[a]] -> [a]
mergeAll = mergeAllBy compare

-- | The 'mergeAllBy' function is the non-overloaded variant of the 'mergeAll'
-- function.
mergeAllBy :: (a -> a -> Ordering) -> [[a]] -> [a]
mergeAllBy cmp = serve . foldt merge' (Crowd []) . vips
  where
    merge' (VIP x xs) ys = VIP x (merge' xs ys)
    merge' (Crowd []) ys = ys
    merge' (Crowd xs) (Crowd ys) = Crowd (mergeBy cmp xs ys)
    merge' xs@(Crowd (x:xt)) ys@(VIP y yt)
      = case cmp x y of
         GT -> VIP y (merge' xs yt)
         _  -> VIP x (merge' (Crowd xt) ys)

-- | The 'unionAll' computes the union of a (potentially) infinite number
-- of lists,  under the assumption that the heads of the inner lists
-- are sorted.  The result will duplicate an element as many times as
-- the maximum number of occurrences in any single list.  Thus, the result
-- is a set if and only if every inner list is a set.
--
-- The 'unionAll' function is closely related to @'foldr' 'union' []@.
-- The former does not assume that the outer list is finite, whereas
-- the latter does not assume that the heads of the inner lists are sorted.
-- When both sets of assumptions are met,  these two functions are
-- equivalent.
--
-- Note that there is no simple way to express 'unionAll' in terms of
-- 'mergeAll' or vice versa on arbitrary valid inputs.  They are related
-- via 'nub' however,  as @'nub' . 'mergeAll' == 'unionAll' . 'map' 'nub'@.
-- If every list is a set,  then @map nub == id@,  and in this special case
-- (and only in this special case) does @nub . mergeAll == unionAll@.
--
-- This implementation of 'unionAll'  uses a tree of comparisons, and is
-- based on input from Dave Bayer, Heinrich Apfelmus, Omar Antolin Camarena,
-- and Will Ness.  See @CHANGES@ for details.
unionAll :: Ord a => [[a]] -> [a]
unionAll = unionAllBy compare

-- | The 'unionAllBy' function is the non-overloaded variant of the 'unionAll'
-- function.
unionAllBy :: (a -> a -> Ordering) -> [[a]] -> [a]
unionAllBy cmp = serve . foldt union' (Crowd []) . vips
  where
    msg = "Data.List.Ordered.unionAllBy:  the heads of the lists are not sorted"

    union' (VIP x xs) ys
       = VIP x $ case ys of
                  Crowd _ -> union' xs ys
                  VIP y yt -> case cmp x y of
                               LT -> union' xs ys
                               EQ -> union' xs yt
                               GT -> error msg
    union' (Crowd []) ys = ys
    union' (Crowd xs) (Crowd ys) = Crowd (unionBy cmp xs ys)
    union' xs@(Crowd (x:xt)) ys@(VIP y yt)
       = case cmp x y of
           LT -> VIP x (union' (Crowd xt) ys)
           EQ -> VIP x (union' (Crowd xt) yt)
           GT -> VIP y (union' xs yt)

main :: IO ()
main = do
  c <- getContents
  let l = (map (read :: String -> Int) . words) c
  let (n : m : k : ll) = l
  let a = [(0, 1, y, 0) | y <- [1..n]] ++ [(0, 2, y, 0) | y <- [1..m]] ++ mt ll 1
  let b = reverse a
  let b1 = filter (\(i, x, y, z) -> case x of {1 -> True; _ -> False}) b
  let b2 = filter (\(i, x, y, z) -> case x of {2 -> True; _ -> False}) b
  let c1 = nubSortBy fc b1
  let c2 = nubSortBy fc b2
--  putStrLn $ show $ sum (map (\(i, x, y, z) -> z) c1 :: [Int])
--  putStrLn $ show $ sum (map (\(i, x, y, z) -> z) c2 :: [Int])
  let c = [[q | (i2,x2,y2,z2) <- c2, let i = y1, let j = y2, let q = case compare i1 i2 of {GT -> z1; EQ -> z1; LT -> z2}] | (i1,x1,y1,z1) <- c1]
  putStrLn $ unlines . map (unwords . (map show)) $ c

fc :: (Int,Int,Int,Int) -> (Int,Int,Int,Int) -> Ordering
fc (i1,x1,y1,z1) (i2,x2,y2,z2) = compare y1 y2

mt :: [Int] -> Int -> [(Int, Int, Int, Int)]
mt [] _ = []
mt (a : b : c : ll) n = (n,a,b,c) : mt ll (n+1)

import Data.List(sort,sortBy,intersect)

--import Data.List.Ordered

-- |  The 'union' function computes the union of two ordered lists.
-- An element occurs in the output as many times as the maximum number
-- of occurrences in either input.  The output is a set if and only if
-- both inputs are sets.
--
-- > union [ 1,2, 3,4 ] [ 3,4, 5,6 ]   == [ 1,2, 3,4, 5,6 ]
-- > union [ 1, 2,2,2 ] [ 1,1,1, 2,2 ] == [ 1,1,1, 2,2,2 ]
union :: Ord a => [a] -> [a] -> [a]
union = unionBy compare

-- |  The 'unionBy' function is the non-overloaded version of 'union'.
unionBy :: (a -> a -> Ordering) -> [a] -> [a] -> [a]
unionBy cmp = loop
  where
     loop [] ys = ys
     loop xs [] = xs
     loop (x:xs) (y:ys)
       = case cmp x y of
          LT -> x : loop xs (y:ys)
          EQ -> x : loop xs ys
          GT -> y : loop (x:xs) ys

-- |  The 'nubSort' function is equivalent to @'nub' '.' 'sort'@,  except
-- that duplicates are removed as it sorts. It is essentially the same
-- implementation as @Data.List.sort@, with 'merge' replaced by 'union'.
-- Thus the performance of 'nubSort' should better than or nearly equal
-- to 'sort' alone.  It is faster than both 'sort' and @'nub' '.' 'sort'@
-- when the input contains significant quantities of duplicated elements.
nubSort :: Ord a => [a] -> [a]
nubSort = nubSortBy compare

-- |  The 'nubSortBy' function is the non-overloaded version of 'nubSort'.
nubSortBy :: (a -> a -> Ordering) -> [a] -> [a]
nubSortBy cmp = foldt' (unionBy cmp) [] . runs
  where
    -- 'runs' partitions the input into sublists that are monotonic,
    -- contiguous,  and non-overlapping.   Descending runs are reversed
    -- and adjacent duplicates are eliminated,  so every run returned is
    -- strictly ascending.

    runs (a:b:xs)
      = case cmp a b of
          LT -> asc b (a:) xs
          EQ -> runs (a:xs)
          GT -> desc b [a] xs
    runs xs = [xs]

    desc a as []  = [a:as]
    desc a as (b:bs)
      = case cmp a b of
          LT -> (a:as) : runs (b:bs)
          EQ -> desc a as bs
          GT -> desc b (a:as) bs

    asc a as [] = [as [a]]
    asc a as (b:bs)
      = case cmp a b of
         LT -> asc b (\ys -> as (a:ys)) bs
         EQ -> asc a as bs
         GT -> as [a] : runs (b:bs)

-- | The function @'foldt'' plus zero@ computes the sum of a list
-- using a balanced tree of operations.  'foldt'' necessarily diverges
-- on infinite lists, hence it is a stricter variant of 'foldt'.
-- 'foldt'' is used in the implementation of 'sort' and 'nubSort'.
foldt' :: (a -> a -> a) -> a -> [a] -> a
foldt' plus zero xs
  = case xs of
      []    -> zero
      (_:_) -> loop xs
  where
    loop [x] = x
    loop xs  = loop (pairs xs)

    pairs (x:y:zs) = plus x y : pairs zs
    pairs zs       = zs

main :: IO ()
main = do
  c <- getContents
  let l = (map (read :: String -> Int) . words) c
  let (n : m : k : ll) = l
  let a = [(0, 1, y, 0) | y <- [1..n]] ++ [(0, 2, y, 0) | y <- [1..m]] ++ mt ll 1
  let b = reverse a
  let b1 = filter (\(i, x, y, z) -> case x of {1 -> True; _ -> False}) b
  let b2 = filter (\(i, x, y, z) -> case x of {2 -> True; _ -> False}) b
  let c1 = nubSortBy fc b1
  let c2 = nubSortBy fc b2
  let c = [[q | (i2,x2,y2,z2) <- c2, let i = y1, let j = y2, let q = case compare i1 i2 of {GT -> z1; EQ -> z1; LT -> z2}] | (i1,x1,y1,z1) <- c1]
  putStrLn $ unlines . map (unwords . (map show)) $ c

mt :: [Int] -> Int -> [(Int, Int, Int, Int)]
mt [] _ = []
mt (a : b : c : ll) n = (n,a,b,c) : mt ll (n+1)

fc :: (Int,Int,Int,Int) -> (Int,Int,Int,Int) -> Ordering
fc (i1,x1,y1,z1) (i2,x2,y2,z2) = compare y1 y2

{-# LANGUAGE FlexibleContexts, ScopedTypeVariables #-}
{-# OPTIONS_GHC -O2 #-}

import Control.Applicative
import Control.Monad
import Control.Monad.ST.Safe
import Control.Monad.State
import Data.Array.IArray
import Data.Array.IO.Safe
import Data.Array.MArray.Safe
import Data.Array.ST.Safe
import Data.Array.Unboxed
import Data.Char
import Data.Function
-- import Data.Graph
import Data.Int
import Data.List
import Data.List.Split
import Data.Maybe
import Data.Set (Set)
import qualified Data.Set as Set
-- import Data.Tree
import Data.Tuple
import Data.Map (Map)
import qualified Data.Map as Map
import Data.IntMap (IntMap)
import qualified Data.IntMap as IntMap
import qualified Data.ByteString.Char8 as B
-- import Debug.Trace

import qualified Data.ByteString.Lazy.Builder as BB

import Data.Monoid
import System.IO

-- getInts = fmap (map read . words) getLine
getInts = unfoldr (B.readInt . B.dropWhile isSpace) <$> B.getLine

main = do
  [n, m, k] <- getInts

  as <- newArray (1, n) 0 :: IO (IOUArray Int Int)
  bs <- newArray (1, m) 0 :: IO (IOUArray Int Int)
  cs <- newArray (1, k) 0 :: IO (IOUArray Int Int)

  forM_ [1..k] $ \i -> do
    [t, j, c] <- getInts
    if t == 1
      then writeArray as j i
      else writeArray bs j i
    writeArray cs i c

  as' <- freeze as :: IO (UArray Int Int)
  bs' <- freeze bs :: IO (UArray Int Int)
  cs' <- freeze cs :: IO (UArray Int Int)

  forM_ [1..n] $ \i -> do
    let
      f j = if k == 0 then 0 else cs'!k where k = max (as'!i) (bs'!j)

      l = mconcat $ map (\j -> (BB.intDec $ f j) <> BB.char8 ' ') [1..m]

    BB.hPutBuilder stdout $ l <> BB.char8 '\n'

{-# LANGUAGE FlexibleContexts, ScopedTypeVariables #-}
{-# OPTIONS_GHC -O2 #-}

import Control.Applicative
import Control.Monad
import Control.Monad.ST.Safe
import Control.Monad.State
import Data.Array.IArray
import Data.Array.IO.Safe
import Data.Array.MArray.Safe
import Data.Array.ST.Safe
import Data.Array.Unboxed
import Data.Char
import Data.Function
-- import Data.Graph
import Data.Int
import Data.List
import Data.List.Split
import Data.Maybe
import Data.Set (Set)
import qualified Data.Set as Set
-- import Data.Tree
import Data.Tuple
import Data.Map (Map)
import qualified Data.Map as Map
import Data.IntMap (IntMap)
import qualified Data.IntMap as IntMap
import qualified Data.ByteString.Char8 as B
-- import Debug.Trace

import qualified Data.ByteString.Lazy.Builder as BB

import Data.Monoid
import System.IO

-- getInts = fmap (map read . words) getLine
getInts = unfoldr (B.readInt . B.dropWhile isSpace) <$> B.getLine

main = do
  [n, m, k] <- getInts

  as <- newArray (1, n) 0 :: IO (IOUArray Int Int)
  bs <- newArray (1, m) 0 :: IO (IOUArray Int Int)
  cs <- newArray (1, k) 0 :: IO (IOUArray Int Int)

  forM_ [1..k] $ \i -> do
    [t, j, c] <- getInts
    if t == 1
      then writeArray as j i
      else writeArray bs j i
    writeArray cs i c

  as' <- freeze as :: IO (UArray Int Int)
  bs' <- freeze bs :: IO (UArray Int Int)
  cs' <- freeze cs :: IO (UArray Int Int)

  let
    r = [map (f i) [1..m] | i <- [1..n]]
      where
        f i j = if k == 0 then 0 else cs'!k where k = max (as'!i) (bs'!j)

  putStr $ unlines $ map (unwords . map show) r

{-# LANGUAGE FlexibleContexts, ScopedTypeVariables #-}
{-# OPTIONS_GHC -O2 #-}

import Control.Applicative
import Control.Monad
import Control.Monad.ST.Safe
import Control.Monad.State
import Data.Array.IArray
import Data.Array.IO.Safe
import Data.Array.MArray.Safe
import Data.Array.ST.Safe
import Data.Array.Unboxed
import Data.Char
import Data.Function
-- import Data.Graph
import Data.Int
import Data.List
import Data.List.Split
import Data.Maybe
import Data.Set (Set)
import qualified Data.Set as Set
-- import Data.Tree
import Data.Tuple
import Data.Map (Map)
import qualified Data.Map as Map
import Data.IntMap (IntMap)
import qualified Data.IntMap as IntMap
import qualified Data.ByteString.Char8 as B
-- import Debug.Trace

import qualified Data.ByteString.Lazy.Builder as BB

import Data.Monoid
import System.IO

-- getInts = fmap (map read . words) getLine
getInts = unfoldr (B.readInt . B.dropWhile isSpace) <$> B.getLine

main = do
  [n, m, k] <- getInts

  as <- newArray (1, n) 0 :: IO (IOUArray Int Int)
  bs <- newArray (1, m) 0 :: IO (IOUArray Int Int)
  cs <- newArray (1, k) 0 :: IO (IOUArray Int Int)

  forM_ [1..k] $ \i -> do
    [t, j, c] <- getInts
    if t == 1
      then writeArray as j i
      else writeArray bs j i
    writeArray cs i c

  as' <- freeze as :: IO (UArray Int Int)
  bs' <- freeze bs :: IO (UArray Int Int)
  cs' <- freeze cs :: IO (UArray Int Int)

  forM_ [1..n] $ \i -> do
    let
      f j = if k == 0 then 0 else cs'!k where k = max (as'!i) (bs'!j)

    putStrLn $ unlines $ map show $ map f [1..m]

{-# LANGUAGE FlexibleContexts, ScopedTypeVariables #-}
{-# OPTIONS_GHC -O2 #-}

import Control.Applicative
import Control.Monad
import Control.Monad.ST.Safe
import Control.Monad.State
import Data.Array.IArray
import Data.Array.IO.Safe
import Data.Array.MArray.Safe
import Data.Array.ST.Safe
import Data.Array.Unboxed
import Data.Char
import Data.Function
-- import Data.Graph
import Data.Int
import Data.List
import Data.List.Split
import Data.Maybe
import Data.Set (Set)
import qualified Data.Set as Set
-- import Data.Tree
import Data.Tuple
import Data.Map (Map)
import qualified Data.Map as Map
import Data.IntMap (IntMap)
import qualified Data.IntMap as IntMap
import qualified Data.ByteString.Char8 as B
-- import Debug.Trace

import qualified Data.ByteString.Lazy.Builder as BB

import Data.Monoid
import System.IO

-- getInts = fmap (map read . words) getLine
getInts = unfoldr (B.readInt . B.dropWhile isSpace) <$> B.getLine

main = do
  [n, m, k] <- getInts

  as <- newArray (1, n) 0 :: IO (IOUArray Int Int)
  bs <- newArray (1, m) 0 :: IO (IOUArray Int Int)
  cs <- newArray (1, k) 0 :: IO (IOUArray Int Int)

  forM_ [1..k] $ \i -> do
    [t, j, c] <- getInts
    if t == 1
      then writeArray as j i
      else writeArray bs j i
    writeArray cs i c

  as' <- freeze as :: IO (UArray Int Int)
  bs' <- freeze bs :: IO (UArray Int Int)
  cs' <- freeze cs :: IO (UArray Int Int)

  forM_ [1..n] $ \i -> do
  let
    r = [map (f i) [1..m] | i <- [1..n]]
      where
        f i j = if k == 0 then 0 else cs'!k where k = max (as'!i) (bs'!j)

  putStr $ unlines $ map (unwords . map show) r


main = interact $ unlines . map (format . solve) . parse . lines

parse (l:ls) = take (readInt l) $ go ls
  where go ys = x:go ys'
          where (x,ys') = parse1 ys

parse1 (x:xs) = (read x, xs)

readInt = foldl1 (\x y -> x*10 + y) . map (\x -> fromEnum x - fromEnum '0')

solve n = n:[1..n-1]

format = unwords . map show

{-# OPTIONS_GHC -O2 #-}

main = interact $ unlines . map (format . solve) . parse . lines

parse (l:ls) = take (readInt l) $ go ls
  where go ys = x:go ys'
          where (x,ys') = parse1 ys

parse1 (x:xs) = (readInt x, xs)

readInt = foldl1 (\x y -> x*10 + y) . map (\x -> fromEnum x - 48)

solve n = n:[1..n-1]

format = unwords . map show

main = interact $ unlines . map (format . solve) . parse . lines

parse (l:ls) = take (read l) $ go ls
  where go ys = x:go ys'
          where (x,ys') = parse1 ys

parse1 (x:xs) = (read x, xs)

solve n = n:[1..n-1]

format = unwords . map show

--
-- Michael V. Antosha
-- 2022
-- Michael.Antosha@gmail.com
--

{-# language Safe                      #-}
{-# language ImportQualifiedPost       #-}
{-# language NoMonomorphismRestriction #-}

{-# options_ghc -O3                              #-}

{-# options_ghc -Weverything                     #-}
{-# options_ghc -Werror                          #-}

{-# options_ghc -Wno-missing-import-lists        #-}
{-# options_ghc -Wno-missing-local-signatures    #-}

import Prelude               hiding (getLine)
import Control.Arrow
import Control.Monad
import Data.ByteString.Char8 qualified as B
import Data.Char
import Data.List             qualified as L

ri = readInts <$> B.getLine :: IO [Int]
  where
    readInts  = L.unfoldr ((second dropSpace <$>) . B.readInt) . dropSpace
    dropSpace = B.dropWhile isSpace

main :: IO ()
main = do
    [t] <- ri
    tcs <- replicateM t $ do
        [n] <- ri
        return n
    mapM_ (putStrLn.showL.solve) tcs

showL = unwords . map show

solve n = take n . drop (n-1) . cycle $ [1..n]


--
-- Michael V. Antosha
-- 2022
-- Michael.Antosha@gmail.com
--

{-# LANGUAGE Safe                #-}
{-# LANGUAGE ImportQualifiedPost #-}

{-# language NoMonomorphismRestriction #-}

{-# options_ghc -O3                              #-}

{-# options_ghc -Weverything                     #-}
{-# options_ghc -Werror                          #-}

{-# options_ghc -Wno-safe                        #-}     -- no warning if inferred as safe
{-# options_ghc -Wno-all-missed-specialisations  #-}     -- "Could not specialise..." when -O1
{-# options_ghc -Wno-missing-import-lists        #-}
{-# options_ghc -Wno-missing-local-signatures    #-}

import Prelude               hiding (getLine)
import Control.Arrow
import Control.Monad
import Data.ByteString.Char8 qualified as B
import Data.Char
import Data.List             qualified as L

ri = readInts <$> B.getLine :: IO [Int]
  where
    readInts  = L.unfoldr ((second dropSpace <$>) . B.readInt) . dropSpace
    dropSpace = B.dropWhile isSpace

main :: IO ()
main = do
    [t] <- ri
    tcs <- replicateM t $ do
        [n,m] <- ri
        return (n,m)
    mapM_ (putStrLn.showB.solve) tcs

showB False = "Tonya"
showB True  = "Burenka"

solve (n,m) = isFirstWins
  where
    isFirstWins = odd $ (n-1) + (m-1)

decide :: Int -> IO()
decide t | t <= 0 = return ()
         | otherwise = do
            vars <- getLine >>= (return . words)
            let intoInt = return . ((\a -> a `mod` 2 + 1) . (read :: String -> Int))

            n <- intoInt $ head vars
            m <- intoInt $ head $ tail vars

            --Sup
            --putStrLn ("n = " ++ (show n))
            --putStrLn ("m = " ++ (show m))

            if (n + m) `mod` 2 == 1
            then putStrLn "Burenka"
            else putStrLn "Tonya"
            decide $ t-1

main :: IO ()
main = do
    t <- getLine >>= (return . (read :: String -> Int))
    decide t


import Control.Monad (replicateM_)
import Data.Bits ((.&.))
main = read <$> getLine >>= flip replicateM_ scase
scase = read <$> getLine >>= print . minNum

s2P :: Int -> Int
s2P x = x .&. (-x)

minNum :: Int -> Int
minNum x | s2P x == x = if x == 1 then 3 else x+1
         | otherwise = s2P x

import Control.Arrow ((>>>))
import Data.Bits ((.&.))

-- https://codeforces.com/problemset/problem/1688/A
solve :: Int -> Int
solve x =
    let y = x .&. (- x)
     in incWhile
            (\z -> z == x || z .&. x == 0)
            y

incWhile :: (Int -> Bool) -> Int -> Int
incWhile p x = if p x then incWhile p (x + 1) else x

main :: IO ()
main =
    interact $
        lines
            >>> drop 1
            >>> map
                ( read
                    >>> solve
                    >>> show
                )
            >>> unlines

module Main where

getMinNumber :: Int -> Int
getMinNumber 1 = 3
getMinNumber n = one n + isPower2 n
  where
    isPower2 m
      | even m = isPower2 (m `div` 2)
      | m == 1 = 1
      | otherwise = 0
    one m
      | even m = 2 * one (m `div` 2)
      | otherwise = 1

solution :: [Int] -> [Int]
solution (_: xs) = map getMinNumber xs
solution _ = undefined

main :: IO ()
main = interact $ unlines . map show . solution . map read . words

-- boilerplate {{{1
-- vim: foldmethod=marker
-- pragmas {{{2
{-# LANGUAGE BangPatterns        #-}
{-# LANGUAGE DeriveFunctor       #-}
{-# LANGUAGE DeriveFoldable      #-}
{-# LANGUAGE DeriveTraversable   #-}
{-# LANGUAGE FlexibleContexts    #-}
{-# LANGUAGE StandaloneDeriving  #-}
{-# LANGUAGE TupleSections       #-}
{-# LANGUAGE TypeApplications    #-}

module Main where -- {{{2

import Control.Applicative
import Control.Monad
import Control.Monad.ST
import Data.Array.IArray
import Data.Array.ST
import Data.Array.Unboxed
import Data.Bifunctor
import Data.Bits
import Data.Bool
import Data.Char
import Data.Foldable hiding ( sum, product )
import Data.Function
import Data.Functor
import Data.List hiding ( sum, product )
import Data.Maybe
import Data.Monoid
import Data.Ord
import Data.Semigroup ( Min(..), Max(..) )
import Data.Traversable
import Data.Tuple
import Debug.Trace
import Prelude hiding ( sum, product )
import System.IO
import qualified Data.ByteString.Char8 as C
import qualified Data.IntSet           as IS
import qualified Data.Map              as LM
import qualified Data.Map.Strict       as M
import qualified Data.Set              as S

-- recursion schemes {{{2
data Tree a b = Tree a (Forest a b) deriving (Eq,Ord,Show,Functor)
type Forest a b = [b]
deriving instance Foldable (Tree a)
deriving instance Traversable (Tree a)

hylo :: Functor f => (f b -> b) -> (a -> f a) -> a -> b
hylo f g = h where h = f . fmap h . g

newtype Term f = In { out :: f (Term f) }
type Algebra f a = f a -> a
type Coalgebra f a = a -> f a

cata :: Functor f => Algebra f a -> Term f -> a
cata f = c where c = f . fmap c . out

ana :: Functor f => Coalgebra f a -> a -> Term f
ana g = a where a = In . fmap a . g

treeCoalgebra :: -- {{{2
    Int -> [[Int]] -> (Int -> a) ->
    Coalgebra (Tree a) (Int,Int)
treeCoalgebra n uvs f = coalg
  where
    coalg (curr,prev) = Tree (f curr) $ map (,curr) $ lookup curr prev
    lookup curr prev = IS.elems $ IS.delete prev $ uvary ! curr
    uvary = runSTArray $ do
        ary <- newArray (1,n) IS.empty
        let insert u 1 = pure ()
            insert u v = readArray ary u >>= writeArray ary u . IS.insert v
        for_ uvs $ \[u,v] -> insert u v >> insert v u
        pure ary

data V2 a = V2 !a !a -- {{{2
    deriving ( Eq, Ord, Show )
instance Num a => Num (V2 a) where
    (+) = liftA2 (+)
    (-) = liftA2 (-)
    (*) = liftA2 (*)
    abs = fmap abs
    negate = fmap negate
    signum = fmap signum
    fromInteger = pure . fromInteger
instance Functor V2 where
    fmap f (V2 a b) = V2 (f a) (f b)
    a <$ _ = V2 a a
instance Applicative V2 where
    pure a = V2 a a
    V2 a b <*> V2 d e = V2 (a d) (b e)
instance Monad V2 where
    V2 a b >>= f = V2 a' b' where
        V2 a' _ = f a
        V2 _ b' = f b
instance Foldable V2 where
    foldMap f (V2 a b) = f a `mappend` f b
    null _ = False
    length _ = 2
instance Traversable V2 where
    traverse f (V2 a b) = V2 <$> f a <*> f b

data V3 a = V3 !a !a !a -- {{{2
    deriving ( Eq, Ord, Show )
instance Num a => Num (V3 a) where
    (+) = liftA2 (+)
    (-) = liftA2 (-)
    (*) = liftA2 (*)
    abs = fmap abs
    negate = fmap negate
    signum = fmap signum
    fromInteger = pure . fromInteger
instance Functor V3 where
    fmap f (V3 a b c) = V3 (f a) (f b) (f c)
    a <$ _ = V3 a a a
instance Applicative V3 where
    pure a = V3 a a a
    V3 a b c <*> V3 d e f = V3 (a d) (b e) (c f)
instance Monad V3 where
    V3 a b c >>= f = V3 a' b' c' where
        V3 a' _ _ = f a
        V3 _ b' _ = f b
        V3 _ _ c' = f c
instance Foldable V3 where
    foldMap  f (V3 a b c) = f a `mappend` f b `mappend` f c
    null _ = False
    length _ = 3
instance Traversable V3 where
    traverse f (V3 a b c) = V3 <$> f a <*> f b <*> f c

-- utilites {{{2
readInt s = let Just (i,_) = C.readInt s in i :: Int
getInt = readInt <$> C.getLine
getInts = map readInt . C.words <$> C.getLine
ynq = putStrLn . bool "No" "Yes"
ynQ = putStrLn . bool "NO" "YES"
modulus = 10^9 + 7 :: Int
mod' x = rem x modulus
mprint :: Show a => String -> Maybe a -> IO ()
mprint s = maybe (putStrLn s) print
tri n = quot (n * n + n) 2
ifM :: Monad m => m Bool -> m a -> m a -> m a
ifM b t e = b >>= bool e t
whenM :: Monad m => m Bool -> m () -> m ()
whenM b t = ifM b t (pure ())
gcount g@(x:_) = (x, length g)
sum t     = foldl' (+) 0 t
product t = foldl' (*) 1 t

-- }}}1

main = getInt >>= flip replicateM_ docase
-- main = docase

docase = do
    [x] <- getInts
    print $ solve x

solve x
    | ay /= x = ay
    | otherwise = min by ny
  where
    (y:_,n:_) = partition (testBit x) [0..]
    ay = setBit 0 y
    by = setBit ay (y+1)
    ny = setBit ay n

import Data.Bits

powersOfTwo :: [Int]
powersOfTwo = [2^i | i <- [0..30]]

solve :: Int -> Int
solve x = let powerIntersecingX = filter (\power -> (x .&. power) > 0) powersOfTwo in
          if length powerIntersecingX > 1
          then head powerIntersecingX
          else if head powerIntersecingX /= 1
               then head powerIntersecingX + 1
               else head powerIntersecingX + 2

mainLoop :: Int -> IO ()
mainLoop t | t <= 0 = return ()
           | otherwise = do number <- (readLn :: IO Int)
                            print (solve number)
                            mainLoop (t - 1)

main :: IO ()
main = do t <- (readLn :: IO Int)
          mainLoop t


import Data.List
import Data.Function

solve :: [(Int, Int)] -> [Int]
solve xs =
  let
    d = groupDivider $ sort xs
    g = groups d xs
  in validate g

groupDivider :: [(Int, Int)] -> Int
groupDivider ((l, r) : xs) = go r xs
  where
    go r [] = r
    go r ((x, y) : ys)
      | x > r = r
      | otherwise = go (max r y) ys

groups :: Int -> [(Int, Int)] -> [Int]
groups d = map (f . (<= d). snd)
  where f True = 1
        f False = 2

validate :: [Int] -> [Int]
validate xs = if 2 `elem` xs then xs else [-1]

list2tuple :: [Int] -> (Int, Int)
list2tuple [x, y] = (x, y)

parseInput :: String -> [[Int]]
parseInput = map (map read . words) . lines

splitTestCases :: [[Int]] -> [[(Int, Int)]]
splitTestCases = map (map list2tuple) .
                 filter ((==2) . length . head) .
                 groupBy ((==) `on` length)

formatOutput :: [[Int]] -> String
formatOutput = unlines . map (unwords . map show)

main = interact $ formatOutput . map solve . splitTestCases . parseInput

import Text.Printf
import Data.List
import Data.Functor
import Control.Applicative
import Prelude
import Control.Monad
import Data.Maybe
import Data.Function
import Data.Array
import qualified Data.ByteString.Char8 as B8
import Data.Foldable (foldr')

readInt :: String -> Int
readInt = Prelude.read

type Answer = Maybe ([Int], [Int], Int)

foldAnswer :: ((Int, Int), Int) -> Answer -> Answer
foldAnswer ((l, r), i) answer = do
    (a1, a2, ll) <- answer
    if r < ll then
        return (i : a2, a1, l)
    else
        return (i : a1, a2, min l ll)

solve :: [(Int, Int)] -> Maybe [Int]
solve segments = do
    let sortedSegments = sortBy (compare `on` (\((x, y), z) -> ((y, x), z))) $ zip segments [1..]
    (a1, a2, ll) <- foldr' foldAnswer (Just ([], [], 400000)) sortedSegments
    if null a1 || null a2 then
        Nothing
    else
        Just . map snd . sort $ (zip a1 (repeat 1) ++ zip a2 (repeat 2))

main :: IO ()
main = do
    testCount <- readInt <$> getLine
    replicateM_ testCount $ do
        n <- readInt <$> getLine
        segments <- replicateM n $ ((\[l, r] -> (l, r)) . map readInt . words) <$> getLine
        let answer = fromMaybe [-1] $ solve segments
        forM_ answer $ printf "%d "
        printf "\n"

{- We can start out by picking one segment, and arbitrarily put it in a group. Then every other
 - segment that intersect with it have to be put in the same group, etc. If there are at least one
 - element in the rest, we're good. Now that might be very naive, and it uses nothing about segment
 - intersection other than its equivalence relation nature. The running time is definitely in big
 - theta of n squared: it will not fit. Let's nonetheless write this naive solution to get a better
 - view of the problem.
 -
 - The upper bound on li and ri suggests that they could be used to index an array.
 -
 - Update: as expected, the naive solution takes far too much time. There has to be a much better
 - way, using the fact that we are specifically dealing with intervals.
 - Reupdate: apparently the naive solution is fast enough for some inputs of maximum size. There
 - might be another factor that differentiates possible inputs. -}

import Data.List (intersperse, sortBy)
import Data.Ord (comparing)

sortOn :: Ord b => (a -> b) -> [a] -> [a]
sortOn f =
  map snd . sortBy (comparing fst) . map (\x -> let y = f x in y `seq` (y, x))

main = interact (format . solve . parse)

parse :: String -> [[IndexedInterval]]
parse = reverse . parseQueries . words

parseQueries :: [String] -> [[IndexedInterval]]
parseQueries (ns:s) = let
    f 0 _ ret = ret
    f n xs ret = let (s0, q) = parseQuery xs in f (n - 1) s0 (q:ret)
    in
    f (read ns :: Integer) s []

parseQuery :: [String] -> ([String], [IndexedInterval])
parseQuery (ns:s) = let
    f 0 _ xs ret = (xs, ret)
    f rn i (x0:x1:xs) ret = f (rn - 1) (i + 1) xs (IndexedInterval {
        index = i,
        interval = Interval { begin=(read x0), end=(read x1) }
    }:ret)
    f _ _ _ _ = ([], [])
    in
    f (read ns :: Integer) 0 s []
parseQuery [] = ([], [])

{- Introducing these types does not make sense in a Codeforces context, but it might help with
 - Haskell the first few times. -}
data Interval = Interval { begin :: Integer, end :: Integer } deriving (Show)
data IndexedInterval = IndexedInterval { index :: Integer, interval :: Interval } deriving (Show)

solve = map solveQuery

solveQuery :: [IndexedInterval] -> Maybe [Bool]
solveQuery a = let (b, c) = (partitionIntervals . orderIntervals) a in reorderPartition b c

orderIntervals :: [IndexedInterval] -> [IndexedInterval]
orderIntervals a = sortOn (begin . interval) a

{- Note: the intervals passed as argument MUST be sorted with respect to their left boundary. -}
partitionIntervals :: [IndexedInterval] -> ([IndexedInterval], [IndexedInterval])
partitionIntervals [] = ([], [])
partitionIntervals (x:a) = let
    f u b [] = (b, [])
    f u b (i:c) = if end u < (begin . interval) i then (b, (i:c))
        else f (union u (interval i)) (i:b) c
    in f (interval x) [x] a

reorderPartition :: [IndexedInterval] -> [IndexedInterval] -> Maybe [Bool]
reorderPartition _ [] = Nothing
reorderPartition a b = Just $ map snd $ sortOn fst $ (map (\i -> (index i, False)) a) ++ (map (\i -> (index i, True)) b)

{- Only makes sense when passed intersecting intervals. -}
union :: Interval -> Interval -> Interval
union (Interval l0 r0) (Interval l1 r1) = Interval (min l0 l1) (max r0 r1)

{- Returns a query result in the requested output form -}
formatQuery :: Maybe [Bool] -> String
formatQuery Nothing = "-1"
formatQuery (Just a) = intersperse ' ' $ map (\x -> if x then '2' else '1') a

format :: [Maybe [Bool]] -> String
format = unlines . (map formatQuery)

{-# LANGUAGE BangPatterns #-}
import System.IO
import Control.Applicative
import Control.Monad
import Data.Char
import Data.List
import Data.Maybe
import Data.Monoid
import Data.Function (fix, on)
import Data.Array (Array, array, (!))
import Data.ByteString.Lazy.Builder
import Data.ByteString.Lazy.Builder.ASCII
import qualified Data.Set as Set
import qualified Data.Map.Strict as Map
import qualified Data.ByteString as BS
import qualified Data.ByteString.Char8 as BS8

construct :: (BS.ByteString -> Maybe (a, BS.ByteString)) -> BS.ByteString -> [a]
construct reader str
    | BS.null str = []
    | isSpace (BS8.head str) = construct reader (BS8.tail str)
    | otherwise = let Just (i, other) = reader str in i : construct reader other

getInts :: IO [Int]
getInts = construct BS8.readInt <$> BS.getLine

getIntegers :: IO [Integer]
getIntegers = construct BS8.readInteger <$> BS.getLine

printInts :: [Int] -> IO ()
printInts = putStrLn . intercalate " " . map show

check (([_,sr],_):range) = go range sr 2
    where go [] _ _ = -1
          go (([l,r], _):s) x i
            | l > x = i
            | otherwise = go s (max x r) (i+1)

solve _ = do
    [q] <- getInts
    range <- forM [1..q] (\_ -> getInts)
    let sorted = sortBy (compare `on` (head . fst)) (zip range [1..])
    let k = check sorted
    let v = zip (map snd sorted) (map (\x -> if x < k then 1 else 2) [1..q])
    if k == -1 then print k else (printInts $ map snd $ sort v)

main = do
    [t] <- getInts
    mapM_ solve [1..t]

import Data.List
import Data.Function

solve :: [(Int, Int)] -> String
solve xs =
  let
    d = groupDivider $ sort xs
    g = groups d xs
    v = validate g
  in unwords $ map show v

groupDivider :: [(Int, Int)] -> Int
groupDivider ((l, r) : xs) = go r xs
  where
    go r [] = r
    go r ((x, y) : ys)
      | x > r = r
      | otherwise = go (max r y) ys

groups :: Int -> [(Int, Int)] -> [Int]
groups d = map (f . (<= d). snd)
  where f True = 1
        f False = 2

validate :: [Int] -> [Int]
validate xs = if 2 `elem` xs then xs else [-1]

list2tuple :: [Int] -> (Int, Int)
list2tuple [x, y] = (x, y)

parseInput :: String -> [[Int]]
parseInput = map (map read . words) . lines

splitTestCases :: [[Int]] -> [[(Int, Int)]]
splitTestCases = map (map list2tuple) .
                 filter ((==2) . length . head) .
                 groupBy ((==) `on` length)

main = interact $ unlines . map solve . splitTestCases . parseInput

-- Educational Codeforces Round #58 (C), Contest 1101, Problem set ?.

{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE Safe #-}
{-# LANGUAGE TupleSections#-}
{-# LANGUAGE ExplicitForAll #-}

import Data.Bits
import Data.List
import qualified Data.ByteString.Char8 as BS
import qualified Data.ByteString.Lazy.Char8 as BSL
import Data.IntMap.Strict (IntMap)
import qualified Data.IntMap.Strict as IM
import qualified Data.Array.IArray as A
import qualified Data.Array.MArray.Safe as A
-- import qualified Data.Array.MArray as A
import Data.Array (Array)
import Data.Array.Unboxed (UArray)
import Data.Array.IArray (IArray)
import Data.Array.MArray.Safe (MArray)
import Data.Array.IO.Safe (IOArray, IOUArray)
import Data.Array.ST.Safe (STArray, STUArray, runSTArray, runSTUArray)
{-
import qualified Data.Vector.Unboxed as VU
import qualified Data.Vector.Unboxed.Mutable as VUM
-}
import Control.Monad
import Control.Monad.ST.Safe
-- import Control.Monad.ST
import Control.Applicative
import Data.Maybe
import Data.Tuple
import Data.Ord
import Control.Monad.State.Strict
import Data.Int
import Data.Word
import Data.STRef
import Data.IORef
import Data.Function

main :: IO ()
main = do
  t <- read <$> getLine
  replicateM_ t $ do
    n <- read <$> getLine
    lrs <- replicateM n
      $ (\[l,r] -> (l,r)) . map read . words <$> getLine
    putStrLn $ fromMaybe "-1" $ unwords . map show <$> query lrs

query :: [(Int,Int)] -> Maybe [Int]
query lrs = fmap (\cp -> map (\(l,r) -> if r <= cp then 1 else 2) lrs) cutpt
  where
    cutpt = fmap fst $ find ((== 0) . snd)
      $ init $ merge $ sort (lrs >>= \(l,r) -> [(l,1),(r,-1)])
    merge [] = []
    merge ((i,x):xs) = go i x xs
      where
        go !i !acc [] = [(i,acc)]
        go !i !acc ((j,x):xs) | i == j    = go i (acc+x) xs
                              | otherwise = (i,acc) : go j (acc+x) xs

import Text.Printf
import Data.List
import Data.Functor
import Control.Applicative
import Prelude
import Control.Monad
import Data.Maybe
import Data.Function
import Data.Array
import qualified Data.ByteString.Char8 as B8
import Data.Foldable (foldr')

readInt :: String -> Int
readInt = Prelude.read

type Answer = Maybe (([Int], Int), ([Int], Int))

foldAnswer :: ((Int, Int), Int) -> Answer -> Answer
foldAnswer ((l, r), id) answer = do
    ((a1, l1), (a2, l2)) <- answer
    if r < l2 then
        if l < l1 then
            return ((id : a2, l), (a1, l1))
        else
            return ((a1, l1), (id : a2, l))
    else
        Nothing

solve :: [(Int, Int)] -> Maybe [Int]
solve segments = do
    let sortedSegments = sortBy (compare `on` snd) $ zip segments [1..]
    ((a1, l1), (a2, l2)) <- foldr' foldAnswer (Just (([], 300000), ([], 300000))) sortedSegments
    if null a1 || null a2 then
        Nothing
    else
        Just . map snd . sort $ (zip a1 (repeat 1) ++ zip a2 (repeat 2))

main :: IO ()
main = do
    testCount <- readInt <$> getLine
    replicateM_ testCount $ do
        n <- readInt <$> getLine
        segments <- replicateM n $ ((\[l, r] -> (l, r)) . map readInt . words) <$> getLine
        let answer = fromMaybe [-1] $ solve segments
        forM_ answer $ printf "%d "
        printf "\n"

import Text.Printf
import Data.List
import Data.Functor
import Control.Applicative
import Prelude
import Control.Monad
import Data.Maybe
import Data.Function
import Data.Array
import qualified Data.ByteString.Char8 as B8
import Data.Foldable (foldr')

readInt :: String -> Int
readInt = Prelude.read

type Answer = Maybe (([Int], Int), ([Int], Int))

foldAnswer :: ((Int, Int), Int) -> Answer -> Answer
foldAnswer ((l, r), id) answer = do
    ((a1, l1), (a2, l2)) <- answer
    if r < l2 then
        if l < l1 then
            return ((id : a2, l), (a1, l1))
        else
            return ((a1, l1), (id : a2, l))
    else
        Nothing

solve :: [(Int, Int)] -> Maybe [Int]
solve segments = do
    let sortedSegments = sortBy (compare `on` (\((x, y), z) -> ((y, x), z))) $ zip segments [1..]
    ((a1, l1), (a2, l2)) <- foldr' foldAnswer (Just (([], 300000), ([], 300000))) sortedSegments
    if null a1 || null a2 then
        Nothing
    else
        Just . map snd . sort $ (zip a1 (repeat 1) ++ zip a2 (repeat 2))

main :: IO ()
main = do
    testCount <- readInt <$> getLine
    replicateM_ testCount $ do
        n <- readInt <$> getLine
        segments <- replicateM n $ ((\[l, r] -> (l, r)) . map readInt . words) <$> getLine
        let answer = fromMaybe [-1] $ solve segments
        forM_ answer $ printf "%d "
        printf "\n"

import Text.Printf
import Data.List
import Data.Functor
import Control.Applicative
import Prelude
import Control.Monad
import Data.Maybe
import Data.Function
import Data.Array
import qualified Data.ByteString.Char8 as B8
import Data.Foldable (foldr')

readInt :: String -> Int
readInt = Prelude.read

type Answer = Maybe (([Int], Int), ([Int], Int))

foldAnswer :: ((Int, Int), Int) -> Answer -> Answer
foldAnswer ((l, r), id) answer = do
    ((a1, l1), (a2, l2)) <- answer
    if (r < l1) && not (null a2 && r < l2) then
        return ((id : a1, l), (a2, l2))
    else
        if r < l2 then
            Just ((a1, l1), (id : a2, l))
        else
            Nothing

solve :: [(Int, Int)] -> Maybe [Int]
solve segments = do
    let sortedSegments = sort $ zip segments [1..]
    ((a1, l1), (a2, l2)) <- foldr' foldAnswer (Just (([], 300000), ([], 300000))) sortedSegments
    return . map snd . sort $ (zip a1 (repeat 1) ++ zip a2 (repeat 2))

main :: IO ()
main = do
    testCount <- readInt <$> getLine
    replicateM_ testCount $ do
        n <- readInt <$> getLine
        segments <- replicateM n $ ((\[l, r] -> (l, r)) . map readInt . words) <$> getLine
        let answer = fromMaybe [-1] $ solve segments
        forM_ answer $ printf "%d "
        printf "\n"

import Text.Printf
import Data.List
import Data.Functor
import Control.Applicative
import Prelude
import Control.Monad
import Data.Maybe
import Data.Function
import Data.Array
import qualified Data.ByteString.Char8 as B8
import Data.Foldable (foldr')

readInt :: String -> Int
readInt = Prelude.read

type Answer = Maybe (([Int], Int), ([Int], Int))

foldAnswer :: ((Int, Int), Int) -> Answer -> Answer
foldAnswer ((l, r), id) answer = do
    ((a1, l1), (a2, l2)) <- answer
    if (r < l1) && not (null a2 && r < l2) then
        return ((id : a1, l), (a2, l2))
    else
        if r < l2 then
            Just ((a1, l1), (id : a2, l))
        else
            Nothing

solve :: [(Int, Int)] -> Maybe [Int]
solve segments = do
    let sortedSegments = sort $ zip segments [1..]
    ((a1, l1), (a2, l2)) <- foldr' foldAnswer (Just (([], 300000), ([], 300000))) sortedSegments
    if null a1 || null a2 then
        Nothing
    else
        Just . map snd . sort $ (zip a1 (repeat 1) ++ zip a2 (repeat 2))

main :: IO ()
main = do
    testCount <- readInt <$> getLine
    replicateM_ testCount $ do
        n <- readInt <$> getLine
        segments <- replicateM n $ ((\[l, r] -> (l, r)) . map readInt . words) <$> getLine
        let answer = fromMaybe [-1] $ solve segments
        forM_ answer $ printf "%d "
        printf "\n"

import Text.Printf
import Data.List
import Data.Functor
import Control.Applicative
import Prelude
import Control.Monad
import Data.Maybe
import Data.Function
import Data.Array
import qualified Data.ByteString.Char8 as B8
import Data.Foldable (foldr')

readInt :: String -> Int
readInt = Prelude.read

type Answer = Maybe (([Int], Int), ([Int], Int))

foldAnswer :: ((Int, Int), Int) -> Answer -> Answer
foldAnswer ((l, r), id) answer = do
    ((a1, l1), (a2, l2)) <- answer
    if r < l2 then
        if l < l1 then
            return ((id : a2, l), (a1, l1))
        else
            return ((a1, l1), (id : a2, l))
    else
        Nothing

solve :: [(Int, Int)] -> Maybe [Int]
solve segments = do
    let sortedSegments = sort $ zip segments [1..]
    ((a1, l1), (a2, l2)) <- foldr' foldAnswer (Just (([], 300000), ([], 300000))) sortedSegments
    if null a1 || null a2 then
        Nothing
    else
        Just . map snd . sort $ (zip a1 (repeat 1) ++ zip a2 (repeat 2))

main :: IO ()
main = do
    testCount <- readInt <$> getLine
    replicateM_ testCount $ do
        n <- readInt <$> getLine
        segments <- replicateM n $ ((\[l, r] -> (l, r)) . map readInt . words) <$> getLine
        let answer = fromMaybe [-1] $ solve segments
        forM_ answer $ printf "%d "
        printf "\n"

import Text.Printf
import Data.List
import Data.Functor
import Control.Applicative
import Prelude
import Control.Monad
import Data.Maybe
import Data.Function
import Data.Array
import qualified Data.ByteString.Char8 as B8
import Data.Foldable (foldr')

readInt :: String -> Int
readInt = Prelude.read

type Answer = Maybe ([Int], [Int], Int)

foldAnswer :: ((Int, Int), Int) -> Answer -> Answer
foldAnswer ((l, r), i) answer = do
    (a1, a2, ll) <- answer
    if r < ll then
        return (i : a2, a1, l)
    else
        return (i : a1, a2, l)

solve :: [(Int, Int)] -> Maybe [Int]
solve segments = do
    let sortedSegments = sortBy (compare `on` (\((x, y), z) -> ((y, x), z))) $ zip segments [1..]
    (a1, a2, ll) <- foldr' foldAnswer (Just ([], [], 400000)) sortedSegments
    if null a1 || null a2 then
        Nothing
    else
        Just . map snd . sort $ (zip a1 (repeat 1) ++ zip a2 (repeat 2))

main :: IO ()
main = do
    testCount <- readInt <$> getLine
    replicateM_ testCount $ do
        n <- readInt <$> getLine
        segments <- replicateM n $ ((\[l, r] -> (l, r)) . map readInt . words) <$> getLine
        let answer = fromMaybe [-1] $ solve segments
        forM_ answer $ printf "%d "
        printf "\n"

{-# LANGUAGE BangPatterns #-}
import System.IO
import Control.Applicative
import Control.Monad
import Data.Char
import Data.List
import Data.Maybe
import Data.Monoid
import Data.Function (fix, on)
import Data.Array (Array, array, (!))
import Data.ByteString.Lazy.Builder
import Data.ByteString.Lazy.Builder.ASCII
import qualified Data.Set as Set
import qualified Data.Map.Strict as Map
import qualified Data.ByteString as BS
import qualified Data.ByteString.Char8 as BS8

construct :: (BS.ByteString -> Maybe (a, BS.ByteString)) -> BS.ByteString -> [a]
construct reader str
    | BS.null str = []
    | isSpace (BS8.head str) = construct reader (BS8.tail str)
    | otherwise = let Just (i, other) = reader str in i : construct reader other

getInts :: IO [Int]
getInts = construct BS8.readInt <$> BS.getLine

getIntegers :: IO [Integer]
getIntegers = construct BS8.readInteger <$> BS.getLine

printInts :: [Int] -> IO ()
printInts = putStrLn . intercalate " " . map show

check range = go range 0 -- l
    where go [] _ = -1
          go (([l, r], k):[]) x = if x < l then k else -1
          go (([l,r], k):([nl,nr], k2):s) x
            | l > x && r < nl = k
            | otherwise = go (([nl,nr],k2):s) (max x r)

solve _ = do
    [q] <- getInts
    range <- forM [1..q] (\_ -> getInts)
    let sorted = sortBy (compare `on` (head . fst)) (zip range [1..])
    let k = check sorted
    if k == -1 then print k else printInts $ map (\x -> if x == k then 2 else 1) [1..q]

main = do
    [t] <- getInts
    mapM_ solve [1..t]

{-# LANGUAGE BangPatterns #-}
import System.IO
import Control.Applicative
import Control.Monad
import Data.Char
import Data.List
import Data.Maybe
import Data.Monoid
import Data.Function (fix, on)
import Data.Array (Array, array, (!))
import Data.ByteString.Lazy.Builder
import Data.ByteString.Lazy.Builder.ASCII
import qualified Data.Set as Set
import qualified Data.Map.Strict as Map
import qualified Data.ByteString as BS
import qualified Data.ByteString.Char8 as BS8

construct :: (BS.ByteString -> Maybe (a, BS.ByteString)) -> BS.ByteString -> [a]
construct reader str
    | BS.null str = []
    | isSpace (BS8.head str) = construct reader (BS8.tail str)
    | otherwise = let Just (i, other) = reader str in i : construct reader other

getInts :: IO [Int]
getInts = construct BS8.readInt <$> BS.getLine

getIntegers :: IO [Integer]
getIntegers = construct BS8.readInteger <$> BS.getLine

printInts :: [Int] -> IO ()
printInts = putStrLn . intercalate " " . map show

make range = go range 0 0 -- l, r 각각 오른쪽 끝 유지
    where go [] _ _ = []
          go ([l, r]:ls) x y
            | l > max x y = if x > y then 1:go ls r y else 2:go ls x r
            | l > x = 1: go ls r y
            | l > y = 2: go ls x r
            | otherwise = []

solve _ = do
    [q] <- getInts
    range <- forM [1..q] (\_ -> getInts)
    let sorted = sortBy (compare `on` head) range
    let groups = make sorted
    let groups' = if all (\x -> x == 2) groups then 1:tail groups else groups
    if length groups' < q then print (-1) else printInts groups'

main = do
    [t] <- getInts
    mapM_ solve [1..t]

{-# LANGUAGE BangPatterns #-}
import System.IO
import Control.Applicative
import Control.Monad
import Data.Char
import Data.List
import Data.Maybe
import Data.Monoid
import Data.Function (fix, on)
import Data.Array (Array, array, (!))
import Data.ByteString.Lazy.Builder
import Data.ByteString.Lazy.Builder.ASCII
import qualified Data.Set as Set
import qualified Data.Map.Strict as Map
import qualified Data.ByteString as BS
import qualified Data.ByteString.Char8 as BS8

construct :: (BS.ByteString -> Maybe (a, BS.ByteString)) -> BS.ByteString -> [a]
construct reader str
    | BS.null str = []
    | isSpace (BS8.head str) = construct reader (BS8.tail str)
    | otherwise = let Just (i, other) = reader str in i : construct reader other

getInts :: IO [Int]
getInts = construct BS8.readInt <$> BS.getLine

getIntegers :: IO [Integer]
getIntegers = construct BS8.readInteger <$> BS.getLine

printInts :: [Int] -> IO ()
printInts = putStrLn . intercalate " " . map show

make range = go range 0 0 -- l, r 각각 오른쪽 끝 유지
    where go [] _ _ = []
          go (([l, r], k):ls) x y
            | l > max x y = if x > y then (k, 1):go ls r y else (k, 2):go ls x r
            | l > x = (k, 1): go ls r y
            | l > y = (k, 2): go ls x r
            | otherwise = []

solve _ = do
    [q] <- getInts
    range <- forM [1..q] (\_ -> getInts)
    let sorted = sortBy (compare `on` (head . fst)) (zip range [1..])
    let groups = make sorted
    let groups' = if all (\(a, b) -> b == 2) groups then (fst $ head groups, 1):tail groups else groups
    let sorted' = sortBy (compare `on` fst) groups'
    if length groups' < q then print (-1) else printInts (map snd sorted')

main = do
    [t] <- getInts
    mapM_ solve [1..t]

{-# LANGUAGE BangPatterns #-}
import System.IO
import Control.Applicative
import Control.Monad
import Data.Char
import Data.List
import Data.Maybe
import Data.Monoid
import Data.Function (fix, on)
import Data.Array (Array, array, (!))
import Data.ByteString.Lazy.Builder
import Data.ByteString.Lazy.Builder.ASCII
import qualified Data.Set as Set
import qualified Data.Map.Strict as Map
import qualified Data.ByteString as BS
import qualified Data.ByteString.Char8 as BS8

construct :: (BS.ByteString -> Maybe (a, BS.ByteString)) -> BS.ByteString -> [a]
construct reader str
    | BS.null str = []
    | isSpace (BS8.head str) = construct reader (BS8.tail str)
    | otherwise = let Just (i, other) = reader str in i : construct reader other

getInts :: IO [Int]
getInts = construct BS8.readInt <$> BS.getLine

getIntegers :: IO [Integer]
getIntegers = construct BS8.readInteger <$> BS.getLine

printInts :: [Int] -> IO ()
printInts = putStrLn . intercalate " " . map show

make range = go range 0 0 -- l, r 각각 오른쪽 끝 유지
    where go [] _ _ = []
          go ([l, r]:ls) x y
            | l > x = 1:go ls r y
            | l > y = 2: go ls x r
            | otherwise = []

solve _ = do
    [q] <- getInts
    range <- forM [1..q] (\_ -> getInts)
    let sorted = sortBy (compare `on` head) range
    let groups = make sorted
    let groups' = if all (\x -> x == 1) groups then 2:tail groups else groups
    if length groups' < q then print (-1) else printInts groups'

main = do
    [t] <- getInts
    mapM_ solve [1..t]

{-# LANGUAGE BangPatterns #-}
import System.IO
import Control.Applicative
import Control.Monad
import Data.Char
import Data.List
import Data.Maybe
import Data.Monoid
import Data.Function (fix, on)
import Data.Array (Array, array, (!))
import Data.ByteString.Lazy.Builder
import Data.ByteString.Lazy.Builder.ASCII
import qualified Data.Set as Set
import qualified Data.Map.Strict as Map
import qualified Data.ByteString as BS
import qualified Data.ByteString.Char8 as BS8

construct :: (BS.ByteString -> Maybe (a, BS.ByteString)) -> BS.ByteString -> [a]
construct reader str
    | BS.null str = []
    | isSpace (BS8.head str) = construct reader (BS8.tail str)
    | otherwise = let Just (i, other) = reader str in i : construct reader other

getInts :: IO [Int]
getInts = construct BS8.readInt <$> BS.getLine

getIntegers :: IO [Integer]
getIntegers = construct BS8.readInteger <$> BS.getLine

printInts :: [Int] -> IO ()
printInts = putStrLn . intercalate " " . map show

make range = go range 0 0 -- l, r 각각 오른쪽 끝 유지
    where go [] _ _ = []
          go ([l, r]:ls) x y
            | l > max x y = if x > y then 1:go ls r y else 2:go ls x r
            | l > x = 1: go ls r y
            | l > y = 2: go ls x r
            | otherwise = []

solve _ = do
    [q] <- getInts
    range <- forM [1..q] (\_ -> getInts)
    let sorted = sortBy (compare `on` head) range
    let groups = make sorted
    let groups' = if all (\x -> x == 1) groups then 2:tail groups else groups
    if length groups' < q then print (-1) else printInts groups'

main = do
    [t] <- getInts
    mapM_ solve [1..t]


--
-- Michael V. Antosha
-- 2022
-- Michael.Antosha@gmail.com
--

{-# language NoMonomorphismRestriction #-}

{-# options_ghc -Weverything                     #-}

{-# options_ghc -Wno-safe                        #-}     -- no warning if inferred as safe
{-# options_ghc -Wno-all-missed-specialisations  #-}     -- "Could not specialise..." when -O1
{-# options_ghc -Wno-missing-import-lists        #-}
{-# options_ghc -Wno-missing-local-signatures    #-}

-- (ghc -O1 -no-keep-o-files -no-keep-hi-files -rtsopts -o a.out *.hs  &&  set -o pipefail  &&  diff -sdu -- <(cat -- input.txt | ./a.out) output.txt  &&  cat -- bw.hs | xclip -selection clipboard  &&  echo COPIED  ||  echo ERROR)

import Prelude
import System.IO
import Control.Monad
import Data.List

main :: IO ()
main = do
    hSetBuffering stdout NoBuffering

    t <- readLn
    tcs <- replicateM t readTC

    (putStr . unlines . map (show . solve)) tcs

readTC = do
    [n,_m, r,c] <- map read . words <$> getLine
    rows <- replicateM n getLine
    return (rows, r-1, c-1)

solve (rows, r, c) = x
  where
    row =           rows !! r
    col = transpose rows !! c

    rowChars  = toBlacks row
    colChars  = toBlacks col
    matrChars = toBlacks (concat rows)

    x = case (row!!c, rowChars, colChars, matrChars) of
        ('B',  _ ,  _ ,  _ ) ->  0
        ('W', "B",  _ ,  _ ) ->  1
        ('W',  _ , "B",  _ ) ->  1
        ('W',  _ ,  _ , "B") ->  2
        ('W',  _ ,  _ , "" ) -> -1
        _                    -> error "logic error"

toBlacks = nub . sort . filter (== 'B')

--
-- Michael V. Antosha
-- 2022
-- Michael.Antosha@gmail.com
--

{-# language NoMonomorphismRestriction #-}

{-# options_ghc -Weverything                     #-}

{-# options_ghc -Wno-safe                        #-}     -- no warning if inferred as safe
{-# options_ghc -Wno-all-missed-specialisations  #-}     -- "Could not specialise..." when -O1
{-# options_ghc -Wno-missing-import-lists        #-}
{-# options_ghc -Wno-missing-local-signatures    #-}

-- (ghc -O1 -no-keep-o-files -no-keep-hi-files -rtsopts -o a.out *.hs  &&  set -o pipefail  &&  diff -sdu -- <(cat -- input.txt | ./a.out) output.txt)

-- (ghc -O1 -no-keep-o-files -no-keep-hi-files -rtsopts -o a.out *.hs  &&  set -o pipefail  &&  diff -sdu -- <(cat -- input.txt | ./a.out) output.txt)

-- cat -- bw.hs | xclip -selection clipboard

import Prelude
import System.IO
import Control.Monad
import Data.List

main :: IO ()
main = do
    hSetBuffering stdout NoBuffering

    t <- readLn
    tcs <- replicateM t readTC

    (putStr . unlines . map (show . solve)) tcs

readTC = do
    [n,_m, r,c] <- map read . words <$> getLine
    rows <- replicateM n getLine
    return (rows, r-1, c-1)

solve (rows, r, c) = x
  where
    row =           rows !! r
    col = transpose rows !! c

    rowChars  = toBlacks row
    colChars  = toBlacks col
    matrChars = toBlacks (concat rows)

    x = case (row!!c, rowChars, colChars, matrChars) of
        ('B',  _ ,  _ ,  _ ) ->  0
        ('W', "B",  _ ,  _ ) ->  1
        ('W',  _ , "B",  _ ) ->  1
        ('W',  _ ,  _ , "B") ->  2
        ('W',  _ ,  _ , "" ) -> -1
        _                    -> error "logic error"

toBlacks = nub . sort . filter (== 'B')

{-# LANGUAGE TupleSections #-}
import Data.Array
import Control.Monad (replicateM_, replicateM)

main :: IO ()
main = read <$> getLine >>= flip replicateM_ singleCase

readInput :: IO (Int, Int, Int, Int, Array (Int, Int) Bool)
readInput = map read . words <$> getLine >>=
            \a -> case a of
                    [n, m, r, c] -> (n,m,r,c,) . toA n m . map (=='W') .
                                    concat <$> replicateM n getLine
                    _ -> error $ "Could not read an array: " ++ show (a)
  where
    toA n m = listArray ((1, 1), (n, m))

singleCase :: IO ()
singleCase = readInput >>= print . f
  where
    f (n,m,r,c,a)  | (not $ a!(r,c))    = 0
                   | (blackView a r c)  = 1
                   | (blackCount a > 0) = 2
                   | otherwise          = -1

blackView :: Array (Int, Int) Bool -> Int -> Int -> Bool
blackView a r c = any (\i -> not (a!i))
                  $ zip (repeat r) [1..m] ++ zip [1..n] (repeat c)
  where ((1, 1), (n, m)) = bounds a

blackCount :: Array (Int, Int) Bool -> Int
blackCount = foldl (\acc b -> if b then acc else acc+1) 0

{-# LANGUAGE MultiWayIf #-}

import Control.Monad

test :: IO ()
test = do
  [n, _, r', c'] <- (<$>) read . words <$> getLine
  let (r, c) = (pred r', pred c')
  grid <- replicateM n getLine
  print
    ( if
          | (all . all) (== 'W') grid -> -1
          | grid !! r !! c == 'B' -> 0
          | any (== 'B') (grid !! r) || any (== 'B') ((!! c) <$> grid) -> 1
          | otherwise -> 2
    )
  return ()

main :: IO ()
main = getLine >>= flip replicateM_ test . read


import Control.Monad (liftM)
import Data.Array ((!), indices, listArray)

n :: Num a => a
n  =  8

(<?>) :: a -> a -> Bool -> a
(<?>) a b p  =  if p then a else b

solve :: [[String]] -> [Bool]
solve  =  map (solve' . toArray)
  where
    toArray  =  listArray ((1, 1), (n, n)) . concat
    solve' array
        =  abs (x1 - x2) `mod` 4 == 0
        && abs (y1 - y2) `mod` 4 == 0
      where
        [(x1, y1), (x2, y2)]  =
            [ij | ij <- indices array, array ! ij == 'K']

intoGroups :: Int -> [a] -> [[a]]
intoGroups _ []  =  []
intoGroups n xs  =  take n xs : intoGroups n (drop n xs)

main :: IO ()
main  =  liftM (intoGroups n . tail . words) getContents
    >>= return . solve
    >>= mapM_ (putStrLn . ("YES" <?> "NO"))

{-# LANGUAGE MultiParamTypeClasses,FlexibleContexts,FlexibleInstances,TypeSynonymInstances,BangPatterns,RankNTypes,TupleSections #-}
import Control.Monad
import Control.Monad.ST
import Control.Applicative
import Control.Arrow
import Debug.Trace
import Text.Printf

import Data.List
import Data.Int
import Data.Bits
import Data.Maybe
import Data.Array.Unboxed
import Data.Array.ST
import qualified Data.Map as M
import qualified Data.Set as S
import qualified Data.ByteString.Char8 as B

readInt = B.readInt >>> fmap fst >>> fromMaybe 0
readInts = map readInt . B.words <$> B.getLine
readIntPair = l2p . map readInt . take 2 . B.words <$> B.getLine
readLns :: Read a => IO [a]
readLns = map read . words <$> getLine
cmpFst (a,_) (b,_) = compare a b
cmpSnd (_,a) (_,b) = compare a b
cmpLen a b = length a `compare` length b
swap (a,b) = (b,a)
l2p (a:b:_) = (a,b)
p2l (a,b) = [a,b]
itof :: Int -> Double
itof = fromIntegral
defaultArray :: (IArray a e,Ix i) => e -> (i,i) -> [(i,e)] -> a i e
defaultArray = accumArray $ curry snd
flatten :: [(a,[(b,c)])] -> [((a,b),c)]
flatten = (=<<) $ uncurry $ fmap . first . (,)

infixr 2 <||>
infixr 3 <&&>
p1 <||> p2 = (p1 &&& p2) >>> uncurry (||)
p1 <&&> p2 = (p1 &&& p2) >>> uncurry (&&)

main = do
    n <- readLn
    forM_ [1..n] $ \i -> do
        l <- replicateM 8 getLine
        putStrLn $ if solve l then "YES" else "NO"
        when ( i < n ) (void getLine)

solve :: [String] -> Bool
solve l = any (check bads) $ zip l1 l2
    where
    as = zip (range ((1,1),(8,8))) (concat l)
    [k1,k2] = [ p | (p,'K') <- as ]
    bads = S.fromList [ p | (p,'#') <- as ]
    l1 = calcFP step (S.empty,S.singleton k1)
    l2 = calcFP step (S.empty,S.singleton k2)

type Pos = (Int,Int)
check :: S.Set Pos -> ((S.Set Pos,S.Set Pos),(S.Set Pos,S.Set Pos))-> Bool
check bads ((a,b),(c,d)) = sub a b || sub b d
    where
    sub x y = not $ S.null (S.intersection x y S.\\ bads)

next (i,j) = (\dx dy -> (i+dx,j+dy)) <$> [-2,2] <*> [-2,2]

step (s1,s2) = (s3,s4)
    where
    f s = S.fromList $ do
        p <- S.elems s >>= next
        guard (inRange ((1,1),(8,8)) p)
        return p
    s3 = f s2
    s4 = f s3

calcFP f p = p:go p
    where
    go p = let p' = f p in if p' == p then [] else p':go p'


{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE Safe #-}
{-# LANGUAGE TupleSections #-}
{-# LANGUAGE ExplicitForAll #-}
{-# LANGUAGE MultiWayIf #-}
{-# LANGUAGE CPP #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE NoMonomorphismRestriction #-}

import Data.Bits
import Data.List
import qualified Data.ByteString.Char8 as BS
import qualified Data.ByteString.Lazy.Char8 as BSL
import Data.IntMap.Strict (IntMap)
import qualified Data.IntMap.Strict as IM
import Data.IntSet (IntSet)
import qualified Data.IntSet as IS
import qualified Data.Array.IArray as A
import qualified Data.Array.MArray.Safe as A
-- import qualified Data.Array.MArray as A
import Data.Array (Array)
import Data.Array.Unboxed (UArray)
import Data.Array.IArray (IArray)
import Data.Array.MArray.Safe (MArray)
import Data.Array.IO.Safe (IOArray, IOUArray)
import Data.Array.ST.Safe (STArray, STUArray, runSTArray, runSTUArray)
{-
import qualified Data.Vector.Unboxed as VU
import qualified Data.Vector.Unboxed.Mutable as VUM
-}
import Control.Monad
import Control.Monad.ST.Safe
-- import Control.Monad.ST
import Control.Applicative
import Data.Maybe
import Data.Tuple
import Data.Ord
import Control.Monad.State.Strict
import Data.Int
import Data.Word
import Data.STRef
import Data.IORef
import Data.Function
import System.IO
import System.Exit
import Data.Char

main :: IO ()
main = do
  [n,m,k] <- map readInt . words <$> getLine
  powers <- A.listArray (1,n) . map readInt . words <$> getLine
             :: IO (UArray Int Int)
  school <- A.listArray (1,n) . map readInt . words <$> getLine
             :: IO (UArray Int Int)
  chosen <- map readInt . words <$> getLine
  print
    $ length
    $ [ i
      | i <- chosen,
        (> powers A.! i) $ maximum
        $ map (powers A.!) $ map fst
        $ filter ((== school A.! i) . snd) $ A.assocs school]

rInt :: StateT BSL.ByteString Maybe Int
rInt = StateT $ BSL.readInt . BSL.dropWhile (<'!')

#define D(f,r,d) f::Integral a=>a->d;f=fromIntegral;r::String->d;r=read
#define C(f,r,g,h,d) D(f,r,d);g,h::RealFrac a=>a->d;g=floor;h=ceiling
C(_toInteger_,readInteger,floorInteger,ceilInteger,Integer)
C(toInt,readInt,floorInt,ceilInt,Int)
C(toI8,readI8,floorI8,ceilI8,Int8)
C(toI16,readI16,floorI16,ceilI16,Int16)
C(toI32,readI32,floorI32,ceilI32,Int32)
C(toI64,readI64,floorI64,ceilI64,Int64)
C(toWord,readWord,floorWord,ceilWord,Word)
C(toW8,readW8,floorW8,ceilW8,Word8)
C(toW16,readW16,floorW16,ceilW16,Word16)
C(toW32,readW32,floorW32,ceilW32,Word32)
C(toW64,readW64,floorW64,ceilW64,Word64)
D(toDouble,readDouble,Double)
D(toFloat,readFloat,Float)
#undef D
#undef C

#define N(f,g,a,m)\
  f :: forall e i s. (C(a,m)A.Ix i) => (i,i) -> e -> m (a i e); f=A.newArray;\
  g :: forall e i s. (C(a,m)A.Ix i) => (i,i) -> m (a i e); g=A.newArray_
#define C(a,m)
N(newIOA,newIOA_,IOArray,IO)
N(newSTA,newSTA_,STArray s,ST s)
#undef C
#define C(a,m) MArray (a) e (m),
N(newIOUA,newIOUA_,IOUArray,IO)
N(newSTUA,newSTUA_,STUArray s,ST s)
#undef C
#undef N

{-
Problem statement in Japanese:

トーナメントが開催される.
m校の学校が参加し各校から1人参加できる.

全ての学校合わせて学生はn人である.
トーナメント前に全ての学生は氏名と学校名をTechnoに提出する.
続いてTechnoは各校から最も強い学生を参加者として選ぶ.

Arkadyは特定のk人が選ばれるようにしたい.
残念ながら, その学生達は自身の学校で最も強いとは限らない.
しかし, Arkadyは学校名を追加し, 学生の学校名を追加したものに書き換えることができる.
なお, 追加した学校名を使い回すことはできない.

あなたは各学生の強さと学校名を知っている.
特定のk人が選ばれるために必要となる, 学校名を追加する最小回数を求めよ.
-}

main = do
  [_, _, _] <- map read . words <$> getLine :: IO [Int]
  as <- map read . words <$> getLine :: IO [Int]
  ps <- map read . words <$> getLine :: IO [Int]
  qs <- map read . words <$> getLine :: IO [Int]
  let xs = zip as ps
  print $ sum $ map (f xs) qs

f xs q = if a < m then 1 else 0
  where
    m = maximum $ map fst $ filter ((== p) . snd) xs
    (a, p) = xs !! (q - 1)


{-# OPTIONS_GHC -O3 #-}
{-# LANGUAGE ViewPatterns, ScopedTypeVariables #-}

test x v t = maximum la <= minimum lb where
    (la, lb) = unzip $ zipWith (\a b -> (a - t * b, a + t * b)) x v

bin x v a b | b - a < 1E-6           = b
            | test x v ((a + b) / 2) = bin x v a ((a + b) / 2)
            | otherwise              = bin x v ((a + b) / 2) b

main = do
    (read -> n) <- getLine
    (take n . map (read :: String -> Double) . words -> x) <- getLine
    (take n . map (read :: String -> Double) . words -> v) <- getLine
    let tm = (maximum x - minimum x) * maximum v
    putStrLn $ show $ bin x v 0.0 tm

{-# LANGUAGE BangPatterns #-}

import Data.List

main :: IO ()
main = do
  readLine
  xs <- readLine
  vs <- readLine
  print $ search 0 1e9 $ sortBy (\(a, _) (b, _) -> a `compare` b) (zip xs vs)
    where
      search :: Double -> Double -> [(Double, Double)] -> Double
      search t1 t2 xvs
        | abs (t1-t2) <= 1e-6 = t2
        | otherwise = if valid mid then search t1 mid xvs else search mid t2 xvs
        where
          mid = (t1+t2)/2

          valid :: Double -> Bool
          valid t = loop (tail xvs) (x0+v0*t)
            where
              (x0, v0) = head xvs

              loop [] _ = True
              loop ((curX, curV):rem) rightMost =
                if (curX - t*curV) <= rightMost then loop rem (min (curX + t*curV) rightMost)
                                                else False

readLine :: IO [Double]
readLine = getLine >>= return . words >>= return . (map read)

-- Codeforces Round #403 (Div. 2)
-- B. The Meeting Place Cannot Be Changed
-- http://codeforces.com/contest/782/problem/B

import Control.Monad
import Data.Maybe
import qualified Data.ByteString as BS
import qualified Data.ByteString.Char8 as BS8

getInt = read `fmap` getLine :: IO Int
getInts = (map parseInt . BS8.words) `fmap` BS.getLine :: IO [Int]
parseInt = fst . fromJust . BS8.readInt

main = do
    n <- getInt
    coords <- (map fromIntegral) `fmap` getInts :: IO [Double]
    speeds <- (map fromIntegral) `fmap` getInts :: IO [Double]
    let (lb, ub) = recurse coords speeds (0.0, 1e9) 100
    let answer = (lb + ub) / 2.0
    print answer

recurse _ _ result 0 = result
recurse coords speeds (lb, ub) cnt
    | canMeet coords speeds mid = recurse coords speeds (lb, mid) (cnt-1)
    | otherwise = recurse coords speeds (mid, ub) (cnt-1)
    where mid = (lb + ub) / 2.0

canMeet :: [Double] -> [Double] -> Double -> Bool
canMeet coords speeds t = isJust $ foldl getOverlap (Just (0.0, 1e9)) ranges where
    ranges = zipWith (\coord speed -> (coord - speed * t, coord + speed * t)) coords speeds

getOverlap Nothing _ = Nothing
getOverlap (Just (l1, r1)) (l2, r2)
    | l > r = Nothing
    | otherwise = Just (l, r)
    where
        l = max l1 l2
        r = min r1 r2

{-# LANGUAGE BangPatterns #-}

import Data.List

main :: IO ()
main = do
  readLine
  xs <- readLine
  vs <- readLine
  print $ search 0 1e9 $ sortBy (\(a, _) (b, _) -> a `compare` b) (zip xs vs)
    where
      search :: Double -> Double -> [(Double, Double)] -> Double
      search t1 t2 xvs
        | abs (t1-t2) <= 1e-6 = t2
        | otherwise = if valid mid then search t1 mid xvs else search mid t2 xvs
        where
          mid = (t1+t2)/2

          valid :: Double -> Bool
          valid t = loop xvs (x0+v0*t)
            where
              (x0, v0) = head xvs

              loop [] _ = True
              loop ((curX, curV):rem) rightMost =
                if (curX - t*curV) <= rightMost then loop rem (min (curX + t*curV) rightMost)
                                                else False

readLine :: IO [Double]
readLine = getLine >>= return . words >>= return . (map read)