#include<bits/stdc++.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define HUGE_NUM 99999999999999999
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;



#define SIZE 100005
#define NUM 0

struct Info{

	int x_L1,x_L2,x_U1,x_U2;
};

struct Data{
	Data(int arg_value,int arg_index,bool arg_is_left){
		value = arg_value;
		index = arg_index;
		is_left = arg_is_left;
	}
	bool operator<(const struct Data &arg) const{

		return value < arg.value;
	}

	int value,index;
	bool is_left;
};

int N;
int table[8*SIZE];
int dp[SIZE];
Info info[SIZE];


void init(int first_N){
	while(N < first_N*2)N *= 2;
}

void update(int loc,int value){
	loc += N-1;

	table[loc] = value;

	if(N == 1)return;

	int parent = (loc-1)/2;

	while(true){
		table[parent] = max(table[2*parent+1],table[2*parent+2]);

		if(parent == 0)break;
		else{
			parent = (parent-1)/2;
		}
	}
}

int query(int search_left,int search_right,int node_id,int node_left,int node_right){

	if(search_right < node_left || search_left > node_right)return NUM;

	if(search_left <= node_left && search_right >= node_right){
		return table[node_id];
	}

	int left_max = query(search_left,search_right,2*node_id+1,node_left,(node_left+node_right)/2);
	int right_max = query(search_left,search_right,2*node_id+2,(node_left+node_right)/2+1,node_right);

	return max(left_max,right_max);
}


int main(){

	int first_N;

	scanf("%d",&first_N);

	vector<int> UPPER;
	vector<Data> V;

	for(int i = 0; i < first_N; i++){

		scanf("%d %d %d %d",&info[i].x_L1,&info[i].x_L2,&info[i].x_U1,&info[i].x_U2);

		//上辺
		UPPER.push_back(info[i].x_U1);
		UPPER.push_back(info[i].x_U2);

		//下辺
		V.push_back(Data(info[i].x_L1,i,true));
		V.push_back(Data(info[i].x_L2,i,false));
	}

	sort(UPPER.begin(),UPPER.end());
	sort(V.begin(),V.end());

	N = 1;
	init(first_N);

	for(int i = 0; i <= 2*N-2; i++){

		table[i] = 0;
	}

	for(int i = 0; i < first_N; i++){

		dp[i] = 0;
	}

	int L,R,mid;

	for(int i = 0; i < V.size(); i++){ //下辺の端点座標の昇順に走査

		int index = V[i].index;

		if(V[i].is_left){ //下辺左端の場合

			L = 0,R = UPPER.size()-1,mid = (L+R)/2;
			int loc;

			while(L <= R){

				if(info[index].x_U1 == UPPER[mid]){

					loc = mid;
					break;

				}else if(info[index].x_U1 > UPPER[mid]){

					L = mid+1;

				}else{

					R = mid-1;
				}
				mid = (L+R)/2;
			}

			dp[index] = query(0,loc-1,0,0,N-1)+1;

		}else{ //下辺右端の場合

			L = 0,R = UPPER.size()-1,mid = (L+R)/2;
			int loc;

			while(L <= R){

				if(info[index].x_U2 == UPPER[mid]){

					loc = mid;
					break;

				}else if(info[index].x_U2 > UPPER[mid]){

					L = mid+1;

				}else{

					R = mid-1;
				}
				mid = (L+R)/2;
			}

			update(loc,dp[index]);
		}
	}

	printf("%d\n",query(0,N-1,0,0,N-1));

	return 0;
}

