Consultas de elementos mayores que K en el rango de índice dado usando Segment Tree

Dada una array arr[] de N elementos y un número de consultas donde cada consulta contendrá tres números enteros L , R y K . Para cada consulta, la tarea es encontrar el número de elementos en el subarreglo arr[L…R] que son mayores que K .

Ejemplos: 

Entrada: arr[] = {7, 3, 9, 13, 5, 4}, q[] = {{0, 3, 6}, {1, 5, 8}} 
Salida: 


Consulta 1: Solo 7 , 9 y 13 son mayores 
que 6 en el subarreglo {7, 3, 9, 13}. 
Consulta 2: solo 9 y 13 son mayores 
que 8 en el subarreglo {3, 9, 13, 5, 4}.

Entrada: arr[] = {0, 1, 2, 3, 4, 5, 6, 7}, q[] = {{0, 7, 3}, {4, 6, 10}} 
Salida: 

Requisito previo: árbol de segmentos

Enfoque ingenuo: encuentre la respuesta para cada consulta simplemente recorriendo la array desde el índice l hasta r y siga agregando 1 al conteo siempre que el elemento de la array sea mayor que k . La Complejidad de Tiempo de este enfoque será O(n * q) .

Enfoque eficiente: construya un árbol de segmentos con un vector en cada Node que contenga todos los elementos del subrango en orden ordenado. Responda cada consulta usando el árbol de segmentos donde se puede usar la búsqueda binaria para calcular cuántos números están presentes en cada Node cuyo subrango se encuentra dentro del rango de consulta que es mayor que K . La complejidad temporal de este enfoque será O(q * log(n) * log(n))

A continuación se muestra la implementación del enfoque anterior: 

C++

// C++ implementation of the approach
#include <bits/stdc++.h>
using namespace std;
 
// Merge procedure to merge two
// vectors into a single vector
vector<int> merge(vector<int>& v1, vector<int>& v2)
{
    int i = 0, j = 0;
 
    // Final vector to return
    // after merging
    vector<int> v;
 
    // Loop continues until it reaches
    // the end of one of the vectors
    while (i < v1.size() && j < v2.size()) {
        if (v1[i] <= v2[j]) {
            v.push_back(v1[i]);
            i++;
        }
        else {
            v.push_back(v2[j]);
            j++;
        }
    }
 
    // Here, simply add the remaining
    // elements to the vector v
    for (int k = i; k < v1.size(); k++)
        v.push_back(v1[k]);
    for (int k = j; k < v2.size(); k++)
        v.push_back(v2[k]);
    return v;
}
 
// Procedure to build the segment tree
void buildTree(vector<int>* tree, int* arr,
               int index, int s, int e)
{
 
    // Reached the leaf node
    // of the segment tree
    if (s == e) {
        tree[index].push_back(arr[s]);
        return;
    }
 
    // Recursively call the buildTree
    // on both the nodes of the tree
    int mid = (s + e) / 2;
    buildTree(tree, arr, 2 * index, s, mid);
    buildTree(tree, arr, 2 * index + 1, mid + 1, e);
 
    // Storing the final vector after merging
    // the two of its sorted child vector
    tree[index] = merge(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<int>* tree, int index, int s,
          int e, int l, int r, int k)
{
 
    // 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) {
        // binary search to find index of k
        return (tree[index].size()
                - (lower_bound(tree[index].begin(),
                               tree[index].end(), k)
                   - tree[index].begin()));
    }
 
    // 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, k)
            + query(tree, 2 * index + 1, mid + 1,
                    e, l, r, k));
}
 
// Function to perform the queries
void performQueries(int L[], int R[], int K[],
                    int n, int q, vector<int> tree[])
{
    for (int i = 0; i < q; i++) {
        cout << query(tree, 1, 0, n - 1,
                      L[i] - 1, R[i] - 1, K[i])
             << endl;
    }
}
 
// Driver code
int main()
{
    int arr[] = { 7, 3, 9, 13, 5, 4 };
    int n = sizeof(arr) / sizeof(arr[0]);
    vector<int> tree[4 * n + 1];
    buildTree(tree, arr, 1, 0, n - 1);
 
    // 1-based indexing
    int L[] = { 1, 2 };
    int R[] = { 4, 6 };
    int K[] = { 6, 8 };
 
    // Number of queries
    int q = sizeof(L) / sizeof(L[0]);
 
    performQueries(L, R, K, n, q, tree);
 
    return 0;
}

