Open In App

Queries for count of elements not present in range

Last Updated : 29 Jan, 2024
Improve
Improve
Like Article
Like
Save
Share
Report

Given an integer N which represents the total number of IDs present, a 2D array arr of size Mx2, where arr[i] = [ID, score] and 1D array query of size Q. We can assign multiple scores to a single ID. For each query q[i] where 0 <= i < Q, find the number of IDs who don’t have any scores within the range (query[i]/2, query[i]) where 0 <= i < Q.

Examples:

Input: N = 3, M = 4, arr[][] = [[1, 4], [2, 1], [1, 1], [3, 2]], query[] = [4, 2], Q =2
Output: [1, 0]
Explanation:

  • For the first query, its value is 4, so we have to find the number of IDs whose scores do not lie between [4/2, 4]. Seeing in arr[][], ID 1 and 3 have scores lying between range but score of ID 2 doesn’t. Therefore for first query, the answer is 1.
  • For the second query, its value is 2, so we have to find the number of IDs whose scores do not lie between [ 2/2, 2]. Seeing in arr[][] all IDs have scores lying between the range. Therefore for the second query, the answer is 0.

Input: N=2, M=4, arr[][] = [[2, 1], [1, 2], [1, 5], [2, 4]], query[] = [6, 10], Q = 2
Output: [0, 1]
Explanation:

  • For the first query, its value is 6, so we need to find the number of IDs whose scores do not lie between [6/2, 6]. Seeing in arr[][], all IDs have scores lying between the range. Therefore for the first query, answer is 0.
  • For the second query, its value is 10, so we need to find the number of IDs whose scores do not lie between [10/2, 10]. Seeing in arr[][], ID 1 has scores lying between the range but scores of ID 2 doesn’t. Therefore, for the second query, the answer is 1.

Approach: This can be solved with the following idea:

This can be solved by using a map as frequency array and two pointers algorithm. Instead of solving the queries in order of the input we can sort the queries and solve using two pointers. Sort the query and arr. For each query we try to maintain 2 pointers (start and end) which will maintain a window of only those scores (with IDs) which lie inside the query range. To get the answer of a query, we simply subtract the total number of IDs present (N) – IDs having values within the query range.

Below are the steps involved in the implementation of the code:

  • Sort the 2-D array arr according to their scores in ascending order.
  • Sort the array query in ascending order.
  • Initialize a map freq which will help us to find frequency of element IDs lying in a range.
  • Start Iterating through query array.
  • For each query[i], we have to see how many IDs are present in the range.
  • First, keep incrementing the frequency of IDs in freq by seeing their scores until query[i] maximum range is reached.
  • Now keep decreasing the frequency of IDs in freq by seeing their scores until query[i] minimum range is reached. If for any ID, the frequency becomes 0, then delete it from freq map.
  • Now for query[i], ans would be n – freq.size().
  • Same for rest of the query elements.

Below is the implementation of the following code:

C++




// C++ Implementation
#include <bits/stdc++.h>
using namespace std;
 
// Function to count number of elements
// not in specified range
void count(int n, vector<vector<int> >& arr,
           vector<int>& query)
{
    // vector to store the score with their IDs
    vector<pair<int, int> > vp;
    for (int i = 0; i < arr.size(); i++) {
        vp.push_back({ arr[i][1], arr[i][0] });
    }
    // vector to store the order of input queries
    vector<pair<int, int> > vq;
    int q = query.size();
    for (int i = 0; i < q; i++) {
        vq.push_back({ query[i], i });
    }
    sort(vp.begin(), vp.end());
    sort(vq.begin(), vq.end());
 
    // map to store the frequency of IDs
    map<int, int> freq;
    vector<int> ans(q);
    int l = 0, r = 0;
    for (int i = 0; i < q; i++) {
        int query_number = vq[i].second;
        int start = vq[i].first / 2;
        int end = vq[i].first;
 
        while (r < vp.size() && vp[r].first <= end) {
            freq[vp[r].second]++;
            r++;
        }
 
        while (l < vp.size() && vp[l].first < start) {
            freq[vp[l].second]--;
            if (freq[vp[l].second] == 0)
                freq.erase(vp[l].second);
            l++;
        }
        ans[query_number] = n - freq.size();
    }
 
    for (int i = 0; i < q; i++)
        cout << ans[i] << " ";
    cout << "\n";
}
 
