#include #include #include #include namespace std { template<> struct hash> { inline std::size_t operator()(const std::pair& v) const { return std::hash()(v.first) ^ std::hash()(v.second); } }; } class DetectSquaresOld { private: std::unordered_multiset> s; public: DetectSquaresOld() = default; void add(const std::vector& point) { s.insert(std::make_pair(point[0], point[1])); } int count(const std::vector& point) const { int ret = 0; // Point 1 auto p1 = std::make_pair(point[0], point[1]); // Point 2's have same X index as Point 1. std::vector> p2s; std::copy_if(s.begin(), s.end(), std::back_inserter(p2s), [&](const std::pair& v) { return v.first == p1.first && v.second != p1.second; } ); for (const auto& p2 : p2s) { // Now, we know what Point 3 and Point 4 looks like. // Point 1 is (x, y) // Point 2 is (x, y + dist) // Point 3 is (x +/- dist, y + dist) // Point 4 is (x +/- dist, y) ret += s.count(std::make_pair(p1.first + (p2.second - p1.second), p2.second)) * s.count(std::make_pair(p1.first + (p2.second - p1.second), p1.second)); ret += s.count(std::make_pair(p1.first - (p2.second - p1.second), p2.second)) * s.count(std::make_pair(p1.first - (p2.second - p1.second), p1.second)); /* ret += std::count_if(s.begin(), s.end(), [&](const std::pair& v) { // Point 3, + return (v.second == p2.second) && (v.first == p1.first + (p2.second - p1.second)); }) * std::count_if(s.begin(), s.end(), [&](const std::pair& v) { // Point 4, + return (v.second == p1.second) && (v.first == p1.first + (p2.second - p1.second)); }) + std::count_if(s.begin(), s.end(), [&](const std::pair& v) { // Point 3, - return (v.second == p2.second) && (v.first == p1.first - (p2.second - p1.second)); }) * std::count_if(s.begin(), s.end(), [&](const std::pair& v) { // Point 4, - return (v.second == p1.second) && (v.first == p1.first - (p2.second - p1.second)); }); */ } return ret; } }; /** * 2013. Detect Squares * You are given a stream of points on the X-Y plane. Design an algorithm that: * * Adds new points from the stream into a data structure. Duplicate points are allowed and should be treated as different points. * Given a query point, counts the number of ways to choose three points from the data structure such that the three points and the query point form an axis-aligned square with positive area. * An axis-aligned square is a square whose edges are all the same length and are either parallel or perpendicular to the x-axis and y-axis. * * Implement the DetectSquares class: * * DetectSquares() Initializes the object with an empty data structure. * void add(int[] point) Adds a new point point = [x, y] to the data structure. * int count(int[] point) Counts the number of ways to form axis-aligned squares with point point = [x, y] as described above. */ class DetectSquares { private: std::unordered_multiset indexX[1002], indexY[1002]; public: DetectSquares() = default; void add(const std::vector& point) { indexX[point[0]].insert(point[1]); indexY[point[1]].insert(point[0]); } int count(const std::vector& point) const { int ret = 0; // Point 2's have same X index as Point 1. std::unordered_map p2s; for (const int p2Y : indexX[point[0]]) { if (p2Y != point[1]) { ++p2s[p2Y]; } } for (const auto& p2C : p2s) { // Now, we know what Point 3 and Point 4 looks like. // Point 1 is (x, y) // Point 2 is (x, y + dist) // Point 3 is (x +/- dist, y + dist) // Point 4 is (x +/- dist, y) int dist = p2C.first - point[1]; ret += indexY[p2C.first].count(point[0] + dist) * indexY[point[1]].count(point[0] + dist) * p2C.second; ret += indexY[p2C.first].count(point[0] - dist) * indexY[point[1]].count(point[0] - dist) * p2C.second; } return ret; } }; int main() { DetectSquares detectSquares; detectSquares.add({3, 10}); detectSquares.add({11, 2}); detectSquares.add({3, 2}); std::cout << std::endl << detectSquares.count({11, 10}); std::cout << std::endl << detectSquares.count({14, 8}); detectSquares.add({11, 2}); std::cout << std::endl << detectSquares.count({11, 10}); return 0; }