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 C++ (GCC 9.2.1 with AC Library v1.1) (judge verdict: Wrong Answer)

#include <bits/stdc++.h>
#include <atcoder/all>
using namespace std;

template <typename T>
class BinaryIndexedTree
{
    std::vector<T> arr;
    const std::size_t size;
    const std::function<T(const T, const T)> operation;
    const T initial_value;

    void initialize_array()
    {
        this->arr = std::vector<T>(this->size, this->initial_value);
    }

public:
    BinaryIndexedTree(const std::size_t N, std::function<T(const T, const T)> func, T init) : size(N + 1), operation(func), initial_value(init)
    {
        initialize_array();
    }

    void update(const std::size_t idx, const T value)
    {
        long long idxll = (long long)idx;
        while (idxll <= (long long)this->size)
        {
            this->arr[idxll] = this->operation(this->arr[idxll], value);
            idxll += (idxll & -idxll);
        }
    }

    T query(const std::size_t idx)
    {
        T ret = this->initial_value;
        long long idxll = (long long)idx;
        while (idxll > 0)
        {
            ret = this->operation(ret, this->arr[idxll]);
            idxll -= (idxll & -idxll);
        }
        return ret;
    }
};

class UnionFind
{
    std::vector<std::size_t> root;
    const std::size_t maximum_size;

public:
    UnionFind(const std::size_t N) : maximum_size(N + 5)
    {
        this->root = std::vector<std::size_t>(N + 1, this->maximum_size);
    }

    std::size_t find_root(const std::size_t A)
    {
        if (this->root[A] >= this->maximum_size)
        {
            return A;
        }
        this->root[A] = this->find_root(this->root[A]);
        return this->root[A];
    }

    std::size_t size(const std::size_t A)
    {
        return this->root[this->find_root(A)] - this->maximum_size + 1;
    }

    bool unite(const std::size_t A, const std::size_t B)
    {
        std::size_t rootA = find_root(A);
        std::size_t rootB = find_root(B);
        if (rootA == rootB)
        {
            return false;
        }

        if (this->size(rootA) < this->size(rootB))
        {
            std::swap(rootA, rootB);
        }

        this->root[rootA] += this->size(rootB);
        this->root[rootB] = rootA;

        return true;
    }

    bool has_same_root(const std::size_t A, const std::size_t B)
    {
        return this->find_root(A) == this->find_root(B);
    }
};

void f(vector<int> &x, vector<int> &y, UnionFind &uf)
{
    size_t n = x.size();
    BinaryIndexedTree<int> bit(
        n + 5, [](int a, int b) { return max(a, b); }, INT_MIN);

    vector<pair<int, size_t>> x_with_index(n);
    for (size_t i = 0; i < n; i++)
    {
        x_with_index[i] = make_pair(x[i], i);
    }
    sort(x_with_index.begin(), x_with_index.end());

    priority_queue<pair<int, size_t>, vector<pair<int, size_t>>, greater<pair<int, size_t>>> q;
    for (size_t i = 0; i < n; i++)
    {
        size_t index = x_with_index[i].second;
        if (bit.query(y[index]) >= 0)
        {
            uf.unite(index, bit.query(y[index]));
        }
        else
        {
            while (!q.empty())
            {
                if (q.top().first < y[index])
                {
                    uf.unite(index, q.top().second);
                    q.pop();
                }
                else
                {
                    break;
                }
            }
            q.push(make_pair(y[index], index));
        }
        bit.update(y[index], index);
    }
}

int main()
{
    size_t N;
    cin >> N;

    vector<int> x(N);
    vector<int> y(N);
    for (size_t i = 0; i < N; i++)
    {
        cin >> x[i] >> y[i];
    }

    UnionFind uf(N);

    f(x, y, uf);

    for (size_t i = 0; i < N; i++)
    {
        x[i] = N - x[i] + 1;
        y[i] = N - y[i] + 1;
    }
    f(x, y, uf);

    for (size_t i = 0; i < N; i++)
    {
        cout << uf.size(i) << endl;
    }
}