Problem:
Score : 300 points

Problem Statement

There are N cities on a 2D plane. The coordinate of the i-th city is (x_i, y_i). Here (x_1, x_2, \dots, x_N) and (y_1, y_2, \dots, y_N) are both permuations of (1, 2, \dots, N).

For each k = 1,2,\dots,N, find the answer to the following question:

Rng is in City k.
Rng can perform the following move arbitrarily many times:

move to another city that has a smaller x-coordinate and a smaller y-coordinate, or a larger x-coordinate and a larger y-coordinate, than the city he is currently in.

How many cities (including City k) are reachable from City k?

Constraints

1 \leq N \leq 200,000

(x_1, x_2, \dots, x_N) is a permutation of (1, 2, \dots, N).

(y_1, y_2, \dots, y_N) is a permutation of (1, 2, \dots, N).

All values in input are integers.

Input

Input is given from Standard Input in the following format:

N
x_1 y_1
x_2 y_2
:
x_N y_N

Output

Print N lines. In i-th line print the answer to the question when k = i.

Sample Input 1

4
1 4
2 3
3 1
4 2

Sample Output 1

1
1
2
2

Rng can reach City 4 from City 3, or conversely City 3 from City 4.

Sample Input 2

7
6 4
4 3
3 5
7 1
2 7
5 2
1 6

Sample Output 2

3
3
1
1
2
3
2

Solution in Haskell (GHC 8.8.3) (judge verdict: Wrong Answer)

