给定N个元素的数组arr []和两个整数A到B ,任务是回答Q个查询,每个查询都有两个整数L和R。对于每个查询,任务是找到子数组arr [L…R]中的元素数量,该数量在A到B范围内(均包括在内)。
例子:
Input: arr[] = {7, 3, 9, 13, 5, 4}, A=4, B=7
query = { 1, 5 }
Output: 2
Explanation :
Only 5 and 4 lies within 4 to 7
in the subarray {3, 9, 13, 5, 4}.
Input: arr[] = {0, 1, 2, 3, 4, 5, 6, 7}, A=1, B=5
query = { 3, 5 }
Output: 3
Explanation :
All the elements 3, 4 and 5 lies within 1 to 5
in the subarray {3, 4, 5}.
先决条件:段树
天真的方法:只需将数组从索引L遍历到R即可找到每个查询的答案,并且只要数组元素位于A到B的范围内,就继续对计数加1 。这种方法的时间复杂度将是O(n * q) 。
高效的方法:
建立区隔树。
段树的表示
1.叶节点是输入数组的元素。
2.每个内部节点包含的叶子数位于其下所有叶子的A到B范围内。
从给定数组构造细分树
我们从一个段arr [0开始。 。 。 n-1]。每次我们将当前段分为两半(如果尚未变成长度为1的段),然后在这两个半段上调用相同的过程,则对于每个这样的段,我们存储其中的元素数量下所有节点的范围A到B。
这种方法的时间复杂度为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
如果您希望与行业专家一起参加现场课程,请参阅《 Geeks现场课程》和《 Geeks现场课程美国》。