#include #include #include #include using namespace std; class Point { public: Point(const int _x = 0, const int _y = 0): x(_x), y(_y) {} int X() const { return x; } int Y() const { return y; } long long HashCode() const { return 1LL * x * BASE + y; } bool operator==(const Point &other) const { return (x == other.x && y == other.y); } private: static const int BASE = 1000000007; int x, y; }; template class Hash { public: Hash() {} bool Find(const Type &object) const { int key = GetKey(object.HashCode()); for (int i = 0; i < int(table[key].size()); ++i) if (object == table[key][i]) return true; return false; } void Insert(const Type &object) { int key = GetKey(object.HashCode()); if (!Find(object)) table[key].push_back(object); } private: static const int U = 666013; vector table[U]; static int GetKey(const long long hashCode) { return hashCode % U; } }; vector Points; int N, Answer; Hash HashedPoints; class CompareX { public: bool operator()(const int a, const int b) const { return Points[a].X() < Points[b].X(); } }; class CompareY { public: bool operator()(const int a, const int b) const { return Points[a].Y() < Points[b].Y(); } }; void Solve() { map< int, vector > verticalLines, horizontalLines; for (int i = 0; i < N; ++i) { if (verticalLines.count(Points[i].X()) == 0) verticalLines[Points[i].X()] = vector(); verticalLines[Points[i].X()].push_back(i); if (horizontalLines.count(Points[i].Y()) == 0) horizontalLines[Points[i].Y()] = vector(); horizontalLines[Points[i].Y()].push_back(i); } vector verticalIndex = vector(N, -1), horizontalIndex = vector(N, -1); for (map< int, vector >::iterator x = verticalLines.begin(); x != verticalLines.end(); ++x) { sort(x->second.begin(), x->second.end(), CompareX()); for (int i = 0; i < int(x->second.size()); ++i) verticalIndex[x->second[i]] = i; } for (map< int, vector >::iterator y = horizontalLines.begin(); y != horizontalLines.end(); ++y) { sort(y->second.begin(), y->second.end(), CompareY()); for (int i = 0; i < int(y->second.size()); ++i) horizontalIndex[y->second[i]] = i; } Answer = 0; for (int i = 0; i < N; ++i) { vector &xLine = verticalLines[Points[i].X()], &yLine = horizontalLines[Points[i].Y()]; int x = verticalIndex[i], y = horizontalIndex[i]; // up and right if (int(xLine.size()) - x < int(yLine.size()) - y) { for (int j = x + 1; j < int(xLine.size()); ++j) if (HashedPoints.Find(Point(Points[i].X() + Points[xLine[j]].Y() - Points[i].Y(), Points[i].Y()))) ++Answer; } else { for (int j = y + 1; j < int(yLine.size()); ++j) if (HashedPoints.Find(Point(Points[i].X(), Points[i].Y() + Points[yLine[j]].X() - Points[i].X()))) ++Answer; } //right and down if (x - 1 < int(yLine.size()) - y) { for (int j = x - 1; j >= 0; --j) if (HashedPoints.Find(Point(Points[i].X() - Points[xLine[j]].Y() + Points[i].Y(), Points[i].Y()))) ++Answer; } else { for (int j = y + 1; j < int(yLine.size()); ++j) if (HashedPoints.Find(Point(Points[i].X(), Points[i].Y() - Points[yLine[j]].X() + Points[i].X()))) ++Answer; } //down and left if (x - 1 < y - 1) { for (int j = x - 1; j >= 0; --j) if (HashedPoints.Find(Point(Points[i].X() + Points[xLine[j]].Y() - Points[i].Y(), Points[i].Y()))) ++Answer; } else { for (int j = y - 1; j >= 0; --j) if (HashedPoints.Find(Point(Points[i].X(), Points[i].Y() + Points[yLine[j]].X() - Points[i].X()))) ++Answer; } //left and up if (int(xLine.size()) - x < y - 1) { for (int j = x + 1; j < int(xLine.size()); ++j) if (HashedPoints.Find(Point(Points[i].X() + Points[xLine[j]].Y() - Points[i].Y(), Points[i].Y()))) ++Answer; } else { for (int j = y - 1; j >= 0; --j) if (HashedPoints.Find(Point(Points[i].X(), Points[i].Y() - Points[yLine[j]].X() + Points[i].X()))) ++Answer; } } } void Read() { cin >> N; Points = vector(N); for (int i = 0; i < N; ++i) { int x, y; cin >> x >> y; Points[i] = Point(x, y); HashedPoints.Insert(Points[i]); } } void Print() { cout << Answer << "\n"; } int main() { Read(); Solve(); Print(); return 0; }