📌  相关文章
📜  在数组中查找第K个最小元素以进行多个查询

📅  最后修改于: 2021-05-17 03:24:55             🧑  作者: Mango

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

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

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

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

例子:

幼稚的方法:针对此问题的幼稚的方法是在数组中添加元素,并为每种第一种查询类型对数组进行排序。并且,无论何时发生第二种查询,都将在排序数组中打印第K个元素。

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

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

  • order_of_key()是有序集的内置函数,它是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是数组的大小。