[AtCoder] E - Packing Under Range Regulations

 

Key idea: For a given box and a list of balls that can be placed in this box,  we should choose the ball with the smallest R. 

Proof:  say we have box B and ball X and Y with R[X] < R[Y].  If we put ball Y in B, then ball X must be put in another box C, with C > B. There will be 2 cases to consider:

1. R[X] <= C: we can simply swap the position of ball X and Y, without impacting the final answer. 

2. R[X] > C:  we can not put ball X to box C, this will turn the answer from yes to no.

 

Solution:

1. sort all [L, R] in increasing L order. 

2. start from the 1st box, iterate [L, R] ranges from left to right, as long as a ball can be placed in the current box, add the ball's right bound R to a min heap H. 

optimization: there are up to 10^9 boxes, so incrementing the current box number by 1 at a time is too slow. There are only up to 2 * 10^5 balls, so most of the 10^9 boxes will be unoccupied. 

To speed up this simulation process, we check if the min heap H is empty before we try to add balls' right bound R to H.

If H is empty, it means no balls can be placed to any of the boxes in [current box,  current unprocessed box's L - 1], we can simply set the current box number to be current unprocessed box's L.

3. pick the ball with the smallest R from the min heap and try to put it in the current box. If impossible, the answer is No. Otherwise move to the next box. 

 

    static void solve(int testCnt) {
        for (int testNumber = 0; testNumber < testCnt; testNumber++) {
            int n = in.nextInt();
            int[][] a = new int[n][];
            for(int i = 0; i < n; i++) {
                a[i] = in.nextIntArrayPrimitive(2);
            }
            Arrays.sort(a, (e1, e2) -> {
                if(e1[0] != e2[0]) {
                    return e1[0] - e2[0];
                }
                return e1[1] - e2[1];
            });
            //process all ranges from left to right and keep the current box number
            //if the current box number == the current left bound of a range, add the current ball's right bound to a min heap

            boolean ans = true;
            int currBoxNum = 1;
            PriorityQueue<Integer> rightBoundOfBallsToBePlaced = new PriorityQueue<>();
            int i = 0;
            while(i < n) {
                if(rightBoundOfBallsToBePlaced.size() == 0) {
                    currBoxNum = a[i][0];
                }
                while(i < n && a[i][0] == currBoxNum) {
                    rightBoundOfBallsToBePlaced.add(a[i][1]);
                    i++;
                }
                if(rightBoundOfBallsToBePlaced.size() > 0) {
                    if(rightBoundOfBallsToBePlaced.peek() < currBoxNum) {
                        ans = false;
                        break;
                    }
                    rightBoundOfBallsToBePlaced.poll();
                    currBoxNum++;
                }
            }
            while(rightBoundOfBallsToBePlaced.size() > 0 && rightBoundOfBallsToBePlaced.peek() >= currBoxNum) {
                rightBoundOfBallsToBePlaced.poll();
                currBoxNum++;
            }
            ans &= rightBoundOfBallsToBePlaced.size() == 0;
            out.println(ans ? "Yes" : "No");
        }
        out.close();
    }

 

posted @ 2023-10-01 02:50  Review->Improve  阅读(18)  评论(0编辑  收藏  举报