// Driver code
int main()
{
    int N = 3;
 
    vector<vector<int> > arr
        = { { 1, 4 }, { 2, 1 }, { 1, 1 }, { 3, 2 } };
 
    vector<int> query = { 4, 2 };
 
    // Function call
    count(N, arr, query);
 
    return 0;
}


Java




// Java Implementation
import java.util.*;
 
public class Main {
    // Function to count number of elements not in specified range
    public static void count(int n, List<List<Integer>> arr, List<Integer> query) {
        // ArrayList to store the score with their IDs
        List<Pair<Integer, Integer>> vp = new ArrayList<>();
        for (List<Integer> list : arr) {
            vp.add(new Pair<>(list.get(1), list.get(0)));
        }
 
        // ArrayList to store the order of input queries
        List<Pair<Integer, Integer>> vq = new ArrayList<>();
        int q = query.size();
        for (int i = 0; i < q; i++) {
            vq.add(new Pair<>(query.get(i), i));
        }
 
        // Sort both ArrayLists based on the first element
        Collections.sort(vp, Comparator.comparingInt(o -> o.getKey()));
        Collections.sort(vq, Comparator.comparingInt(Pair::getKey));
 
        // HashMap to store the frequency of IDs
        Map<Integer, Integer> freq = new HashMap<>();
        int[] ans = new int[q];
        int l = 0, r = 0;
        for (int i = 0; i < q; i++) {
            int queryNumber = vq.get(i).getValue();
            int start = vq.get(i).getKey() / 2;
            int end = vq.get(i).getKey();
 
            while (r < vp.size() && vp.get(r).getKey() <= end) {
                freq.put(vp.get(r).getValue(), freq.getOrDefault(vp.get(r).getValue(), 0) + 1);
                r++;
            }
 
            while (l < vp.size() && vp.get(l).getKey() < start) {
                freq.put(vp.get(l).getValue(), freq.get(vp.get(l).getValue()) - 1);
                if (freq.get(vp.get(l).getValue()) == 0) {
                    freq.remove(vp.get(l).getValue());
                }
                l++;
            }
            ans[queryNumber] = n - freq.size();
        }
 
        // Print the result
        for (int i = 0; i < q; i++) {
            System.out.print(ans[i] + " ");
        }
        System.out.println();
    }
 
    public static void main(String[] args) {
        int N = 3;
 
        List<List<Integer>> arr = Arrays.asList(
            Arrays.asList(1, 4),
            Arrays.asList(2, 1),
            Arrays.asList(1, 1),
            Arrays.asList(3, 2)
        );
 
        List<Integer> query = Arrays.asList(4, 2);
 
        // Function call
        count(N, arr, query);
    }
 
    // Helper class to store pairs
    static class Pair<K, V> {
        private final K key;
        private final V value;
 
        public Pair(K key, V value) {
            this.key = key;
            this.value = value;
        }
 
        public K getKey() {
            return key;
        }
 
        public V getValue() {
            return value;
        }
    }
}
// This code is contributed by Tapesh(tapeshdua420)


Python3




from collections import defaultdict
 
# Function to count number of elements not in specified range
def count(n, arr, query):
    # List to store the score with their IDs
    vp = [(arr[i][1], arr[i][0]) for i in range(len(arr))]
     
    # List to store the order of input queries
    vq = [(query[i], i) for i in range(len(query))]
     
    vp.sort()
    vq.sort()
 
    # Dictionary to store the frequency of IDs
    freq = defaultdict(int)
    ans = [0] * len(query)
    l = 0
    r = 0
     
    for i in range(len(query)):
        query_number = vq[i][1]
        start = vq[i][0] // 2
        end = vq[i][0]
 
        while r < len(vp) and vp[r][0] <= end:
            freq[vp[r][1]] += 1
            r += 1
 
        while l < len(vp) and vp[l][0] < start:
            freq[vp[l][1]] -= 1
            if freq[vp[l][1]] == 0:
                del freq[vp[l][1]]
            l += 1
 
        ans[query_number] = n - len(freq)
 
    for i in range(len(query)):
        print(ans[i], end=" ")
 
# Driver code
if __name__ == "__main__":
    N = 3
 
    arr = [[1, 4], [2, 1], [1, 1], [3, 2]]
 
    query = [4, 2]
 
    # Function call
    count(N, arr, query)


