📌  相关文章
📜  使用细分树查询给定索引范围内的值在A到B范围内的元素

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

给定N个元素的数组arr []和两个整数AB ,任务是回答Q个查询,每个查询都有两个整数LR。对于每个查询,任务是找到子数组arr [L…R]中的元素数量,该数量在AB范围内(均包括在内)。
例子:

先决条件:段树
天真的方法:只需将数组从索引L遍历到R即可找到每个查询的答案,并且只要数组元素位于AB的范围内,就继续对计数加1 。这种方法的时间复杂度将是O(n * q)

高效的方法:
建立区隔树。
段树的表示
1.叶节点是输入数组的元素。
2.每个内部节点包含的叶子数位于其下所有叶子的AB范围内。

从给定数组构造细分树
我们从一个段arr [0开始。 。 。 n-1]。每次我们将当前段分为两半(如果尚未变成长度为1的段),然后在这两个半段上调用相同的过程,则对于每个这样的段,我们存储其中的元素数量下所有节点的范围AB。
这种方法的时间复杂度为O(q * log(n))

下面是上述方法的实现:

C++
// C++ implementation of the approach
#include 
using namespace std;
  
// Procedure to build the segment tree
void buildTree(vector& tree, int* arr,
               int index, int s, int e, int A, int B)
{
  
    // Reached the leaf node
    // of the segment tree
    if (s == e) {
        if (arr[s] >= A && arr[s] <= B)
            tree[index] = 1;
        else
            tree[index] = 0;
        return;
    }
  
    // Recursively call the buildTree
    // on both the nodes of the tree
    int mid = (s + e) / 2;
    buildTree(tree, arr, 2 * index, s, mid, A, B);
    buildTree(tree, arr, 2 * index + 1, mid + 1, e, A, B);
  
    tree[index] = tree[2 * index] + tree[2 * index + 1];
}
  
// Query procedure to get the answer
// for each query l and r are query range
int query(vector tree, int index, int s,
          int e, int l, int r)
{
  
    // out of bound or no overlap
    if (r < s || l > e)
        return 0;
  
    // Complete overlap
    // Query range completely lies in
    // the segment tree node range
    if (s >= l && e <= r) {
        return tree[index];
    }
  
    // Partially overlap
    // Query range partially lies in
    // the segment tree node range
    int mid = (s + e) / 2;
    return (query(tree, 2 * index, s, mid, l, r)
            + query(tree, 2 * index + 1, mid + 1, e, l, r));
}
  
// Driver code
int main()
{
    int arr[] = { 7, 3, 9, 13, 5, 4 };
    int n = sizeof(arr) / sizeof(arr[0]);
    vector tree(4 * n + 1);
  
    int L = 1, R = 5, A = 4, B = 7;
  
    buildTree(tree, arr, 1, 0, n - 1, A, B);
  
    cout << query(tree, 1, 0, n - 1, L, R)
         << endl;
    return 0;
}


Java
// Java implementation of the approach 
class GFG{
      
// Procedure to build the segment tree 
static void buildTree(int tree[] , int arr[] , 
                      int index, int s, int e,
                      int A, int B) 
{ 
      
    // Reached the leaf node 
    // of the segment tree 
    if (s == e) 
    { 
        if (arr[s] >= A && arr[s] <= B) 
            tree[index] = 1; 
        else
            tree[index] = 0; 
              
        return; 
    } 
  
    // Recursively call the buildTree 
    // on both the nodes of the tree 
    int mid = (s + e) / 2; 
    buildTree(tree, arr, 2 * index, 
              s, mid, A, B); 
    buildTree(tree, arr, 2 * index + 1,
              mid + 1, e, A, B); 
  
    tree[index] = tree[2 * index] + 
                  tree[2 * index + 1]; 
} 
  
// Query procedure to get the answer 
// for each query l and r are query range 
static int query(int tree[], int index, int s, 
                 int e, int l, int r) 
{ 
      
    // Out of bound or no overlap 
    if (r < s || l > e) 
        return 0; 
  
    // Complete overlap 
    // Query range completely lies in 
    // the segment tree node range 
    if (s >= l && e <= r)
    { 
        return tree[index]; 
    } 
  
    // Partially overlap 
    // Query range partially lies in 
    // the segment tree node range 
    int mid = (s + e) / 2; 
    return (query(tree, 2 * index, 
                  s, mid, l, r) + 
            query(tree, 2 * index + 1, 
                  mid + 1, e, l, r)); 
} 
  
// Driver code 
public static void main (String []args)
{ 
    int arr[] = { 7, 3, 9, 13, 5, 4 }; 
    int n = arr.length;
    int tree[] = new int [(4 * n + 1)]; 
  
    int L = 1, R = 5, A = 4, B = 7; 
  
    buildTree(tree, arr, 1, 0, n - 1, A, B); 
  
    System.out.print(query(tree, 1, 0, n - 1, L, R));
} 
}
  