Java

// Java implementation of the approach
import java.util.*;
 
class GFG {
 
    // Merge procedure to merge two
    // vectors into a single vector
    static Vector<Integer> merge(Vector<Integer> v1,
                               Vector<Integer> v2)
    {
        int i = 0, j = 0;
 
        // Final vector to return
        // after merging
        Vector<Integer> v = new Vector<>();
 
        // Loop continues until it reaches
        // the end of one of the vectors
        while (i < v1.size() && j < v2.size())
        {
            if (v1.elementAt(i) <= v2.elementAt(j))
            {
                v.add(v1.elementAt(i));
                i++;
            }
            else
            {
                v.add(v2.elementAt(j));
                j++;
            }
        }
 
        // Here, simply add the remaining
        // elements to the vector v
        for (int k = i; k < v1.size(); k++)
            v.add(v1.elementAt(k));
        for (int k = j; k < v2.size(); k++)
            v.add(v2.elementAt(k));
        return v;
    }
 
    // Procedure to build the segment tree
    static void buildTree(Vector<Integer>[] tree, int[] arr,
                        int index, int s, int e)
    {
 
        // Reached the leaf node
        // of the segment tree
        if (s == e)
        {
            tree[index].add(arr[s]);
            return;
        }
 
        // Recursively call the buildTree
        // on both the nodes of the tree
        int mid = (s + e) / 2;
        buildTree(tree, arr, 2 * index, s, mid);
        buildTree(tree, arr, 2 * index + 1, mid + 1, e);
 
        // Storing the final vector after merging
        // the two of its sorted child vector
        tree[index] = merge(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(Vector<Integer>[] tree, int index, int s,
                    int e, int l, int r, int k)
    {
 
        // 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)
        {
             
            // binary search to find index of k
            return (tree[index].size() - lowerBound(tree[index],
                    tree[index].size(), k));
        }
 
        // 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, k) +
                query(tree, 2 * index + 1, mid + 1, e, l, r, k));
    }
 
    // Function to perform the queries
    static void performQueries(int L[], int R[], int K[],
                        int n, int q, Vector<Integer> tree[])
    {
        for (int i = 0; i < q; i++)
        {
            System.out.println(query(tree, 1, 0, n - 1,
                                    L[i] - 1, R[i] - 1, K[i]));
        }
    }
 
    static int lowerBound(Vector<Integer> array,
                        int length, int value)
    {
        int low = 0;
        int high = length;
        while (low < high)
        {
            final int mid = (low + high) / 2;
            if (value <= array.elementAt(mid))
            {
                high = mid;
            }
            else
            {
                low = mid + 1;
            }
        }
        return low;
    }
 
    // Driver Code
    public static void main(String[] args)
    {
        int arr[] = { 7, 3, 9, 13, 5, 4 };
        int n = arr.length;
        @SuppressWarnings("unchecked")
        Vector<Integer>[] tree = new Vector[4 * n + 1];
        for (int i = 0; i < (4 * n + 1); i++)
        {
            tree[i] = new Vector<>();
        }
 
        buildTree(tree, arr, 1, 0, n - 1);
 
        // 1-based indexing
        int L[] = { 1, 2 };
        int R[] = { 4, 6 };
        int K[] = { 6, 8 };
 
        // Number of queries
        int q = L.length;
 
        performQueries(L, R, K, n, q, tree);
    }
}
 
// This code is contributed by
// sanjeev2552

Python3

# Python3 implementation of the approach
from bisect import bisect_left as lower_bound
 
# Merge procedure to merge two
# vectors into a single vector
def merge(v1, v2):
    i = 0
    j = 0
 
    # Final vector to return
    # after merging
    v = []
 
    # Loop continues until it reaches
    # the end of one of the vectors
    while (i < len(v1) and j < len(v2)):
        if (v1[i] <= v2[j]):
            v.append(v1[i])
            i += 1
        else:
            v.append(v2[j])
            j += 1
 
    # Here, simply add the remaining
    # elements to the vector v
    for k in range(i, len(v1)):
        v.append(v1[k])
    for k in range(j, len(v2)):
        v.append(v2[k])
    return v
 
# Procedure to build the segment tree
def buildTree(tree,arr,index, s, e):
 
    # Reached the leaf node
    # of the segment tree
    if (s == e):
        tree[index].append(arr[s])
        return
 
