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 PHP (7.4.4) (judge verdict: Time Limit Exceeded)

<?php

[$N] = fscanf(STDIN, "%d");
$X = [];
$Y = [];
for($i=0;$i<$N;$i++){
    [$a, $b] =  fscanf(STDIN, "%d%d");
    $X[] = $a;
    $Y[] = $b;
}

asort($X);
$fn = fn($x, $y) => max($x, $y);

$count = count($X)-1;
$tr = new SegmentTree($count+2, $fn, -1);

$dsu = new DSU($count+2);

$ans = [];
foreach($X as $key => $value){
    $tr->set($Y[$key], $key);
    $get = $tr->prod(0, $Y[$key]);
    if($get !== -1){
        $dsu->merge($get, $key);
    }
    $rev[$count] = $key;
    $count--;
}

$count = count($X)-1;
$tr = new SegmentTree($count+2, $fn, -1);
for($i=0;$i<=$count;$i++){
    $j = $rev[$i];

    $tr->set($Y[$j], $j);
    $get = $tr->prod($Y[$j]+1, $count+2);
    if($get !== -1){
        $dsu->merge($get, $j);
    }
}
$groups = $dsu->groups();
$ans = [];
foreach($groups as $group){
    $a = count($group);
    foreach($group as $value){
        $ans[$value] = $a;
    }
}

for($i=0;$i<=$count;$i++){
    echo $ans[$i].PHP_EOL;
}


/**
 * Class SegmentTree
 * ref. AtCoder Library
 */
class SegmentTree
{


    private array $tree = [];
    private int $leaf_size;
    private int $tree_size;
    private int $real_size;
    private int $log;
    private $e;
    private object $operation;
    private array $t = [0xFFFFFFFF00000000,
        0x00000000FFFF0000,
        0x000000000000FF00,
        0x00000000000000F0,
        0x000000000000000C,
        0x0000000000000002];

    /**
     * SegmentTree constructor.<br>
     * 計算量 O(n)
     * @param int|array $sv treeのサイズもしくは初期値配列
     * @param object $op 2値比較演算子
     * @param mixed $e 単位元: op(e, a) = a, op(a, e)=a
     */
    function __construct($sv, callable $op, $e)
    {
        if(gettype($sv) === "integer"){
            $count = $sv;
            $list = array_fill(0, $count, $e);
        }elseif(gettype($sv) === "array"){
            $count = count($sv);
            $list = $sv;
        }else{
            $count = 0;
            $list = [];
        }
        $this->e = $e;
        $this->operation = $op;
        $this->real_size = $count;
        $this->log = $this->ceil_log2($count);
        $this->leaf_size = 1 << $this->log;
        $this->tree_size = $this->leaf_size * 2;
        $this->tree = [...array_fill(0,$this->leaf_size, $this->e),
            ...$list,
            ...array_fill(0, $this->leaf_size - $count, $this->e)];

        for($i = $this->leaf_size - 1; $i >= 1; $i--){
            $this->update($i);
        }
    }

    private function update(int $k):void
    {
        $this->tree[$k] = ($this->operation)($this->tree[2 * $k], $this->tree[2 * $k + 1]);

    }

    public function set(int $p, $x):void
    {
        assert(0 <= $p && $p < $this->real_size);
        $p += $this->leaf_size;
        $this->tree[$p] = $x;
        for($i = 1; $i <= $this->log; $i++){
            $this->update($p >> $i);
        }
    }

    public function get(int $p)
    {
        assert(0 <= $p && $p < $this->real_size);
        return $this->tree[$p + $this->leaf_size];
    }

    /**
     * op(a[1], ..., a[n]) を計算します。n=1 のときは e() を返します。
     * @return mixed
     */
    public function prod_all()
    {
        return $this->tree[1];
    }


