6043. 统计包含每个点的矩形数目

本文介绍了如何解决统计矩形包含特定点的数目问题,提出了四种不同的算法实现:暴力+二分、二维偏序与树状数组、Python排序+双指针以及名次树。每种方法都利用了数据特性,如高度限制和有序性,通过排序、二分查找和树状数组等数据结构来提高效率。
摘要由CSDN通过智能技术生成

6043. 统计包含每个点的矩形数目


题目

在这里插入图片描述


样例

在这里插入图片描述

输入:rectangles = [[1,1],[2,2],[3,3]], points = [[1,3],[1,1]]
输出:[1,3]
解释:
第一个矩形只包含点 (1, 1) 。
第二个矩形只包含点 (1, 1) 。
第三个矩形包含点 (1, 3) 和 (1, 1) 。
包含点 (1, 3) 的矩形数目为 1 。
包含点 (1, 1) 的矩形数目为 3 。
所以,我们返回 [1, 3] 。


数据

1 <= rectangles.length, points.length <= 5 * 104
rectangles[i].length == points[j].length == 2
1 <= li, xj <= 109
1 <= hi, yj <= 100
所有 rectangles 互不相同 。
所有 points 互不相同 。


暴力 + 二分

思路:

  • 由于高度最大100,所以考虑以此为突破口。(高:y;长,x)
  • 对每个y都存入对应矩阵的x,并排序。
  • 对每个点都枚100次y,然后二分到大于x的位置,加上贡献。
class Solution {
public:
    vector<int> countRectangles(vector<vector<int>>& rectangles, vector<vector<int>>& points) {
        vector<vector<int>> mp(110, vector<int>());
        for (auto &v: rectangles) mp[v[1]].push_back(v[0]);
        for (auto &v: mp) sort(v.begin(), v.end());

        vector<int> res;
        for (int i = 0; i < points.size(); i++) {
            auto &v = points[i];
            int a = v[0], b = v[1];
            int ans = 0;
            for (int j = 0; j < 110; j++) {
                auto &v = mp[j];
                if(!v.size() || j < b) continue;
                int d = lower_bound(v.begin(), v.end(), a) - v.begin();
                ans += v.size() - d;
            }
            res.push_back(ans);
        }
        return res;
    }
};

二维偏序问题:树状数组

思路:

  • 打包矩阵和点 ( x , y , i ) {(x,y,i)} (x,y,i),存入 v e c t o r {vector} vector中。(标记矩阵INF,点 i {i} i表示第 i {i} i个点)

  • 排序完后,倒序遍历 v e c t o r {vector} vector

    • 排序按 x , y , i {x,y,i} x,y,i依次排序
    • 遍历到矩阵,就加进 t r {tr} tr数组中
    • 遍历到点,此时 t r {tr} tr数组中都是 > = x {>=x} >=x && > = y {>=y} >=y
    • a n s [ i ] = s u m ( n ) − s u m ( y − 1 ) {ans[i] = sum(n) - sum(y-1)} ans[i]=sum(n)sum(y1)
class Solution {
public:
    static constexpr int N = 110;
    int tr[N + 1] = {0};
    
    int lowbit(int x) {
        return x & -x;
    }
    
    void add(int x, int c) {
        for (int i = x; i <= N; i += lowbit(i)) tr[i] += c;
    }
    
    int sum(int x) {
        int res = 0;
        for (int i = x; i; i -= lowbit(i)) res += tr[i];
        return res;
    }
    vector<int> countRectangles(vector<vector<int>>& rectangles, vector<vector<int>>& points) {
        vector<pair<pair<int, int>, int>> res;
        for (auto &v: rectangles) {
            res.push_back({{v[0], v[1]}, 0x3f3f3f3f});
        }
        for (int i = 0; i < points.size(); i++) {
            auto &v = points[i];
            res.push_back({{v[0], v[1]}, i});
        }
        sort(res.begin(), res.end());
        vector<int> ans(points.size());
        for (int i = res.size() - 1; i >= 0; i--) {
            auto &v = res[i];
            if(v.second == 0x3f3f3f3f) {
                add(v.first.second, 1);
            } else {
                ans[v.second] = sum(N) - sum(v.first.second - 1);
            }
        }
        return ans;
    }
};

Python

排序 + 双指针

参考灵茶山艾府

思路:

  • 对矩阵和点都进行 y {y} y降序排列。
  • 每次插完 x {x} x坐标后,对 x s {xs} xs进行排序,二分出 > = x {>=x} >=x的矩阵个数。
  • 由于我们是按纵坐标从大到小遍历的,因此这些矩形的纵坐标均不小于 y {y} y
class Solution:
    def countRectangles(self, rectangles: List[List[int]], points: List[List[int]]) -> List[int]:
        rectangles.sort(key=lambda r: -r[1])
        n = len(points)
        ans = [0] * n
        i, xs = 0, []
        for (x, y), id in sorted(zip(points, range(n)), key=lambda x: -x[0][1]):
            start = i
            while i < len(rectangles) and y <= rectangles[i][1]:
                xs.append(rectangles[i][0])
                i += 1
            if start < i:
                xs.sort()  # 只有在 xs 插入了新元素时才排序
            ans[id] = i - bisect_left(xs, x)
        return ans


名次树:(SortedList)

如果x<=1e9 && y<=1e9

from sortedcontainers import SortedList

class Solution:
    def countRectangles(self, rectangles: List[List[int]], points: List[List[int]]) -> List[int]:
        rectangles.sort(key=lambda r: -r[1])
        n = len(points)
        ans = [0] * n
        i, xs = 0, SortedList()
        for (x, y), id in sorted(zip(points, range(n)), key=lambda x: -x[0][1]):
            while i < len(rectangles) and y <= rectangles[i][1]:
                xs.add(rectangles[i][0])
                i += 1
            ans[id] = i - xs.bisect_left(x)
        return ans
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ღCauchyོꦿ࿐

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值