    # Recursively call the buildTree
    # on both the nodes of the tree
    mid = (s + e) // 2
    buildTree(tree, arr, 2 * index, s, mid)
    buildTree(tree, arr, 2 * index + 1, mid + 1, e)
 
    # Storing the final vector after merging
    # the two of its sorted child vector
    tree[index] = merge(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, k):
 
    # 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):
         
        # binary search to find index of k
        return len(tree[index]) - (lower_bound(tree[index], k))
 
    # 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, k)
            + query(tree, 2 * index + 1, mid + 1,e, l, r, k))
 
# Function to perform the queries
def performQueries(L, R, K,n, q,tree):
    for i in range(q):
        print(query(tree, 1, 0, n - 1,L[i] - 1, R[i] - 1, K[i]))
 
# Driver code
if __name__ == '__main__':
    arr = [7, 3, 9, 13, 5, 4]
    n = len(arr)
    tree = [[] for i in range(4 * n + 1)]
    buildTree(tree, arr, 1, 0, n - 1)
 
    # 1-based indexing
    L = [1, 2]
    R = [4, 6]
    K = [6, 8]
 
    # Number of queries
    q = len(L)
 
     performQueries(L, R, K, n, q, tree)
      
# This code is contributed by mohit kumar 29        

C#

// C# implementation of the approach
using System;
using System.Collections.Generic;
 
class GFG {
  
    // Merge procedure to merge two
    // vectors into a single vector
    static List<int> merge(List<int> v1,
                               List<int> v2)
    {
        int i = 0, j = 0;
  
        // Final vector to return
        // after merging
        List<int> v = new List<int>();
  
        // Loop continues until it reaches
        // the end of one of the vectors
        while (i < v1.Count && j < v2.Count)
        {
            if (v1[i] <= v2[j])
            {
                v.Add(v1[i]);
                i++;
            }
            else
            {
                v.Add(v2[j]);
                j++;
            }
        }
  
        // Here, simply add the remaining
        // elements to the vector v
        for (int k = i; k < v1.Count; k++)
            v.Add(v1[k]);
        for (int k = j; k < v2.Count; k++)
            v.Add(v2[k]);
        return v;
    }
  
    // Procedure to build the segment tree
    static void buildTree(List<int>[] tree, int[] arr,
                        int index, int s, int e)
    {
  
        // Reached the leaf node
        // of the segment tree
        if (s == e)
        {
            tree[index].Add(arr[s]);
            return;
        }
  
        // Recursively call the buildTree
        // on both the nodes of the tree
        int mid = (s + e) / 2;
        buildTree(tree, arr, 2 * index, s, mid);
        buildTree(tree, arr, 2 * index + 1, mid + 1, e);
  
        // Storing the readonly vector after merging
        // the two of its sorted child vector
        tree[index] = merge(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(List<int>[] tree, int index, int s,
                    int e, int l, int r, int k)
    {
  
        // 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)
        {
              
            // binary search to find index of k
            return (tree[index].Count - lowerBound(tree[index],
                    tree[index].Count, k));
        }
  
        // 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, k) +
                query(tree, 2 * index + 1, mid + 1, e, l, r, k));
    }
  
    // Function to perform the queries
    static void performQueries(int []L, int []R, int []K,
                        int n, int q, List<int> []tree)
    {
        for (int i = 0; i < q; i++)
        {
            Console.WriteLine(query(tree, 1, 0, n - 1,
                                    L[i] - 1, R[i] - 1, K[i]));
        }
    }
  
    static int lowerBound(List<int> array,
                        int length, int value)
    {
        int low = 0;
        int high = length;
        while (low < high)
        {
            int mid = (low + high) / 2;
            if (value <= array[mid])
            {
                high = mid;
            }
            else
            {
                low = mid + 1;
            }
        }
        return low;
    }
  
    // Driver Code
    public static void Main(String[] args)
    {
        int []arr = { 7, 3, 9, 13, 5, 4 };
        int n = arr.Length;
        List<int>[] tree = new List<int>[4 * n + 1];
        for (int i = 0; i < (4 * n + 1); i++)
        {
            tree[i] = new List<int>();
        }
  
        buildTree(tree, arr, 1, 0, n - 1);
  
        // 1-based indexing
        int []L = { 1, 2 };
        int []R = { 4, 6 };
        int []K = { 6, 8 };
  
        // Number of queries
        int q = L.Length;
  
        performQueries(L, R, K, n, q, tree);
    }
}
 
// This code is contributed by PrinciRaj1992

Javascript

<script>
 
// JavaScript implementation of the approach
 
 
// Merge procedure to merge two
// vectors into a single vector
function merge(v1, v2) {
    let i = 0, j = 0;
 
    // Final vector to return
    // after merging
    let v = new Array();
 
    // Loop continues until it reaches
    // the end of one of the vectors
    while (i < v1.length && j < v2.length) {
        if (v1[i] <= v2[j]) {
            v.push(v1[i]);
            i++;
        }
        else {
            v.push(v2[j]);
            j++;
        }
    }
 
    // Here, simply add the remaining
    // elements to the vector v
    for (let k = i; k < v1.length; k++)
        v.push(v1[k]);
    for (let k = j; k < v2.length; k++)
        v.push(v2[k]);
    return v;
}
 
// Procedure to build the segment tree
function buildTree(tree, arr, index, s, e) {
 
    // Reached the leaf node
    // of the segment tree
    if (s == e) {
        tree[index].push(arr[s]);
        return;
    }
 
    // Recursively call the buildTree
    // on both the nodes of the tree
    let mid = Math.floor((s + e) / 2);
    buildTree(tree, arr, 2 * index, s, mid);
    buildTree(tree, arr, 2 * index + 1, mid + 1, e);
 
    // Storing the final vector after merging
    // the two of its sorted child vector
    tree[index] = merge(tree[2 * index], tree[2 * index + 1]);
}
 
// Query procedure to get the answer
// for each query l and r are query range
function query(tree, index, s, e, l, r, k) {
 
    // 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) {
        // binary search to find index of k
        return (tree[index].length
            - (lowerBound(tree[index], tree[index].length, k)));
    }
 
