Leetcode 391. Perfect Rectangle

想切题, 开个博客督促下自己。
但最近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;
    }
};


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值