    /**
     * op(a[l], ..., a[r-1]) を、モノイドの性質を満たしていると仮定して計算します。
     * 添え字は<em>0</em>スタート <em>rの手前まで</em>を計算します。
     * @param int $from
     * @param int $to
     * @return mixed
     */
    public function prod(int $from, int $to ){
        assert(0 <= $from && $from <= $to && $to <= $this->real_size);
        $sml = $smr = $this->e;
        $from += $this->leaf_size;
        $to += $this->leaf_size;
        while ($from < $to){
            if($from & 1) $sml = ($this->operation)($sml, $this->tree[$from++]);
            if($to & 1) $smr = ($this->operation)($this->tree[--$to], $smr);
            $from >>= 1;
            $to >>= 1;
        }

        return ($this->operation)($sml, $smr);

    }


    /**
     * 以下の条件を両方満たす r を(いずれか一つ)返します。 <br>
     * r = l もしくは f(op(a[l], a[l + 1], ..., a[r - 1])) = true <br>
     * r = n もしくは f(op(a[r], a[r + 1], ..., a[n])) = false <br>
     * fが単調だとすれば、f(op(a[l], a[l + 1], ..., a[r - 1])) = true となる最大の r、と解釈することが可能です。 <br>
     * 添え字は0スタート<br>
     * 計算量 O(log n)
     * @param int $l 0 ≤ l ≤ n
     * @param callable $fn 評価関数
     * @return int = 左から評価して初めてfalseになる位置
     */
    public function max_right(int $l, callable $fn): int
    {
        assert(0 <= $l && $l <= $this->real_size);
        assert($fn($this->e));

        if($l === $this->real_size){
            return $this->real_size;
        }
        $l += $this->leaf_size;
        $sm = $this->e;
        do {
            while ($l % 2 === 0) {
                $l >>= 1;
            }
            if (!$fn(($this->operation)($sm, $this->tree[$l]))) {
                while ($l < ($this->leaf_size)) {
                    $l <<= 1;
                    if ($fn(($this->operation)($sm, $this->tree[$l]))) {
                        $sm = ($this->operation)($sm, $this->tree[$l]);
                        $l++;
                    }
                }
                return $l - $this->leaf_size;
            }
            $sm = ($this->operation)($sm, $this->tree[$l]);
            $l++;

        } while (($l & -$l) !== $l);
        return $this->real_size;
    }

    /**
     * 以下の条件を両方満たす l を(いずれか一つ)返します。<br>
     * l = r もしくは f(op(a[l], a[l + 1], ..., a[r - 1])) = true<br>
     * l = 0 もしくは f(op(a[0], a[1], ..., a[l - 1])) = false
     * fが単調だとすれば、f(op(a[l], a[l + 1], ..., a[r - 1])) = true となる最小の l、と解釈することが可能です。
     * 制約
     * fを同じ引数で呼んだ時、返り値は等しい(=副作用はない)
     * f(e()) = true
     * 0 ≤ r ≤ n
     * 計算量
     * O(logn)
     * @param int $r
     * @param callable $fn
     * @return int 右から評価して最後にtrueとなる座標
     */
    public function min_left(int $r, callable $fn): int
    {
        assert(0 <= $r && $r <= $this->real_size);
        assert($fn($this->e));
        if($r === 0){
            return 0;
        }
        $r += $this->leaf_size;
        $sm = $this->e;
        do {
            $r--;
            while (($r % 2) && $r > 1) {
                $r >>= 1;
            }
            if (!$fn(($this->operation)($this->tree[$r], $sm))) {
                while ($r < $this->leaf_size){
                    $r = $r * 2 + 1;
                    if ($fn(($this->operation)($this->tree[$r], $sm))) {
                        $sm = ($this->operation)($this->tree[$r], $sm);
                        $r--;
                    }
                }
                return $r - $this->leaf_size + 1;
            }
            $sm = ($this->operation)($this->tree[$r], $sm);
        } while (($r & -$r) !== $r);
        return 0;
    }