    // Partially overlap
    // Query range partially lies in
    // the segment tree node range
    let mid = Math.floor((s + e) / 2);
    return (query(tree, 2 * index, s,
        mid, l, r, k)
        + query(tree, 2 * index + 1, mid + 1,
            e, l, r, k));
}
 
function lowerBound(array, length, value) {
    let low = 0;
    let high = length;
    while (low < high) {
        let mid = Math.floor((low + high) / 2);
        if (value <= array[mid]) {
            high = mid;
        }
        else {
            low = mid + 1;
        }
    }
    return low;
}
 
// Function to perform the queries
function performQueries(L, R, K, n, q, tree) {
    for (let i = 0; i < q; i++) {
        document.write(
        query(tree, 1, 0, n - 1, L[i] - 1, R[i] - 1, K[i]) +
        "<br>"
        );
    }
}
 
// Driver code
 
let arr = [7, 3, 9, 13, 5, 4];
let n = arr.length;
let tree = new Array();
 
for (let i = 0; i < 4 * n + 1; i++) {
    tree.push([])
}
buildTree(tree, arr, 1, 0, n - 1);
 
// 1-based indexing
let L = [1, 2];
let R = [4, 6];
let K = [6, 8];
 
// Number of queries
let q = L.length;
 
performQueries(L, R, K, n, q, tree);
 
</script>
Producción: 

3
2

 

Otro enfoque:

Otra forma de hacerlo utilizando árboles de segmentos es almacenando el primer elemento mayor que en cada Node (si está presente) en ese rango, de lo contrario almacenando 0 .

Aquí, necesitamos considerar 3 casos para construir el árbol.

  1. Si tanto el hijo izquierdo como el derecho contienen un número distinto de 0, la respuesta siempre es el hijo izquierdo. (necesitamos considerar la primera aparición del número mayor que K .)
  2. Si cualquiera de los hijos izquierdo o derecho contiene 0 , la respuesta siempre es un número distinto de 0 .
  3. Si tanto el hijo izquierdo como el derecho contienen 0 , la respuesta siempre es 0 (lo que indica que ningún número mayor que K está presente en ese rango).

La función de consulta sigue siendo la misma de siempre.

Considere el siguiente ejemplo:   arr[] = {7, 3, 9, 13, 5, 4} , K = 6

El árbol en este caso se verá así:

  A continuación se muestra la implementación del enfoque anterior:

C++

// C++ implementation of the approach
#include <bits/stdc++.h>
using namespace std;
 
vector<int> arr(1000000), tree(4 * arr.size());
 
// combine function to make parent node
int combine(int a, int b)
{
    if (a != 0 && b != 0) {
        return a;
    }
    if (a >= b) {
        return a;
    }
    return b;
}
 