{-# LANGUAGE MultiWayIf #-}
{-# LANGUAGE TypeFamilies #-}

module Main where

import Control.Monad
import Control.Monad.Extra
import qualified Data.Array as A
import qualified Data.Array.IO as AIO
import qualified Data.Array.Unboxed as AU
import Data.Bits
import Data.Bool
import qualified Data.ByteString as BS
import qualified Data.ByteString.Char8 as BSC8
import Data.Char
import Data.Either
import Data.Foldable
import Data.Function
import qualified Data.Graph.Inductive.Graph as G
import qualified Data.Graph.Inductive.PatriciaTree as G
import qualified Data.Heap as H
import Data.Int
import Data.List
import qualified Data.Map.Strict as M
import Data.Maybe
import Data.Monoid
import Data.Ord
import qualified Data.Sequence as SQ
import qualified Data.Set as S
import Data.Time
import Data.Tuple
import qualified Data.Vector as V
import Data.Vector.Algorithms.Search
import qualified Data.Vector.Mutable as VM
import qualified Data.Vector.Unboxed as VU
import qualified Data.Vector.Unboxed.Mutable as VUM
import qualified Data.Vector.Unboxing as VUG
import qualified Data.Vector.Unboxing.Mutable as VUGM
import Debug.Trace
import GHC.Base
import GHC.Stack

main :: IO ()
main = do
  --aN       <- getI
  --[aA, aB] <- getIL
  --aS       <- getLine
  aN <- getI
  mXY <- (replicateM aN $ getIT2)
  let aXY = VU.fromList $ sort mXY
  table <- aclDsuTable aN

  acc@(maxx, maxp, maxlist) <-
    foldrM
      ( \v acc@(x, p, list) -> do
          let i = 0
          let (ix, iy) = aXY VU.! i
          let (vx, vy) = aXY VU.! v
          if (ix < vx && iy < vy) || (ix > vx && iy > vy)
            then do
              aclDsuMerge table (ix -1) (vx -1)
              if x < vx then return (vx, v, list) else return acc
            else return (x, p, v : list)
      )
      (0, -1, [])
      $ [1 .. aN -1]
  search table maxlist maxx maxp aXY

  mapM_
    ( \(x, y) ->
        print =<< aclDsuSize table (x -1)
    )
    mXY

  return ()

search :: (Int, VUM.IOVector Int) -> [Int] -> Int -> Int -> VU.Vector (Int, Int) -> IO ()
search table maxlist maxx maxp aXY = do
  acc@(minx, minp, minlist) <-
    foldrM
      ( \i acc@(x, p, list) -> do
          let (ix, iy) = aXY VU.! i
          if ix < maxx
            then do
              aclDsuMerge table (ix -1) (maxx -1)
              if x > ix then return (ix, i, list) else return acc
            else return (x, p, i : list)
      )
      (maxInt, -1, [])
      maxlist
  if length minlist <= 1
    then return ()
    else do
      if minp == -1
        then do
          (maxx, maxp, list) <- searchp table minlist aXY
          if length list <= 1
            then return ()
            else search table list maxx maxp aXY
        else do
          acc@(maxx, maxp, maxlist) <-
            foldrM
              ( \i acc@(x, p, list) -> do
                  let (ix, iy) = aXY VU.! i
                  if ix > minx
                    then do
                      aclDsuMerge table (minx -1) (ix -1)
                      if x < ix then return (ix, i, list) else return acc
                    else return (x, p, i : list)
              )
              (0, -1, [])
              maxlist
          if length maxlist <= 1
            then return ()
            else do
              if maxp == -1
                then do
                  (maxx, maxp, list) <- searchp table maxlist aXY
                  if length list <= 1
                    then return ()
                    else search table list maxx maxp aXY
                else search table maxlist maxx maxp aXY

searchp table mlist aXY = do
  acc@(maxx, maxp, list) <-
    foldrM
      ( \v acc@(x, p, list) -> do
          let i = head mlist
          let (ix, iy) = aXY VU.! i
          let (vx, vy) = aXY VU.! v
          if (ix < vx && iy < vy) || (ix > vx && iy > vy)
            then do
              aclDsuMerge table (ix -1) (vx -1)
              if x < vx then return (vx, v, list) else return acc
            else return (x, p, v : list)
      )
      (0, -1, [])
      (tail mlist)
  if maxp == -1
    then
      if length list <= 1
        then return (0, -1, [])
        else do
          searchp table list aXY
    else do
      return (maxx, maxp, list)

--ACL(AtCoder LibraryのHaskell移植版(おっさんたたき台Ver.))
--DSU
aclDsuTable n = do
  parentOrSize <- VUM.replicate n (-1)
  return (n, parentOrSize)

aclDsuMerge table@(n, parentOrSize) a b
  | a < 0
      || n <= a =
    error "aclDsuMerge:aの範囲を見直してください。"
  | b < 0
      || n <= b =
    error "aclDsuMerge:bの範囲を見直してください。"
  | otherwise = do
    x <- aclDsuLeader table a
    y <- aclDsuLeader table b
    if x == y
      then return x
      else do
        posX <- VUM.read parentOrSize x
        posY <- VUM.read parentOrSize y
        if - posX < - posY
          then do
            VUM.write parentOrSize y (posY + posX)
            VUM.write parentOrSize x y
            return y
          else do
            VUM.write parentOrSize x (posX + posY)
            VUM.write parentOrSize y x
            return x

aclDsuSame table@(n, parentOrSize) a b
  | a < 0
      && n <= a =
    error "aclDsuSame:aの範囲を見直してください。"
  | b < 0
      && n <= b =
    error "aclDsuSame:bの範囲を見直してください。"
  | otherwise = do
    x <- aclDsuLeader table a
    y <- aclDsuLeader table b
    return $ x == y

aclDsuLeader table@(n, parentOrSize) a
  | a < 0
      && n <= a =
    error "aclDsuLeader:aの範囲を見直してください。"
  | otherwise = do
    posA <- VUM.read parentOrSize a
    if posA < 0
      then return a
      else do
        x <- aclDsuLeader table posA
        VUM.write parentOrSize a x
        return x

aclDsuSize table@(n, parentOrSize) a
  | a < 0
      && n <= a =
    error "aclDsuSize:aの範囲を見直してください。"
  | otherwise = do
    x <- aclDsuLeader table a
    negate <$> VUM.read parentOrSize x

aclDsuGroup table@(n, parentOrSize) = do
  leaderBuf <- VUM.replicate n 0 :: IO (VUM.IOVector Int)
  groupSize <- VUM.replicate n 0 :: IO (VUM.IOVector Int)
  VU.forM_ (VU.enumFromN 0 n) $
    \i -> do
      leaderI <- aclDsuLeader table i
      VUM.write leaderBuf i leaderI
      VUM.modify groupSize succ leaderI
  resultTmpIndex <- VUM.replicate n 0 :: IO (VUM.IOVector Int)
  resultTmp <-
    ( V.generateM n $
        \i -> do
          gs <- VUM.read groupSize i
          VUM.replicate gs 0 :: IO (VUM.IOVector Int)
      )
  VU.forM_ (VU.enumFromN 0 n) $
    \i -> do
      leaderI <- VUM.read leaderBuf i
      tmpIndex <- VUM.read resultTmpIndex leaderI
      VUM.write (resultTmp V.! leaderI) tmpIndex i
      VUM.modify resultTmpIndex succ leaderI
  V.mapMaybe id
    <$> ( V.mapM
            ( \i -> do
                rti <- VU.freeze $ resultTmp V.! i :: IO (VU.Vector Int)
                if rti == VU.empty
                  then return Nothing
                  else return $ Just rti
            )
            $ V.enumFromN 0 n
        )

--雑多系
t :: Int -> (Int, Int)
t x = (x, 1)

i def f t = bool t def $ f t

shiftRCnt k = shiftRCntP k 1

shiftRCntP k c =
  let nk = shiftR k 1
   in if nk == 0
        then c
        else shiftRCntP nk (c + 1)

myVUmap f vu =
  if vu == VU.empty
    then VU.empty
    else
      VU.unfoldr
        ( \x ->
            let ret = f $ VU.head x
                tailx = VU.tail x
             in if x == VU.empty
                  then Nothing
                  else
                    if isLeft ret
                      then Just (either id id ret, tailx)
                      else Just (either id id ret, VU.empty)
        )
        vu

myVUmapM f vu =
  if vu == VU.empty
    then return VU.empty
    else
      VU.unfoldrM
        ( \x -> do
            ret <- f $ VU.head x
            let tailx = VU.tail x
            if x == VU.empty
              then return Nothing
              else
                if isLeft ret
                  then return $ Just (either id id ret, tailx)
                  else return $ Just (either id id ret, VU.empty)
        )
        vu

myVUmapM_ f vu =
  if vu == VU.empty
    then return ()
    else do
      ret1 <-
        VU.unfoldrM
          ( \x -> do
              ret2 <- f $ VU.head x
              let tailx = VU.tail x
              if x == VU.empty
                then return Nothing
                else
                  if isLeft ret2
                    then return $ Just (either id id ret2, tailx)
                    else return $ Just (either id id ret2, VU.empty)
          )
          vu
      return ()

myVUfor vu f = myVUmap f vu

myVUforM vu f = myVUmapM f vu

myVUforM_ vu f = myVUmapM_ f vu

myVUfoldl f acc vu =
  if vu == VU.empty
    then return acc
    else do
      let ret = f acc (VU.head vu)
      if isLeft ret
        then myVUfoldl f (either id id ret) (VU.tail vu)
        else return $ either id id ret

myVUfoldr f acc vu =
  if vu == VU.empty
    then return acc
    else do
      let ret = f acc (VU.last vu)
      if isLeft ret
        then myVUfoldr f (either id id ret) (VU.init vu)
        else return $ either id id ret

myVUfoldM f acc vu =
  if vu == VU.empty
    then return acc
    else do
      ret <- f acc (VU.head vu)
      if isLeft ret
        then myVUfoldM f (either id id ret) (VU.tail vu)
        else return $ either id id ret

--周りのマス
aroundSquare y x h w =
  VU.concatMap
    ( \a ->
        VU.mapMaybe
          ( \b ->
              let ya = y + a
                  xb = x + b
               in if abs a + abs b == 1
                    then
                      if ya < 0 || ya >= h || xb < 0 || xb >= w
                        then Nothing
                        else Just (ya, xb)
                    else Nothing
          )
          $ VU.enumFromN (-1) 3
    )
    $ VU.enumFromN (-1) 3

--入力系
splitReadBSC8 :: BSC8.ByteString -> [Int]
splitReadBSC8 bs =
  let (bs1, newBs) = BSC8.splitAt 1 bs
   in if newBs == BSC8.empty
        then [test $ BSC8.readInt bs1]
        else test (BSC8.readInt bs1) : splitReadBSC8 newBs
  where
    test (Just (i, _)) = i

read2DimChar :: VM.IOVector (VUM.IOVector Char) -> Int -> Int -> IO Char
read2DimChar vec y x = do
  vecY <- VM.read vec y
  VUM.read vecY x

write2DimChar :: VM.IOVector (VUM.IOVector Char) -> Int -> Int -> Char -> IO ()
write2DimChar vec y x t = do
  vecY <- VM.read vec y
  VUM.write vecY x t

readTwoDimVec :: VM.IOVector (VUM.IOVector Int) -> Int -> Int -> IO Int
readTwoDimVec vec y x = do
  vecY <- VM.read vec y
  VUM.read vecY x

writeTwoDimVec :: VM.IOVector (VUM.IOVector Int) -> Int -> Int -> Int -> IO ()
writeTwoDimVec vec y x t = do
  vecY <- VM.read vec y
  VUM.write vecY x t

getVUI :: IO (VU.Vector Int)
getVUI = VU.unfoldr (BSC8.readInt . BSC8.dropWhile isSpace) <$> BSC8.getLine

getRepVUI :: Int -> IO (VU.Vector Int)
getRepVUI n =
  VU.unfoldr (BSC8.readInt . BSC8.dropWhile isSpace) . BSC8.unlines
    <$> replicateM n BSC8.getLine

getVS :: IO (V.Vector Char)
getVS = V.fromList <$> getLine

getVUC :: IO (VU.Vector Char)
getVUC = VU.fromList <$> getLine

readI :: BSC8.ByteString -> Int
readI = fst . fromJust . BSC8.readInt

readInteger :: BSC8.ByteString -> Integer
readInteger = fst . fromJust . BSC8.readInteger

readIL :: BSC8.ByteString -> [Int]
readIL = map readI . BSC8.words

readIT2 :: BSC8.ByteString -> (Int, Int)
readIT2 bs =
  let words = BSC8.words bs
   in (readI $ head words, readI $ last words)

readIT3 :: BSC8.ByteString -> (Int, Int, Int)
readIT3 bs =
  let words = BSC8.words bs
   in (readI $ head words, readI $ words !! 1, readI $ words !! 2)

getI :: IO Int
getI = readI <$> BSC8.getLine

getInteger :: IO Integer
getInteger = readInteger <$> BSC8.getLine

getIL :: IO [Int]
getIL = readIL <$> BSC8.getLine

getIT2 :: IO (Int, Int)
getIT2 = readIT2 <$> BSC8.getLine

getIT3 :: IO (Int, Int, Int)
getIT3 = readIT3 <$> BSC8.getLine

getIT2Order :: IO (Int, Int)
getIT2Order =
  getIL
    >>= \x@[xz, xo] ->
      if xz > xo
        then return (xo, xz)
        else return (xz, xo)

getNIS :: Int -> IO [(Int, BSC8.ByteString)]
getNIS 0 = return []
getNIS n = do
  [aFst, aSnd] <- BSC8.words <$> BSC8.getLine
  next <- getNIS (n - 1)
  return ((readI aFst, aSnd) : next)

il2Words :: [Int] -> String
il2Words = unwords . map show

il2Lines :: [Int] -> String
il2Lines = unlines . map show