矩形重叠

链接
平面内有n个矩形, 第i个矩形的左下角坐标为(x1[i], y1[i]), 右上角坐标为(x2[i], y2[i])。
如果两个或者多个矩形有公共区域则认为它们是相互重叠的(不考虑边界和角落)。
请你计算出平面内重叠矩形数量最多的地方,有多少个矩形相互重叠。

import java.util.*;

public class Main {

    /**
     * 离散化横坐标
     *
     * @param rectangles
     * @return
     */
    private static Map<Integer, Integer> dispersed(Rectangle[] rectangles) {
        TreeSet<Integer> treeSet = new TreeSet<>();
        for (Rectangle rectangle : rectangles) {
            treeSet.add(rectangle.left);
            treeSet.add(rectangle.right - 1);
        }

        int index = 1;
        Map<Integer, Integer> retMap = new HashMap<>();
        for (int item : treeSet) {
            retMap.put(item, index ++);
        }
        return retMap;
    }

    private static int solve(Rectangle[] rectangles) {
        Arrays.sort(rectangles, new Comparator<Rectangle>() {
            @Override
            public int compare(Rectangle o1, Rectangle o2) {
                return Integer.compare(o1.down, o2.down);
            }
        });

        Map<Integer, Integer> dispersed = dispersed(rectangles);

        /**
         * 和线段最大重叠问题一样
         */
        PriorityQueue<Rectangle> queue = new PriorityQueue<>(new Comparator<Rectangle>() {
            @Override
            public int compare(Rectangle o1, Rectangle o2) {
                return Integer.compare(o1.up, o2.up);
            }
        });

        int segmentSize = dispersed.size();
        SegmentTree segmentTree = new SegmentTree(segmentSize);

        int L, R;

        int ret = 0;

        for (Rectangle rectangle : rectangles) {
            while (!queue.isEmpty() && queue.peek().up <= rectangle.down) {
                Rectangle poll = queue.poll();
                L = dispersed.get(poll.left);
                R = dispersed.get(poll.right - 1);
                segmentTree.add(L, R, -1, 1, segmentSize, 1);
            }
            queue.offer(rectangle);
            L = dispersed.get(rectangle.left);
            R = dispersed.get(rectangle.right - 1);
            segmentTree.add(L, R, 1, 1, segmentSize, 1);
            ret = Math.max(ret, segmentTree.query(L, R, 1, segmentSize, 1));
        }
        return ret;
    }

    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        while (in.hasNext()) {
            int n = in.nextInt();
            Rectangle[] rectangles = new Rectangle[n];
            for (int i = 0; i < n; ++i) {
                rectangles[i] = new Rectangle();
            }

            for (int i = 0; i < n; ++i) {
                rectangles[i].left = in.nextInt();
            }

            for (int i = 0; i < n; ++i) {
                rectangles[i].down = in.nextInt();
            }

            for (int i = 0; i < n; ++i) {
                rectangles[i].right = in.nextInt();
            }

            for (int i = 0; i < n; ++i) {
                rectangles[i].up = in.nextInt();
            }

            System.out.println(solve(rectangles));
        }
    }
}

class SegmentTree {
    private int n;
    private int[] max;
    private int[] lazy;

    public SegmentTree(int n) {
        this.n = n;
        this.max = new int[n << 2 | 1];
        this.lazy = new int[n << 2 | 1];
    }

    private void pushUp(int rt) {
        max[rt] = Math.max(max[rt << 1], max[rt << 1 | 1]);
    }

    private void pushDown(int rt) {
        if (lazy[rt] != 0) {
            lazy[rt << 1] += lazy[rt];
            lazy[rt << 1 | 1] += lazy[rt];
            max[rt << 1] += lazy[rt];
            max[rt << 1 | 1] += lazy[rt];
            lazy[rt] = 0;
        }
    }

    public void add(int L, int R, int V, int l, int r, int rt) {
        if (L <= l && r <= R) {
            max[rt] += V;
            lazy[rt] += V;
            return;
        }
        int mid = (l + r) >> 1;
        pushDown(rt);
        if (L <= mid) {
            add(L, R, V, l, mid, rt << 1);
        }

        if (mid < R) {
            add(L, R, V, mid + 1, r, rt << 1 | 1);
        }
        pushUp(rt);
    }

    public int query(int L, int R, int l, int r, int rt) {
        if (l == r) {
            return max[rt];
        }
        int mid = (l + r) >> 1;
        pushDown(rt);
        int ret = 0;
        if (L <= mid) {
            ret = Math.max(ret, query(L, R, l, mid, rt << 1));
        }

        if (mid < R) {
            ret = Math.max(ret, query(L, R, mid + 1, r, rt << 1 | 1));
        }

        return ret;
    }
}

class Rectangle {
    int up;
    int down;
    int left;
    int right;
}
posted @ 2021-10-12 22:08  Tianyiya  阅读(60)  评论(0)    收藏  举报