想切题, 开个博客督促下自己。
但最近wrong answer(42/45 test cases passed) 的好心烦, 代码贴出来, 谁有空可以帮我挑挑bug。
题目:
Given N axis-aligned rectangles where N > 0, determine if they all together form an exact cover of a rectangular region.
Each rectangle is represented as a bottom-left point and a top-right point. For example, a unit square is represented as [1,1,2,2]. (coordinate of bottom-left point is (1, 1) and top-right point is (2, 2)).
https://leetcode.com/problems/perfect-rectangle/
思路:
题目给定n个矩形, 判定是否可以不重合(non-overlap)的拼成一个大矩形。
step 1) 第一反应对坐标进行离散化, 把原有的矩形映射到[0, 2n-1] * [0, 2n-1]的范围内, 这样自然就得到了O(n^2)的算法(可对每个方块枚举它被覆盖的次数).
step 2) 更进一步优化下, 可以把矩形的拼接想象成盖房子, 优先级自然的是肯定是从下到上。如此覆盖完毕若所有方块仅被覆盖一次则拼接成功,不然则失败。
我们维持[0, n]上的一个线段树, 每次加盖矩形的时候对相应区间累加。 但在累加前应判定矩形下面是平整的并且可以和当前矩形完美拼接上即可。
证明:
Order all rectangles Ri(x1i, y1i, x2i, y2i) based on y1i only.
When we insert Ri, for any j in [1, i-1],
#define INF (0x3f3f3f3f)
struct R{
int x1, y1, x2, y2;
R(int a, int b, int c, int d) : x1(a), y1(b), x2(c), y2(d){}
bool operator<(const R& rhs) const {
return y1 < rhs.y1 || (y1 == rhs.y1 && x1 < rhs.x1);
}
};
struct node{
int low, high;
node *left, *right;
bool need_update;
int incr;
node(int c){low = high = c; left = right = NULL; need_update = false;}
};
struct RT{
node * root;
int a, b;
RT(int l, int r, int v){
a = l, b = r;
root = build(a, b, v);
}
node* build(int l, int r, int v){
node* ref = new node(v);
if(l != r){
int m = l + (r-l)/2;
ref->left = build(l, m, v);
ref->right = build(m+1, r, v);
}
return ref;
}
int get_min(int l, int r){
return get_min(root, a, b, l, r);
}
int get_max(int l, int r){
return get_max(root, a, b, l, r);
}
void add(int l, int r, int h){
add(root, a, b, l, r, h);
}
int get_min(node* ref, int nl, int nr, int l, int r){
if(nl >= l && nr <= r)
return ref->low;
if(nl > r || nr < l)
return INF;
int m = nl + (nr - nl)/2;
if(ref->need_update){
add(ref->left, nl, m, nl, m, ref->incr);
add(ref->right, m+1, nr, m+1, nr, ref->incr);
ref->need_update = false;
}
int p = get_min(ref->left, nl, m, l, r);
int q = get_min(ref->right, m+1, nr, l, r);
return min(p, q);
}
int get_max(node* ref, int nl, int nr, int l, int r){
if(nl >= l && nr <= r)
return ref->high;
if(nl > r || nr < l)
return -INF;
int m = nl + (nr - nl)/2;
if(ref->need_update){
add(ref->left, nl, m, nl, m, ref->incr);
add(ref->right, m+1, nr, m+1, nr, ref->incr);
ref->need_update = false;
}
int p = get_max(ref->left, nl, m, l, r);
int q = get_max(ref->right, m+1, nr, l, r);
return max(p, q);
}
void add(node* ref, int nl, int nr, int l, int r, int h){
if(nl >= l && nr <= r){
ref->low += h;
ref->high += h;
if(nr > nl){
ref->need_update = true;
ref->incr = h;
}
return;
}else if(nl > r || nr < l){
return;
}else{
int m = nl + (nr - nl)/2;
add(ref->left, nl, m, l, r, h);
add(ref->right, m+1, nr, l, r, h);
ref->low = min(ref->left->low, ref->right->low);
ref->high = min(ref->left->high, ref->right->high);
}
return;
}
};
class Solution {
public:
bool isRectangleCover(vector<vector<int>>& rectangles) {
vector<int> x, y;
for(auto v : rectangles){
x.push_back(v[0]);
x.push_back(v[2]);
y.push_back(v[1]);
y.push_back(v[3]);
}
sort(x.begin(), x.end());
sort(y.begin(), y.end());
auto xit = unique(x.begin(), x.end());
auto yit = unique(y.begin(), y.end());
x.resize(distance(x.begin(), xit));
y.resize(distance(y.begin(), yit));
map<int, int> mx, my;
for(int i = 0; i < x.size(); i++)
mx[x[i]] = i;
for(int i = 0; i < y.size(); i++)
my[y[i]] = i;
int max_x = x.size() - 1;
int max_y = y.size() - 1;
vector<R> rs;
for(auto v : rectangles)
rs.push_back(R(mx[v[0]], my[v[1]], mx[v[2]], my[v[3]]));
sort(rs.begin(), rs.end());
RT t(0, max_x - 1, 0);
for(auto r : rs){
int l = t.get_min(r.x1, r.x2-1);
int h = t.get_max(r.x1, r.x2-1);
if(l != h || l != r.y1)
return false;
t.add(r.x1, r.x2-1, r.y2-r.y1);
}
return t.get_min(0, max_x-1) == max_y && t.get_max(0, max_x - 1) == max_y;
}
};