#define _USE_MATH_DEFINES
#include <bits/stdc++.h>

using namespace std;

using i64 = long long;
#define forn(a, e) for (i64 a = 0; a < (i64)(e); a++)
#define forr(a, s, e) for (i64 a = s; a < (i64)(e); a++)
#define fore(e, a) for (auto& e : a)

#ifdef LOCAL
#define logv(a) {cerr << #a << " = "; fore(e, a) {cerr << e << " ";} cerr << "\n";}
#define logvp(a) {cerr << #a << " = "; fore(e, a) {cerr << "(" << e.first << ", " << e.second << ") ";} cerr << "\n";}
#define logvv(a) {cerr << #a << " = \n"; fore(r, a) { fore(e, r) {cerr << e << " ";} cerr << "\n";} }
#define logvf(a, field) {cerr << #a"."#field << " = \n"; fore(e, a) { cerr << e.field << " ";} cerr << "\n"; }
#define logvff(a, f1, f2) {cerr << #a".{"#f1 << ", "#f2 << "} = \n"; fore(e, a) { cerr << "(" << e.f1 <<", " << e.f2 << ") ";} cerr << "\n"; }
#define logs(a) cerr << #a << " = " << (a) << "\n";
#define logss(a, b) cerr << #a << " = " << (a) << ", " << #b << " = " << (b) << "\n";
#define logp(a) cerr << #a << " = " << "(" << a.first << ", " << a.second << ")" << "\n";
#define cond(pred, stmt) if (pred) { stmt }
#else
#define logv(a)
#define logvp(a)
#define logvv(a)
#define logvf(a, field)
#define logvff(a, f1, f2)
#define logs(a)
#define logss(a, b)
#define logp(a)
#define cond(pred, stmt)
#endif

using iip = pair<int, int>;
using llp = pair<i64, i64>;
using ivec = vector<int>;
using llvec = vector<i64>;
using svec = vector<string>;
template<typename T> using vec = vector<T>;

template<typename T, typename Dim>
auto make_vec(T value, Dim dim) { return vector<T>(dim, value); }
template<typename T, typename Dim1, typename... Dim>
auto make_vec(T value, Dim1 dim1, Dim... dims) { return make_vec(make_vec(value, dims...), dim1); }

template<typename T>
bool uax(T& v, const T& newv) { if (v < newv) { v = newv; return true; } else return false; }
template<typename T>
bool uin(T& v, const T& newv) { if (v > newv) { v = newv; return true; } else return false; }

template<typename T>
istream& operator>>(istream& is, vector<T>& c) { for (auto& e : c) is >> e; return is; }
template<typename T, size_t N>
istream& operator>>(istream& is, array<T, N>& c) { for (auto& e : c) is >> e; return is; }

template<typename ...T>
istream& read(T&... args) { return (cin >> ... >> args); }

static mt19937 rande(123123);
template<typename T>
T rand_int(T from, T to) { uniform_int_distribution<T> distr(from, to); return distr(rande); }

// const i64 INF = 1e18;
const int INF = 2e9;
const i64 M = 998244353;
const int MXB = 20;
using bin = bitset<MXB + 1>;

template<typename T>
struct SegTree {
    vector<T> data;
    int N;
    T idVal;
    function<T(T const&, T const&)> combine;
    function<void(T &, T const&)> leafMod;
    SegTree(vector<T> const&base, T const& identity_value, function<void(T &, T const&)> const&leaf_update, function<T(T const&, T const&)> const&subtree_combine):N(base.size()), idVal(identity_value), combine(subtree_combine), leafMod(leaf_update){
        data.resize(2*N);
        copy(base.begin(), base.end(), data.begin()+N);
        for(int i=N-1;i>=0;--i){
            data[i]=combine(data[i<<1], data[i<<1|1]);
        }
    }
    void update(int pos, T val){
        for(leafMod(data[pos+=N], val);pos>>=1;){
            data[pos]=combine(data[pos<<1], data[pos<<1|1]);
        }
    }
    T query(int l, int r){
        T retL=idVal, retR=idVal;
        for(l+=N, r+=N;l<r;l>>=1, r>>=1){
            if(l&1)retL=combine(retL, data[l++]);
            if(r&1)retR=combine(data[--r], retR);
        }
        return combine(retL, retR);
    }
};

void update(iip& v, iip nv) {
    v = nv;
}

iip combine_max(iip a, iip b) {
    iip res = {max(a.first, b.first), max(a.second, b.second)};
    return res;
}

iip combine_min(iip a, iip b) {
    iip res = {min(a.first, b.first), min(a.second, b.second)};
    return res;
}


struct SegTree2d {
    vector<ivec> data;
    int N;
    int idVal;
    // function<T(T const&, T const&)> combine;
    // function<void(T &, T const&)> leafMod;
    ivec combine(const ivec& a, const ivec& b) {
        ivec res;
        int ap = 0;
        int bp = 0;
        while (ap < a.size() && bp < b.size()) {
            if (a[ap] < b[bp]) {
                res.push_back(a[ap]);
                ap++;
            } else {
                res.push_back(b[bp]);
                bp++;
            }
        }
        while (ap < a.size()) {
            res.push_back(a[ap]);
            ap++;
        }
        while (bp < b.size()) {
            res.push_back(b[bp]);
            bp++;
        }
        return res;
    }

