#include <bits/stdc++.h>
// clang-format off
using namespace std; using ll = int64_t; using ull = uint64_t; const ll INF = 9e18;
void print() { cout << endl; }
template<typename Head,typename... Tail> void print(Head head,Tail... tail){cout<<head;if(sizeof...(Tail)>0)cout<<" ";print(tail...);}
void print0() {}
template<typename Head,typename... Tail> void print0(Head head,Tail... tail){cout<<head;print0(tail...);}
// clang-format on

class iunionfind {
   public:
    // 連続するuintにのみ使える。vectorであるため定数時間がとれる。
    // 基本的にこれだけあればよい。任意の構造体を扱うときは、IDと構造体のマッピングをとるvectorを別途用意する。
    // libs-test.cppの iuf_map あたりを検索。
    vector<ull> partition;
    vector<ull> rank;

    iunionfind(ull n) {
        partition.resize(n);
        rank.resize(n);
        for (ull x = 0; x < n; x++) {
            partition[x] = x;
            rank[x] = 0;
        }
    }
    ull find(ull x) {
        if (partition[x] == x) {
            return x;
        } else {
            partition[x] = find(partition[x]);
            return partition[x];
        }
    }
    void unite(ull x, ull y) {
        x = find(x);
        y = find(y);
        if (x == y) {
            return;
        }
        if (rank[x] < rank[y]) {
            partition[x] = y;
        } else {
            partition[y] = x;
            if (rank[x] == rank[y]) {
                rank[x]++;
            }
        }
    }
    bool same(ull x, ull y) {
        return find(x) == find(y);
    }
};

struct point_y {
    ll id;
    ll x;
    ll y;
};
bool operator<(const point_y& lhs, const point_y& rhs) {
    return lhs.y < rhs.y;
}
bool operator==(const point_y& lhs, const point_y& rhs) {
    return lhs.y == rhs.y;
}
bool operator!=(const point_y& lhs, const point_y& rhs) {
    return !(lhs == rhs);
}
bool operator>(const point_y& lhs, const point_y& rhs) {
    return !(lhs == rhs) && !(lhs < rhs);
}
bool operator>=(const point_y& lhs, const point_y& rhs) {
    return (lhs == rhs) || (lhs > rhs);
}
bool operator<=(const point_y& lhs, const point_y& rhs) {
    return (lhs == rhs) || (lhs < rhs);
}

struct point_revy {
    ll id;
    ll x;
    ll y;
};
bool operator<(const point_revy& lhs, const point_revy& rhs) {
    return lhs.y > rhs.y;
}
bool operator==(const point_revy& lhs, const point_revy& rhs) {
    return lhs.y == rhs.y;
}
bool operator!=(const point_revy& lhs, const point_revy& rhs) {
    return !(lhs == rhs);
}
bool operator>(const point_revy& lhs, const point_revy& rhs) {
    return !(lhs == rhs) && !(lhs < rhs);
}
bool operator>=(const point_revy& lhs, const point_revy& rhs) {
    return (lhs == rhs) || (lhs > rhs);
}
bool operator<=(const point_revy& lhs, const point_revy& rhs) {
    return (lhs == rhs) || (lhs < rhs);
}

struct point_x {
    ll id;
    ll x;
    ll y;
};
bool operator<(const point_x& lhs, const point_x& rhs) {
    return lhs.x < rhs.x;
}
bool operator==(const point_x& lhs, const point_x& rhs) {
    return lhs.x == rhs.x;
}
bool operator!=(const point_x& lhs, const point_x& rhs) {
    return !(lhs == rhs);
}
bool operator>(const point_x& lhs, const point_x& rhs) {
    return !(lhs == rhs) && !(lhs < rhs);
}
bool operator>=(const point_x& lhs, const point_x& rhs) {
    return (lhs == rhs) || (lhs > rhs);
}
bool operator<=(const point_x& lhs, const point_x& rhs) {
    return (lhs == rhs) || (lhs < rhs);
}

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

    auto uf = iunionfind(N);
    vector<point_y> points(N);
    set<point_y> pmap_xl;
    set<point_revy> pmap_xs;
    set<point_x> pmap_yl;
    for (ll i = 0; i < N; i++) {
        ll x, y;
        cin >> x >> y;
        x--;
        y--;
        points[i] = {i, x, y};
        pmap_xl.insert({i, x, y});
        pmap_xs.insert({i, x, y});
        pmap_yl.insert({i, x, y});
    }

    {
        // x座標が大きい順
        sort(points.begin(), points.end(), [](point_y a, point_y b) { return a.x > b.x; });

        for (ll i = 0; i < N; i++) {
            // y座標が自分より小さい点があれば、それと同じクラスタ
            point_y pt = points[i];
            point_y pt_y_small = *(pmap_xl.begin());

            if (pt_y_small != pt) {
                uf.unite(pt.id, pt_y_small.id);
            }

            // 以降現れないよう消す
            pmap_xl.erase(pt);
        }
    }
    {
        // x座標が小さい順
        sort(points.begin(), points.end(), [](point_y a, point_y b) { return a.x < b.x; });

        for (ll i = 0; i < N; i++) {
            // y座標が自分より大きい点があれば、それと同じクラスタ
            point_y pt = points[i];
            point_revy pt_y_large = *(pmap_xs.begin());

            if (pt_y_large.id != pt.id) {
                uf.unite(pt.id, pt_y_large.id);
            }

            // 以降現れないよう消す
            pmap_xs.erase({pt.id, pt.x, pt.y});
        }
    }
    {
        // y座標が大きい順
        sort(points.begin(), points.end(), [](point_y a, point_y b) { return a.y > b.y; });

        for (ll i = 0; i < N; i++) {
            // x座標が自分より小さい点があれば、それと同じクラスタ
            point_y pt = points[i];
            point_x pt_x_small = *(pmap_yl.begin());

            if (pt_x_small.id != pt.id) {
                uf.unite(pt.id, pt_x_small.id);
            }

            // 以降現れないよう消す
            pmap_yl.erase({pt.id, pt.x, pt.y});
        }
    }

    // id順に戻す
    sort(points.begin(), points.end(), [](point_y a, point_y b) { return a.id < b.id; });

    vector<vector<ll>> clusters(N);
    for (ll i = 0; i < N; i++) {
        point_y pt = points[i];
        ll cluster_id = uf.find(pt.id);
        clusters[cluster_id].push_back(pt.id);
    }

    for (ll i = 0; i < N; i++) {
        point_y pt = points[i];
        ll cluster_id = uf.find(pt.id);
        print(clusters[cluster_id].size());
    }
}


Measured memory_bytes: 48600