C#




// C# program for the above approach
using System;
using System.Collections.Generic;
using System.Linq;
 
public class GFG {
    // Function to count the number of elements
    // not in the specified range
    static void Count(int n, List<List<int> > arr,
                      List<int> query)
    {
        // List to store the score with their IDs
        List<Tuple<int, int> > vp
            = new List<Tuple<int, int> >();
        for (int i = 0; i < arr.Count; i++) {
            vp.Add(
                new Tuple<int, int>(arr[i][1], arr[i][0]));
        }
 
        // List to store the order of input queries
        List<Tuple<int, int> > vq
            = new List<Tuple<int, int> >();
        int q = query.Count;
        for (int i = 0; i < q; i++) {
            vq.Add(new Tuple<int, int>(query[i], i));
        }
 
        vp.Sort();
        vq.Sort();
 
        // Dictionary to store the frequency of IDs
        Dictionary<int, int> freq
            = new Dictionary<int, int>();
        List<int> ans = new List<int>(new int[q]);
 
        int l = 0, r = 0;
 
        for (int i = 0; i < q; i++) {
            int queryNumber = vq[i].Item2;
            int start = vq[i].Item1 / 2;
            int end = vq[i].Item1;
 
            while (r < vp.Count && vp[r].Item1 <= end) {
                if (!freq.ContainsKey(vp[r].Item2)) {
                    freq[vp[r].Item2] = 0;
                }
                freq[vp[r].Item2]++;
                r++;
            }
 
            while (l < vp.Count && vp[l].Item1 < start) {
                freq[vp[l].Item2]--;
                if (freq[vp[l].Item2] == 0) {
                    freq.Remove(vp[l].Item2);
                }
                l++;
            }
 
            ans[queryNumber] = n - freq.Count;
        }
 
        Console.WriteLine(string.Join(" ", ans));
    }
 
    // Driver code
    static void Main()
    {
        int N = 3;
 
        List<List<int> > arr = new List<List<int> >{
            new List<int>{ 1, 4 }, new List<int>{ 2, 1 },
            new List<int>{ 1, 1 }, new List<int>{ 3, 2 }
        };
 
        List<int> query = new List<int>{ 4, 2 };
 
        // Function call
        Count(N, arr, query);
    }
}
 
// This code is contributed by Susobhan Akhuli


Javascript




// JavaScript program for the above approach
 
// Function to count number of elements
// not in the specified range
function count(n, arr, query) {
    // Array to store the score with their IDs
    let vp = [];
    for (let i = 0; i < arr.length; i++) {
        vp.push([arr[i][1], arr[i][0]]);
    }
 
    // Array to store the order of input queries
    let vq = [];
    let q = query.length;
    for (let i = 0; i < q; i++) {
        vq.push([query[i], i]);
    }
 
    vp.sort((a, b) => a[0] - b[0]);
    vq.sort((a, b) => a[0] - b[0]);
 
    // Map to store the frequency of IDs
    let freq = new Map();
    let ans = Array(q).fill(0);
    let l = 0, r = 0;
 
    for (let i = 0; i < q; i++) {
        let queryNumber = vq[i][1];
        let start = Math.floor(vq[i][0] / 2);
        let end = vq[i][0];
 
        while (r < vp.length && vp[r][0] <= end) {
            freq.set(vp[r][1], (freq.get(vp[r][1]) || 0) + 1);
            r++;
        }
 
        while (l < vp.length && vp[l][0] < start) {
            freq.set(vp[l][1], freq.get(vp[l][1]) - 1);
            if (freq.get(vp[l][1]) === 0) {
                freq.delete(vp[l][1]);
            }
            l++;
        }
 
        ans[queryNumber] = n - freq.size;
    }
 
    console.log(ans.join(" "));
}
 
// Driver code
let N = 3;
 
let arr = [
    [1, 4],
    [2, 1],
    [1, 1],
    [3, 2]
];
 
let query = [4, 2];
 
// Function call
count(N, arr, query);
 
// This code is contributed by Susobhan Akhuli


Output

1 0 






Complexity Analysis:
Time Complexity: O(M log M + Q log Q )
Auxiliary Space: O(M + Q)
where M is the size of 2D array arr, and Q is the number of queries



Like Article
Suggest improvement
Share your thoughts in the comments

Similar Reads