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# (.NET Core 3.1.201) (judge verdict: Accepted)

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;

class TEST{
	static void Main(){
		Sol mySol =new Sol();
		mySol.Solve();
	}
}

class Sol{
	
	public void Solve(){
		
		int[] ord = new int[N + 1];
		for(int i=0;i<N;i++) ord[X[i]] = i;
		Array.Sort(X, Y);
		
		var UF = new UnionFind(N, Y);
		var ST = new SegTreeMax(N);
		for(int i=0;i<N;i++){
			ST.Update(i, Y[i]);
		}
		
		for(int i=0;i<N;i++){
			int ymin = UF.Min(i);
			int idx = ST.FindLeftMost(i + 1, N, ymin);
			//Console.WriteLine("i:{0}, X[i]:{1}, Y[i]:{2}, ymin:{3}, idx:{4}",i,X[i],Y[i],ymin,idx);
			if(idx == -1) continue;
			UF.Unite(i, idx);
		}
		
		int[] ans = new int[N];
		for(int i=0;i<N;i++) ans[i] = UF.MemCnt(i);
		int[] ans2 = new int[N];
		for(int i=0;i<N;i++) ans2[ord[X[i]]] = ans[i];
		
		
		Console.WriteLine(String.Join("\n", ans2));
		
		
		
	}
	int N;
	int[] X,Y;
	public Sol(){
		N = ri();
		X = new int[N];
		Y = new int[N];
		for(int i=0;i<N;i++){
			var d = ria();
			X[i] = d[0]; Y[i] = d[1];
		}
	}

	static String rs(){return Console.ReadLine();}
	static int ri(){return int.Parse(Console.ReadLine());}
	static long rl(){return long.Parse(Console.ReadLine());}
	static double rd(){return double.Parse(Console.ReadLine());}
	static String[] rsa(char sep=' '){return Console.ReadLine().Split(sep);}
	static int[] ria(char sep=' '){return Array.ConvertAll(Console.ReadLine().Split(sep),e=>int.Parse(e));}
	static long[] rla(char sep=' '){return Array.ConvertAll(Console.ReadLine().Split(sep),e=>long.Parse(e));}
	static double[] rda(char sep=' '){return Array.ConvertAll(Console.ReadLine().Split(sep),e=>double.Parse(e));}
}



class SegTreeMax{
	//segment Tree 
	// 0-origin
	protected int[] Data;	
	protected int Inf;	
	protected int N;		
	protected int n;		
	
	public SegTreeMax(int n_){
		N = n_; Inf = (int)1e9;
		n = 1;
		while(n < n_) n *= 2;
		Data = new int[2 * n - 1];
		for(int i=0; i < 2 * n - 1; i++) Data[i] = -Inf;
	}
	
	//	   0
	//	 1   2
	//	3 4 5 6
	public void Update(int k,int a){
		k+=n-1;	
		Data[k]=a;
		while(k>0){
			k=(k-1)/2;
			Data[k]=Math.Max(Data[k*2+1],Data[k*2+2]);
		}
	}
	
	
	public int QueryMax(int a, int b){
		return Query(a, b, 0, 0, n);
	}
	//RMQ; [a,b)
	public int Query(int a,int b,int k,int l,int r){
		if(r <= a || b <= l) return Inf;
		if(a <= l && r <= b) return Data[k];
		
		var vl = Query(a, b, k * 2 + 1, l, (l + r) / 2);
		var vr = Query(a ,b, k * 2 + 2, (l + r) / 2, r);
		return Math.Max(vl, vr);
	}
	
	
	public int FindLeftMost(int a, int b, int v){
		return FindLeftMost(a, b, v, 0, 0, n);
	}
	int FindLeftMost(int a, int b, int v, int k, int l, int r){
		//Console.WriteLine("a:{0}, b;{1}, v:{2}, k;{3}, l;{4}, r:{5}, Data[k];{6}",a,b,v,k,l,r,Data[k]);
		if(Data[k] < v) return -1;
		if(r <= a || b <= l) return -1;
		if(k >= n - 1) return k - (n - 1);
		
		var ret = FindLeftMost(a, b, v, k * 2 + 1, l, (l + r) / 2);
		if(ret == -1) return FindLeftMost(a, b, v, k * 2 + 2, (l + r) / 2, r);
		else return ret;
		
	}
	
	public void Dump(){
		Console.WriteLine();
		int h = 0;
		int cnt = 0;
		for(int i=0;i<Data.Length;i++){
			Console.Write("{0} ", Data[i]);
			cnt++;
			if(cnt == 1 << h){
				cnt = 0;
				h++;
				Console.WriteLine();
			}
		}
	}
	
}

class UnionFind{
	
	int[] parent;
	int[] mem;
	int[] min;
	int compo;
	int N;
	public UnionFind(int n_, int[] mi_){
		Initialize(n_, mi_);
	}
	
	public void Initialize(int n_, int[] mi){
		N=n_;
		parent = new int[N];
		mem = new int[N];
		min = new int[N];
		for(int i=0;i<N;i++){
			parent[i]=i;
			mem[i]=1;
			min[i] = mi[i];
		}
		compo=N;
	}
	
	
	public int Parent(int a){
		if(parent[a]==a) return a;
		return parent[a] = Parent(parent[a]);
	}
	
	public bool IsUnited(int a,int b){
		return Parent(a) == Parent(b);
	}
	
	public void Unite(int a,int b){
		a = Parent(a); b = Parent(b);//Parent()を呼ぶことでa以上のノードは全てparentがrootになる
		if(a == b) return;
		if(mem[a] > mem[b]){var t = a; a = b; b = t;}
		parent[a] = b;
		mem[b] += mem[a];
		min[b] = Math.Min(min[b], min[a]);
		compo -= 1;
	}
	
	public bool IsRoot(int x){
		return x == parent[x];
	}
	public int MemCnt(int x){
		return mem[Parent(x)];
	}
	public int Min(int x){
		return min[Parent(x)];
	}
	
	public void Dump(){
		for(int i=0;i<parent.Length;i++){
			Console.Write(i==0?"{0}":" {0}",parent[i]);
		}
		Console.WriteLine("");
	}
	
	public int Compo{
		get{
			return compo;
		}
	}
	
}