2940. Find Building Where Alice and Bob Can Meet

You are given a 0-indexed array heights of positive integers, where heights[i] represents the height of the ith building.

If a person is in building i, they can move to any other building j if and only if i < j and heights[i] < heights[j].

You are also given another array queries where queries[i] = [ai, bi]. On the ith query, Alice is in building ai while Bob is in building bi.

Return an array ans where ans[i] is the index of the leftmost building where Alice and Bob can meet on the ith queryIf Alice and Bob cannot move to a common building on query iset ans[i] to -1.

 Example 1:

Input: heights = [6,4,8,5,2,7], queries = [[0,1],[0,3],[2,4],[3,4],[2,2]]
Output: [2,5,-1,5,2]
Explanation: In the first query, Alice and Bob can move to building 2 since heights[0] < heights[2] and heights[1] < heights[2]. 
In the second query, Alice and Bob can move to building 5 since heights[0] < heights[5] and heights[3] < heights[5]. 
In the third query, Alice cannot meet Bob since Alice cannot move to any other building.
In the fourth query, Alice and Bob can move to building 5 since heights[3] < heights[5] and heights[4] < heights[5].
In the fifth query, Alice and Bob are already in the same building.  
For ans[i] != -1, It can be shown that ans[i] is the leftmost building where Alice and Bob can meet.
For ans[i] == -1, It can be shown that there is no building where Alice and Bob can meet.

Example 2:

Input: heights = [5,3,8,2,6,1,4,6], queries = [[0,7],[3,5],[5,2],[3,0],[1,6]]
Output: [7,6,-1,4,6]
Explanation: In the first query, Alice can directly move to Bob's building since heights[0] < heights[7].
In the second query, Alice and Bob can move to building 6 since heights[3] < heights[6] and heights[5] < heights[6].
In the third query, Alice cannot meet Bob since Bob cannot move to any other building.
In the fourth query, Alice and Bob can move to building 4 since heights[3] < heights[4] and heights[0] < heights[4].
In the fifth query, Alice can directly move to Bob's building since heights[1] < heights[6].
For ans[i] != -1, It can be shown that ans[i] is the leftmost building where Alice and Bob can meet.
For ans[i] == -1, It can be shown that there is no building where Alice and Bob can meet.

 Constraints:

  • 1 <= heights.length <= 5 * 104
  • 1 <= heights[i] <= 109
  • 1 <= queries.length <= 5 * 104
  • queries[i] = [ai, bi]
  • 0 <= ai, bi <= heights.length - 1

Solution 1: Binary Indexed Tree

C++

  • class BinaryIndexedTree {
    private:
        int inf = 1 << 30;
        int n;
        vector<int> c;
    
    public:
        BinaryIndexedTree(int n) {
            this->n = n;
            c.resize(n + 1, inf);
        }
    
        void update(int x, int v) {
            while (x <= n) {
                c[x] = min(c[x], v);
                x += x & -x;
            }
        }
    
        int query(int x) {
            int mi = inf;
            while (x > 0) {
                mi = min(mi, c[x]);
                x -= x & -x;
            }
            return mi == inf ? -1 : mi;
        }
    };
    
    class Solution {
    public:
        vector<int> leftmostBuildingQueries(vector<int>& heights, vector<vector<int>>& queries) {
            int n = heights.size(), m = queries.size();
            for (auto& q : queries) {
                if (q[0] > q[1]) {
                    swap(q[0], q[1]);
                }
            }
            vector<int> idx(m);
            iota(idx.begin(), idx.end(), 0);
            sort(idx.begin(), idx.end(), [&](int i, int j) {
                return queries[j][1] < queries[i][1];
            });
            vector<int> s = heights;
            sort(s.begin(), s.end());
            s.erase(unique(s.begin(), s.end()), s.end());
            vector<int> ans(m);
            int j = n - 1;
            BinaryIndexedTree tree(n);
            for (int i : idx) {
                int l = queries[i][0], r = queries[i][1];
                while (j > r) {
                    int k = s.end() - lower_bound(s.begin(), s.end(), heights[j]) + 1;
                    tree.update(k, j);
                    --j;
                }
                if (l == r || heights[l] < heights[r]) {
                    ans[i] = r;
                } else {
                    int k = s.end() - lower_bound(s.begin(), s.end(), heights[l]);
                    ans[i] = tree.query(k);
                }
            }
            return ans;
        }
    };