    private function ceil_log2(int $x):int
    {
        $y = ((($x & ($x - 1)) == 0) ? 0 : 1);
        $j = 32;
        foreach ($this->t as $value) {
            $k = ((($x & $value) == 0) ? 0 : $j);
            $y += $k;
            $x >>= $k;
            $j >>= 1;
        }
        return $y;
    }
}


/**
 * Class DSU
 * ref. AtCoder Library
 * 無向グラフに対して、<br>
 * 1. 辺の追加<br>
 * 2. 2頂点が連結かの判定<br>
 * をならし O(α(n)) 時間で処理することが出来ます。<br>
 * また、内部的に各連結成分ごとに代表となる頂点を 1つ持っています。<br>
 * 辺の追加により連結成分がマージされる時、新たな代表元は元の連結成分の代表元のうちどちらかになります。<br>
 */
class DSU
{
    private int $n;
    private array $parent;

    /**
     * DSU constructor.<br>
     * n 頂点 00 辺の無向グラフを作ります。<br>
     * 制約<br>
     * 0 ≤ n ≤ 10^8 <br>
     * 計算量<br>
     * O(n)<br>
     * @param int $n
     */
    function __construct(int $n)
    {
        $this->n = $n;
        $this->parent = array_fill(0,$n,-1);
    }

    /**
     * 辺 (a, b) を足します。<br>
     * a, bが連結だった場合はその代表元、非連結だった場合は新たな代表元を返します。<br>
     * 制約<br>
     * 0 ≤ a < n<br>
     * 0 ≤ b < n<br>
     * 計算量<br>
     * ならし O(α(n))
     * @param int $a
     * @param int $b
     * @return int
     */
    public function merge(int $a, int $b):int
    {
        assert(0 <= $a && $a < $this->n);
        assert(0 <= $b && $b < $this->n);
        $x = $this->leader($a);
        $y = $this->leader($b);
        if($x === $y){
            return $x;
        }
        if(-$this->parent[$x] < -$this->parent[$y]){
            [$x, $y] = [$y, $x];
        }
        $this->parent[$x] += $this->parent[$y];
        $this->parent[$y] = $x;
        return $x;
    }

    /**
     * 頂点 a, ba,b が連結かどうかを返します。<br>
     * 制約<br>
     * 0 ≤ a < n<br>
     * 0 ≤ b < n<br>
     * 計算量<br>
     * ならし O(α(n))
     * @param int $a
     * @param int $b
     * @return bool
     */
    public function same(int $a, int $b): bool
    {
        assert(0 <= $a && $a < $this->n);
        assert(0 <= $b && $b < $this->n);
        return $this->leader($a) === $this->leader($b);
    }

    /**
     * 頂点aの属する連結成分の代表元を返します。<br>
     * 制約<br>
     * 0 ≤ a < n<br>
     * 計算量<br>
     * ならし O(α(n))<br>
     * @param int $a
     * @return int
     */
    public function leader(int $a): int
    {
        if($this->parent[$a] < 0){
            return $a;
        }
        return $this->parent[$a] = $this->leader($this->parent[$a]);
    }

    /**
     * 頂点aの属する連結成分のサイズを返します。<br>
     * 制約<br>
     * 0 ≤ a < n<br>
     * 計算量<br>
     * ならし O(α(n))<br>
     * @param int $a
     * @return int
     */
    public function size(int $a):int
    {
        assert(0 <= $a && $a < $this->n);
        return -$this->parent[$this->leader($a)];
    }

    /**
     * グラフを連結成分に分け、その情報を返します。<br>
     * 返り値は「「一つの連結成分の頂点番号のリスト」のリスト」です。<br>
     * (内側外側限らず)vector内でどの順番で頂点が格納されているかは未定義です。<br>
     * 計算量<br>
     * O(n)<br>
     * @return array
     */
    public function groups(): array
    {
        $leader_buf = $group_size = array_fill(0,$this->n, 0);
        $result = [];
        for($i=0;$i<$this->n;$i++){
            $result[$this->leader($i)][] = $i;
        }
        return $result;
    }
}