经典line sweep问题,和 perfect rectangle 很类似,但是要考虑多个矩形左边界一样的情况,加个id来区分。
和另一道类似的题 the skyline problem 不同的是,没有很多 corner cases,对 x 排序非常简单。
难点是在 active set 里,和 merge intervals 那题一样,计算 total_y,乘以两个相邻 event 的 delta_x。
class Solution { public: struct interval { int start, end; bool operator<(const interval &i) const { if (start == i.start) return end < i.end; return start < i.start; } }; struct edge { int x; interval i; int type; // left <- 1, right <- -1 int id; }; int rectangleArea(vector<vector<int>>& rectangles) { vector<edge> vec; for (int i=0;i<rectangles.size();++i){ auto rect=rectangles[i]; vec.push_back({rect[0],{rect[1],rect[3]},1,i}); vec.push_back({rect[2],{rect[1],rect[3]},-1,i}); } sort(vec.begin(),vec.end(),[](edge e1, edge e2){ return e1.x < e2.x; }); set<pair<interval,int>> active_set; // <interval,id> active_set.insert({vec[0].i,vec[0].id}); int prev_x=vec[0].x; int res=0; for (int i=1;i<vec.size();++i){ int delta_x=vec[i].x-prev_x; // merge interval int s=-1,e=-1; int total_y=0; for (auto m:active_set){ interval i=m.first; int id=m.second; if (s==-1 || i.start>e){ total_y += e-s; s = i.start; e = i.end; }else{ e = max(e,i.end); } } total_y += e-s; res = (res + long(delta_x)*total_y) % 1000000007; if (vec[i].type==1) active_set.insert({vec[i].i,vec[i].id}); else active_set.erase({vec[i].i,vec[i].id}); prev_x = vec[i].x; } return res; } };
时间复杂度 O(nlogn)
Reference
https://leetcode.com/problems/rectangle-area-ii/solution/
Computational Geometry - Line Sweep - 3 - Rectangles Union (Arabic)