📌  相关文章
📜  为多个查询查找数组中的第 K 个最小元素

📅  最后修改于: 2021-09-06 06:31:51             🧑  作者: Mango

给定一个大小为N的数组arr[]和一个由需要在给定数组上处理的M 个查询组成的数组Q[][] 。众所周知,这些查询可以是以下两种类型:

  • 类型 1:如果 Q = 1,则在数组 {type, element_to_add} 中添加一个元素。
  • 类型 2:如果 Q = 2,则打印数组中的第 K 个最小元素。 {类型,k}

任务是执行给定的查询,以便给出以下约束:

  • 1 ≤ 查询次数 ≤ 1000000。
  • 1 ≤ N ≤ 1000000。
  • 1 ≤ arr[i] ≤ 100000000。而且,数组可以包含重复的条目。

例子:

朴素的方法:这个问题的朴素的方法是在数组中添加元素并为每个第一种类型的查询对数组进行排序。并且,每当出现第二种类型的查询时,打印排序数组中的第 K 个元素。

时间复杂度: O(M * (Nlog(N)))其中 M 是查询的数量,N 是数组的大小。

高效的方法:这个想法是使用基于策略的数据结构。对于这个问题,我们可以使用 order_of_key 数据结构来查找数组中的第 K 个最小元素。

  • order_of_key() 是 Ordered Set 的内置函数,它是 C++ 中基于策略的数据结构。基于策略的数据结构不是 C++ 标准库的一部分,但 g++ 编译器支持它们。该数据结构查找对数时间复杂度中的第 K 个最小元素。
  • 但是,此数据结构不允许重复键。为了对重复元素使用数据结构,使用了一对。
  • 我们创建一对给定的元素和索引号,将其插入到基于策略的数据结构中。
  • 首先通过比较第一个元素而不是第二个元素来对这些对进行排序。例如,(2, 1) 在 (2, 7) 之前排序。

下面是上述方法的实现:

// C++ program to find K-th
// smallest element in an array
// for multiple queries
  
#include 
using namespace std;
  
#include 
#include 
using namespace __gnu_pbds;
  
template 
  
// Defining the policy-based data
// structure
using oset
    = tree, rb_tree_tag,
           tree_order_statistics_node_update>;
  
// Function to find K-th
// smallest element in an array
// for multiple queries
void Operations(int arr[], int n,
                int query[][2], int k)
{
  
    // Declare the data structure that
    // stores the pairs
    oset > s;
  
    int j = 0;
    // Loop to insert the inital array
    // elements into the set
    for (j = 0; j < n; j++) {
        s.insert({ arr[j], j });
    }
  
    // Loop to process the queries
    for (int i = 0; i < k; i++) {
        if (query[i][0] == 1) {
  
            // Inserting the element if the
            // type of query is 1
            s.insert({ query[i][1], j });
            j++;
        }
  
        // Finding the K-th smallest element
        // if the type of the query is 2
        else if (query[i][0] == 2) {
            cout << (*s
                          .find_by_order(
                              query[i][1] - 1))
                        .first
                 << endl;
        }
    }
}
  
// Driver code
int main()
{
    int n = 8;
    int arr[] = { 2, 4, 2, 1, 5, 6, 2, 4 };
  
    int k = 4;
    // Queries. The first element denotes
    // the type of the query
    int query[4][2] = { { 1, 3 },
                        { 2, 2 },
                        { 1, 10 },
                        { 2, 7 } };
  
    Operations(arr, n, query, k);
  
    return 0;
}
输出:
2
4

时间复杂度: O(M * log(N)) ,其中 M 是查询的数量, N 是数组的大小。

如果您想与行业专家一起参加直播课程,请参阅Geeks Classes Live