// building the tree
void buildTree(int ind, int low, int high, int x)
{
    // leaf node
    if (low == high) {
        if (arr[low] > x) {
            tree[ind] = arr[low];
        }
        else {
            tree[ind] = 0;
        }
        return;
    }
    int mid = (low + high) / 2;
    buildTree(2 * ind + 1, low, mid, x);
    buildTree(2 * ind + 2, mid + 1, high, x);
 
    // merging the nodes while backtracking.
    tree[ind]
        = combine(tree[2 * ind + 1], tree[2 * ind + 2]);
}
// performing query
int query(int ind, int low, int high, int l, int r)
{
    int mid = (low + high) / 2;
    // Out of Bounds
    if (low > r || high < l) {
        return 0;
    }
    // completely overlaps
    if (l <= low && r >= high) {
        return tree[ind];
    }
    // partially overlaps
    return combine(query(2 * ind + 1, low, mid, l, r),
                   query(2 * ind + 2, mid + 1, high, l, r));
}
 
// Driver Code
int main()
{
    arr = { 7, 3, 9, 13, 5, 4 };
    int n = 6;
    int k = 6;
 
    // 1-based indexing
    int l = 1, r = 4;
    buildTree(0, 0, n - 1, k);
    cout << query(0, 0, n - 1, l - 1, r - 1);
    return 0;
}
// This code is contributed by yashbeersingh42

Java

// Java implementation of the approach
public class GFG {
    int[] arr, tree;
 
    // combine function to make parent node
    int combine(int a, int b)
    {
        if (a != 0 && b != 0) {
            return a;
        }
        if (a >= b) {
            return a;
        }
        return b;
    }
 
    // building the tree
    void buildTree(int ind, int low, int high, int x)
    {
        // leaf node
        if (low == high) {
            if (arr[low] > x) {
                tree[ind] = arr[low];
            }
            else {
                tree[ind] = 0;
            }
            return;
        }
 
        int mid = (high - low) / 2 + low;
        buildTree(2 * ind + 1, low, mid, x);
        buildTree(2 * ind + 2, mid + 1, high, x);
 
        // merging the nodes while backtracking
        tree[ind]
            = combine(tree[2 * ind + 1], tree[2 * ind + 2]);
    }
 
    // performing query
    int query(int ind, int low, int high, int l, int r)
    {
        int mid = (high - low) / 2 + low;
       
        // Out of Bounds
        if (low > r || high < l) {
            return 0;
        }
       
        // completely overlaps
        if (l <= low && r >= high) {
            return tree[ind];
        }
       
        // partially overlaps
        return combine(
            query(2 * ind + 1, low, mid, l, r),
            query(2 * ind + 2, mid + 1, high, l, r));
    }
 
    // Driver Code
    public static void main(String args[])
    {
        GFG ob = new GFG();
 
        ob.arr = new int[] { 7, 3, 9, 13, 5, 4 };
        int n = ob.arr.length;
        int k = 6;
        ob.tree = new int[4 * n];
 
        // 1-based indexing
        int l = 1, r = 4;
        ob.buildTree(0, 0, n - 1, k);
        System.out.println(
            ob.query(0, 0, n - 1, l - 1, r - 1));
    }
}
 
// This code is contributed by sarvjot.

Python3

# Python implementation of the approach
import math
 
# combine function to make parent node
def combine(a, b):
    if a != 0 and b != 0:
        return a
    if a >= b:
        return a
    return b
 
# building the tree
def build_tree(arr, tree, ind, low, high, x):
   
    # leaf node
    if low == high:
        if arr[low] > x:
            tree[ind] = arr[low]
        else:
            tree[ind] = 0
        return
 
    mid = (high - low) / 2 + low
    mid = math.floor(mid)
    mid = int(mid)
    build_tree(arr, tree, 2 * ind + 1, low, mid, x)
    build_tree(arr, tree, 2 * ind + 2, mid + 1, high, x)
 
    # merging the nodes while backtracking
    tree[ind] = combine(tree[2 * ind + 1], tree[2 * ind + 2])
 
# performing query
def query(tree, ind, low, high, l, r):
    mid = (high - low) / 2 + low
    mid = math.floor(mid)
    mid = int(mid)
 
    # out of bounds
    if low > r or high < l:
        return 0
 
    # complete overlaps
    if l <= low and r >= high:
        return tree[ind]
 
    # partial overlaps
    q1 = query(tree, 2 * ind + 1, low, mid, l, r)
    q2 = query(tree, 2 * ind + 2, mid + 1, high, l, r)
 
    return combine(q1, q2)
 
