/*
*/

#pragma GCC optimize("O3")
#define _CRT_SECURE_NO_WARNINGS
#include <fstream>
#include <iostream>
#include <string>
#include <complex>
#include <math.h>
#include <set>
#include <vector>
#include <map>
#include <queue>
#include <stdio.h>
#include <stack>
#include <algorithm>
#include <list>
#include <ctime>

#include <memory.h>
#include <assert.h>

#define y0 sdkfaslhagaklsldk

#define y1 aasdfasdfasdf
#define yn askfhwqriuperikldjk
#define j1 assdgsdgasghsf
#define tm sdfjahlfasfh
#define lr asgasgash
#define norm asdfasdgasdgsd
#define have adsgagshdshfhds
#define ends asdgahhfdsfshdshfd
#define prev asdgSHJsfgsdfhdsh
#define hash asdgasdgasdgdfrywewery

#define eps 1e-9
#define M_PI 3.141592653589793
#define bsize 300

#define ldouble long double
using namespace std;

#define bs 1000000007

const int N = 300031;

int n;
int x[N],y[N];
int with_x[N],with_y[N];

int used[N];
set<int> sx,sy;

set<int> alive_x[N],alive_y[N];

long long count_s(int x){
	return x;
}

long long C;

void dfs(int v){
	++C;
	used[v]=1;
	sx.insert(x[v]);
	sy.insert(y[v]);
	alive_x[x[v]].erase(v);
	alive_y[y[v]].erase(v);

	while (alive_x[x[v]].size()){
		int id=*(alive_x[x[v]].begin());
		dfs(id);
	}
	while (alive_y[y[v]].size()){
		int id=*(alive_y[y[v]].begin());
		dfs(id);
	}
}

long long count_angles(){
	for (int i=1;i<=n;i++){
		used[i]=0;
	}

	long long ans=0;

	for (int i=1;i<=n;i++){
		alive_x[x[i]].insert(i);
		alive_y[y[i]].insert(i);
	}

	for (int i=1;i<=n;i++){
		if (used[i]==0){
			C=0;
			sx.clear();
			sy.clear();
			dfs(i);
			ans+=count_s(sx.size())*count_s(sy.size());
		}
	}
	return ans;
}

const int MA = 300;

long long RECT;

vector<int> entries[N];

vector<int> heavy,light;

map<pair<int,int>,int> mp;

long long solve_light_light(){
	mp.clear();
	long long ret=0;

	for (int i=0;i<light.size();i++){
		int id=light[i];
		for (int j=0;j<entries[id].size();j++){
			for (int q=j+1;q<entries[id].size();q++){
				pair<int,int> p=make_pair(y[entries[id][j]],y[entries[id][q]]);
				ret+=mp[p];
				mp[p]++;
			}
		}
	}
	return ret;
}

int solve_pair_h_h(int a,int b){
	int ptr1=0;
	int ptr2=0;
	int ret=0;
	while (ptr1<entries[a].size()&&ptr2<entries[b].size()){
		if (y[entries[a][ptr1]]==y[entries[b][ptr2]])
			++ret;
		if (y[entries[a][ptr1]]<y[entries[b][ptr2]])
			++ptr1;
		else
			++ptr2;
	}
	return 1ll*ret*(ret-1)/2;
}


long long solve_heavy_heavy(){
	long long ret=0;

	for (int i=0;i<heavy.size();i++){
		for (int j=i+1;j<heavy.size();j++){
			ret+=solve_pair_h_h(heavy[i],heavy[j]);
		}
	}
	return ret;
}

bool cmp(int a,int b){
	return y[a]<y[b];
}

set<int> xs[N];


long long solve_pair_l_h(int l,int h){
	int p=0;
	for (int i=0;i<entries[l].size();i++){
		int Q=y[entries[l][i]];
		if (xs[h].find(Q)!=xs[h].end())
			++p;
	}
	return 1ll*p*(p-1)/2;
}

long long solve_light_heavy(){
	long long ret=0;
	for (int i=0;i<light.size();i++){
		for (int j=0;j<heavy.size();j++){
			ret+=solve_pair_l_h(light[i],heavy[j]);
		}
	}
	return ret;
}

long long count_rect(){
	RECT=0;

	for (int i=1;i<=n;i++){
		entries[x[i]].push_back(i);
		xs[x[i]].insert(y[i]);
	}

	for (int i=1;i<=100000;i++){
		sort(entries[i].begin(),entries[i].end(),cmp);
	}

	for (int i=1;i<=100000;i++){
		if (entries[i].size()>MA)
			heavy.push_back(i);
		else
			light.push_back(i);
	}

	RECT+=solve_light_light();
	RECT+=solve_heavy_heavy();
	RECT+=solve_light_heavy();
	return RECT;
}

int main(){
//    freopen("apache.in","r",stdin);
//    freopen("apache.out","w",stdout);
    //freopen("input.txt", "r", stdin);
    //freopen("output.txt", "w", stdout);
    ios_base::sync_with_stdio(0);
 //   cin.tie(0);

    cin>>n;

    for (int i=1;i<=n;i++){
    	cin>>x[i]>>y[i];
    	with_x[x[i]]++;
    	with_y[y[i]]++;
    }


   // cout<<"@"<<count_rect()<<endl;

    cout<<count_angles()-n<<endl;

//    cin.get(); cin.get();
    return 0;
}


Measured memory_bytes: 66432