    int county(const ivec& a, int ly, int ry) {
        auto it1 = lower_bound(a.begin(), a.end(), ly);
        auto it2 = lower_bound(a.begin(), a.end(), ry);
        return distance(it1, it2);
    }

    ivec gety(const ivec& a, int ly, int ry) {
        ivec res;
        auto it1 = lower_bound(a.begin(), a.end(), ly);
        auto it2 = lower_bound(a.begin(), a.end(), ry);
        for (auto it = it1; it != it2; ++it) {
            res.push_back(*it);
        }
        return res;
    }

    SegTree2d(vector<ivec> const&base): N(base.size()), idVal(0) {
        data.resize(2*N);
        copy(base.begin(), base.end(), data.begin()+N);
        for(int i=N-1;i>=0;--i){
            data[i]=combine(data[i<<1], data[i<<1|1]);
        }
    }
    ivec query(int lx, int rx, int ly, int ry) {
        int l = lx;
        int r = rx;
        ivec retL, retR;
        for(l+=N, r+=N;l<r;l>>=1, r>>=1){
            if(l&1) {
                retL = combine(retL, gety(data[l++], ly, ry));
                // int cc = county(data[l++], ly, ry);
                // retL += cc;
            }
            if(r&1) {
                retR = combine(retR, gety(data[--r], ly, ry));
            }
        }
        return combine(retL, retR);
    }
};

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);
    rande.seed(chrono::steady_clock::now().time_since_epoch().count());

    int n;
    while (read(n)) {
        vec<iip> pts(n);
        map<int, int> yp;
        forn(i, n) {
            auto& [x, y] = pts[i];
            read(x, y);
            yp[y] = i;
        }

        ivec ans(n);
        vec<ivec> ybx(n + 1);
        for (auto [x, y] : pts) {
            ybx[x].push_back(y);
        }
        SegTree2d stree(ybx);

        ivec used(n);
        forn(i, n) if (!used[i]) {
            auto [x, y] = pts[i];
            int lx = x;
            int ly = y;
            int rx = x;
            int ry = y;
            int nlx = x;
            int nly = y;
            int nrx = x;
            int nry = y;
            ivec ids = {(int)i};
            ivec r1 = stree.query(x + 1, n + 1, y + 1, n + 1);
            ivec r2 = stree.query(0, x, 0, y);
            fore(y, r1) {
                int id = yp[y];
                ids.push_back(id);
                uin(nlx, pts[id].first);
                uax(nrx, pts[id].first);
                uin(nly, pts[id].second);
                uax(nry, pts[id].second);
            }
            fore(y, r2) {
                int id = yp[y];
                ids.push_back(id);
                uin(nlx, pts[id].first);
                uax(nrx, pts[id].first);
                uin(nly, pts[id].second);
                uax(nry, pts[id].second);
            }

            while (nlx != lx || nly != ly || nrx != rx || nry != ry) {
                auto res1 = stree.query(0, lx, ry + 1, nry + 1);
                auto res2 = stree.query(rx + 1, n + 1, nly, ly);
                auto res3 = stree.query(nlx, lx, nry + 1, n + 1);
                auto res4 = stree.query(rx + 1, nrx + 1, 0, nly);
                logss(nlx, nrx);
                logss(nly, nry);

                lx = nlx;
                ly = nly;
                rx = nrx;
                ry = nry;

                fore(y, res1) {
                    int id = yp[y];
                    ids.push_back(id);
                    uin(nlx, pts[id].first);
                    uax(nrx, pts[id].first);
                    uin(nly, pts[id].second);
                    uax(nry, pts[id].second);
                }
                fore(y, res2) {
                    int id = yp[y];
                    ids.push_back(id);
                    uin(nlx, pts[id].first);
                    uax(nrx, pts[id].first);
                    uin(nly, pts[id].second);
                    uax(nry, pts[id].second);
                }
                fore(y, res3) {
                    int id = yp[y];
                    ids.push_back(id);
                    uin(nlx, pts[id].first);
                    uax(nrx, pts[id].first);
                    uin(nly, pts[id].second);
                    uax(nry, pts[id].second);
                }
                fore(y, res4) {
                    int id = yp[y];
                    ids.push_back(id);
                    uin(nlx, pts[id].first);
                    uax(nrx, pts[id].first);
                    uin(nly, pts[id].second);
                    uax(nry, pts[id].second);
                }
                logss(nlx, nrx);
                logss(nly, nry);

                logv(res1);
                logv(res2);
                logv(res3);
                logv(res4);
            }
            logs(i);
            logv(ids);
            fore(j, ids) {
                used[j] = true;
                ans[j] = ids.size();
            }
        }

        fore(a, ans) {
            cout << a << "\n";
        }
    }
}

Measured memory_bytes: 64128