JAVA

  • class BinaryIndexedTree {
        private final int inf = 1 << 30;
        private int n;
        private int[] c;
    
        public BinaryIndexedTree(int n) {
            this.n = n;
            c = new int[n + 1];
            Arrays.fill(c, inf);
        }
    
        public void update(int x, int v) {
            while (x <= n) {
                c[x] = Math.min(c[x], v);
                x += x & -x;
            }
        }
    
        public int query(int x) {
            int mi = inf;
            while (x > 0) {
                mi = Math.min(mi, c[x]);
                x -= x & -x;
            }
            return mi == inf ? -1 : mi;
        }
    }
    
    class Solution {
        public int[] leftmostBuildingQueries(int[] heights, int[][] queries) {
            int n = heights.length;
            int m = queries.length;
            for (int i = 0; i < m; ++i) {
                if (queries[i][0] > queries[i][1]) {
                    queries[i] = new int[] {queries[i][1], queries[i][0]};
                }
            }
            Integer[] idx = new Integer[m];
            for (int i = 0; i < m; ++i) {
                idx[i] = i;
            }
            Arrays.sort(idx, (i, j) -> queries[j][1] - queries[i][1]);
            int[] s = heights.clone();
            Arrays.sort(s);
            int[] ans = new int[m];
            int j = n - 1;
            BinaryIndexedTree tree = new BinaryIndexedTree(n);
            for (int i : idx) {
                int l = queries[i][0], r = queries[i][1];
                while (j > r) {
                    int k = n - Arrays.binarySearch(s, heights[j]) + 1;
                    tree.update(k, j);
                    --j;
                }
                if (l == r || heights[l] < heights[r]) {
                    ans[i] = r;
                } else {
                    int k = n - Arrays.binarySearch(s, heights[l]);
                    ans[i] = tree.query(k);
                }
            }
            return ans;
        }
    }

PYTHON

  • class BinaryIndexedTree {
    private:
        int inf = 1 << 30;
        int n;
        vector<int> c;
    
    public:
        BinaryIndexedTree(int n) {
            this->n = n;
            c.resize(n + 1, inf);
        }
    
        void update(int x, int v) {
            while (x <= n) {
                c[x] = min(c[x], v);
                x += x & -x;
            }
        }
    
        int query(int x) {
            int mi = inf;
            while (x > 0) {
                mi = min(mi, c[x]);
                x -= x & -x;
            }
            return mi == inf ? -1 : mi;
        }
    };
    
    class Solution {
    public:
        vector<int> leftmostBuildingQueries(vector<int>& heights, vector<vector<int>>& queries) {
            int n = heights.size(), m = queries.size();
            for (auto& q : queries) {
                if (q[0] > q[1]) swap(q[0], q[1]);
            }
            vector<int> idx(m);
            iota(idx.begin(), idx.end(), 0);
            sort(idx.begin(), idx.end(), [&](int i, int j) {
                return queries[j][1] < queries[i][1];
            });
            vector<int> s = heights;
            sort(s.begin(), s.end());
            s.erase(unique(s.begin(), s.end()), s.end());
            vector<int> ans(m);
            int j = n - 1;
            BinaryIndexedTree tree(n);
            for (int i : idx) {
                int l = queries[i][0], r = queries[i][1];
                while (j > r) {
                    int k = s.end() - lower_bound(s.begin(), s.end(), heights[j]) + 1;
                    tree.update(k, j);
                    --j;
                }
                if (l == r || heights[l] < heights[r]) {
                    ans[i] = r;
                } else {
                    int k = s.end() - lower_bound(s.begin(), s.end(), heights[l]);
                    ans[i] = tree.query(k);
                }
            }
            return ans;
        }
    };

Comments