// This code is contributed by chitranayal


Python3
# Python3 implementation of the approach
  
# Procedure to build the segment tree
def buildTree(tree,arr,index, s, e, A, B):
  
    # Reached the leaf node
    # of the segment tree
    if (s == e):
        if (arr[s] >= A and arr[s] <= B):
            tree[index] = 1
        else:
            tree[index] = 0
        return
  
    # Recursively call the buildTree
    # on both the nodes of the tree
    mid = (s + e) // 2
    buildTree(tree, arr, 2 * index, s, mid, A, B)
    buildTree(tree, arr, 2 * index + 1, mid + 1, e, A, B)
  
    tree[index] = tree[2 * index] + tree[2 * index + 1]
  
# Query procedure to get the answer
# for each query l and r are query range
def query(tree, index, s, e, l, r):
  
    # out of bound or no overlap
    if (r < s or l > e):
        return 0
  
    # Complete overlap
    # Query range completely lies in
    # the segment tree node range
    if (s >= l and e <= r):
        return tree[index]
  
    # Partially overlap
    # Query range partially lies in
    # the segment tree node range
    mid = (s + e) // 2
    return (query(tree, 2 * index, s, mid, l, r)
            + query(tree, 2 * index + 1, mid + 1, e, l, r))
  
# Driver code
if __name__ == '__main__':
    arr=[7, 3, 9, 13, 5, 4]
    n = len(arr)
    tree=[0]*(4 * n + 1)
  
    L = 1
    R = 5
    A = 4
    B = 7
  
    buildTree(tree, arr, 1, 0, n - 1, A, B)
  
    print(query(tree, 1, 0, n - 1, L, R))
  
# This code is contributed by mohit kumar 29


C#
// C# implementation of the approach 
using System;
  
class GFG{
      
// Procedure to build the segment tree 
static void buildTree(int[] tree, int[] arr, 
                      int index, int s, int e, 
                      int A, int B) 
{ 
      
    // Reached the leaf node 
    // of the segment tree 
    if (s == e) 
    { 
        if (arr[s] >= A && arr[s] <= B) 
            tree[index] = 1; 
        else
            tree[index] = 0; 
              
        return; 
    } 
  
    // Recursively call the buildTree 
    // on both the nodes of the tree 
    int mid = (s + e) / 2; 
    buildTree(tree, arr, 2 * index, 
              s, mid, A, B); 
    buildTree(tree, arr, 2 * index + 1, 
              mid + 1, e, A, B); 
  
    tree[index] = tree[2 * index] + 
                  tree[2 * index + 1]; 
} 
  
// Query procedure to get the answer 
// for each query l and r are query range 
static int query(int[] tree, int index, int s, 
                 int e, int l, int r) 
{ 
      
    // Out of bound or no overlap 
    if (r < s || l > e) 
        return 0; 
  
    // Complete overlap 
    // Query range completely lies in 
    // the segment tree node range 
    if (s >= l && e <= r) 
    { 
        return tree[index]; 
    } 
  
    // Partially overlap 
    // Query range partially lies in 
    // the segment tree node range 
    int mid = (s + e) / 2; 
    return (query(tree, 2 * index, 
                  s, mid, l, r) + 
            query(tree, 2 * index + 1, 
                  mid + 1, e, l, r)); 
} 
  
// Driver code 
public static void Main () 
{ 
    int[] arr = new int[] { 7, 3, 9, 13, 5, 4 }; 
    int n = arr.Length; 
    int[] tree = new int [(4 * n + 1)]; 
  
    int L = 1, R = 5, A = 4, B = 7; 
  
    buildTree(tree, arr, 1, 0, n - 1, A, B); 
  
    Console.Write(query(tree, 1, 0, n - 1, L, R)); 
} 
} 
  
// This code is contributed by sanjoy_62


输出:
2