# Driver Code
if __name__ == '__main__':
    arr = [7, 3, 9, 13, 5, 4]
    n = len(arr)
    k = 6
    tree = [[] for i in range(4 * n)]
 
    # 1-based indexing
    l = 1
    r = 4
 
    build_tree(arr, tree, 0, 0, n - 1, k)
    print(query(tree, 0, 0, n - 1, l - 1, r - 1))
 
    # This code is contributed by sarvjot.

C#

// C# implementation of the approach
using System;
class GFG {
     
    static int[] arr, tree;
  
    // combine function to make parent node
    static int combine(int a, int b)
    {
        if (a != 0 && b != 0) {
            return a;
        }
        if (a >= b) {
            return a;
        }
        return b;
    }
  
    // building the tree
    static void buildTree(int ind, int low, int high, int x)
    {
        // leaf node
        if (low == high) {
            if (arr[low] > x) {
                tree[ind] = arr[low];
            }
            else {
                tree[ind] = 0;
            }
            return;
        }
  
        int mid = (high - low) / 2 + low;
        buildTree(2 * ind + 1, low, mid, x);
        buildTree(2 * ind + 2, mid + 1, high, x);
  
        // merging the nodes while backtracking
        tree[ind]
            = combine(tree[2 * ind + 1], tree[2 * ind + 2]);
    }
  
    // performing query
    static int query(int ind, int low, int high, int l, int r)
    {
        int mid = (high - low) / 2 + low;
        
        // Out of Bounds
        if (low > r || high < l) {
            return 0;
        }
        
        // completely overlaps
        if (l <= low && r >= high) {
            return tree[ind];
        }
        
        // partially overlaps
        return combine(
            query(2 * ind + 1, low, mid, l, r),
            query(2 * ind + 2, mid + 1, high, l, r));
    }
     
  static void Main() {
    arr = new int[] { 7, 3, 9, 13, 5, 4 };
    int n = arr.Length;
    int k = 6;
    tree = new int[4 * n];
 
    // 1-based indexing
    int l = 1, r = 4;
    buildTree(0, 0, n - 1, k);
    Console.Write(query(0, 0, n - 1, l - 1, r - 1));
  }
}
 
// This code is contributed by suresh07.

Javascript

<script>
    // Javascript implementation of the approach
     
    let arr, tree;
   
    // combine function to make parent node
    function combine(a, b)
    {
        if (a != 0 && b != 0) {
            return a;
        }
        if (a >= b) {
            return a;
        }
        return b;
    }
   
    // building the tree
    function buildTree(ind, low, high, x)
    {
        // leaf node
        if (low == high) {
            if (arr[low] > x) {
                tree[ind] = arr[low];
            }
            else {
                tree[ind] = 0;
            }
            return;
        }
   
        let mid = parseInt((high - low) / 2, 10) + low;
        buildTree(2 * ind + 1, low, mid, x);
        buildTree(2 * ind + 2, mid + 1, high, x);
   
        // merging the nodes while backtracking
        tree[ind]
            = combine(tree[2 * ind + 1], tree[2 * ind + 2]);
    }
   
    // performing query
    function query(ind, low, high, l, r)
    {
        let mid = parseInt((high - low) / 2, 10) + low;
         
        // Out of Bounds
        if (low > r || high < l) {
            return 0;
        }
         
        // completely overlaps
        if (l <= low && r >= high) {
            return tree[ind];
        }
         
        // partially overlaps
        return combine(
            query(2 * ind + 1, low, mid, l, r),
            query(2 * ind + 2, mid + 1, high, l, r));
    }
     
    arr = [ 7, 3, 9, 13, 5, 4 ];
    let n = arr.length;
    let k = 6;
    tree = new Array(4 * n);
    tree.fill(0);
  
    // 1-based indexing
    let l = 1, r = 4;
    buildTree(0, 0, n - 1, k);
    document.write(query(0, 0, n - 1, l - 1, r - 1));
     
    // This code is contributed by divyesh072019.
</script>

Producción:

7

Complejidad de tiempo: O(N * log N) para construir el árbol y O(log N) para cada consulta.

Complejidad espacial: O(N)

Publicación traducida automáticamente

Artículo escrito por VikashKumr y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *