#include #include #include #include /** * 497. Random Point in Non-overlapping Rectangles * * You are given an array of non-overlapping axis-aligned rectangles rects where rects[i] = [ai, bi, xi, yi] indicates that (ai, bi) is the bottom-left corner point of the ith rectangle and (xi, yi) is the top-right corner point of the ith rectangle. Design an algorithm to pick a random integer point inside the space covered by one of the given rectangles. A point on the perimeter of a rectangle is included in the space covered by the rectangle. * Any integer point inside the space covered by one of the given rectangles should be equally likely to be returned. * Note that an integer point is a point that has integer coordinates. * Implement the Solution class: * Solution(int[][] rects) Initializes the object with the given rectangles rects. * int[] pick() Returns a random integer point [u, v] inside the space covered by one of the given rectangles. */ class Solution { private: std::vector> r; std::vector pSum; int total; std::mt19937 rnd; int randIntN(int n) { return rnd() % n; } public: explicit Solution(std::vector> rects) { r = std::move(rects); rnd = std::mt19937(std::time(nullptr)); pSum = std::vector(r.size()); for (int i = 1; i < r.size(); ++i) { const auto& x = r[i - 1]; pSum[i] = pSum[i - 1] + (x[2] - x[0] + 1) * (x[3] - x[1] + 1); } total = pSum.back() + (r.back()[2] - r.back()[0] + 1) * (r.back()[3] - r.back()[1] + 1); } std::vector pick() { int pno = randIntN(total); int rno = std::upper_bound(pSum.begin(), pSum.end(), pno) - pSum.begin() - 1; const auto& t = r[rno]; int x1 = t[0], y1 = t[1], x2 = t[2], y2 = t[3], rn = pno - pSum[rno]; return {x1 + rn / (y2 - y1 + 1), y1 + rn % (y2 - y1 + 1)}; } }; int main() { std::vector> rect {{82918473,-57180867,82918476,-57180863},{83793579,18088559,83793580,18088560},{66574245,26243152,66574246,26243153},{72983930,11921716,72983934,11921720}}; Solution s(rect); for (int i = 0; ; ++i) { auto x = s.pick(); bool OK = false; for (const auto& r : rect) { if (x[0] >= r[0] && x[0] <= r[2] && x[1] >= r[1] && x[1] <= r[3]) { OK = true; break; } } if (!OK) { std::printf("0x%08X: Failed when returning {%d, %d}\n", i, x[0], x[1]); } else { // std::printf("0x%08X: OK\n", i); } } return 0; }