Consultas por la mayor suma de pares en el rango de índice dado usando Segment Tree

Dada una array arr[] que contiene N enteros y una array Q[] que representa el rango [L, R] , la tarea es encontrar el mayor valor de suma de pares en el rango [L, R] donde 0 ≤ L ≤ R ≤ N – 1.

Ejemplos:

Entrada: arr[] = {1, 3, 2, 7, 9, 11}, Q[] = {1, 4}
Salida: 16
Explicación:
La mayor suma de pares en el rango de 1 a 4 es 7 + 9 = 16.

Entrada: arr[] = {0, 1, 2, 3, 4, 5, 6, 7}, Q[] = {5, 7}
Salida: 13
Explicación:
La mayor suma de pares en el rango de 5 a 7 es 6 + 7 = 13.

Enfoque ingenuo: el enfoque ingenuo para este problema es ejecutar un ciclo desde [L, R] y encontrar los dos elementos más grandes en el rango dado. Su suma es siempre la mayor suma de pares en el rango de índice dado. La complejidad temporal de este enfoque es O(N) para cada consulta.

Enfoque eficiente: la idea es utilizar un árbol de segmentos para realizar un preprocesamiento y encontrar el valor de cada consulta en tiempo logarítmico.

Representación del árbol de Segmentos:

  1. Los Nodes hoja son los elementos de la array de entrada.
  2. Cada Node interno contiene la mayor suma de pares, así como el elemento máximo de todas las hojas debajo de él.

Se utiliza una representación de array del árbol para representar el árbol de segmentos . Para cada Node en el índice ‘i’, el hijo izquierdo está en el índice ((2 * i) + 1) , el hijo derecho está en el índice ((2 * i) + 2) y el padre está en el índice ( (yo – 1)/2) .

Construcción del árbol de segmentos a partir de una array dada:

  • Comenzamos con un segmento de la array dada arr[].
  • En cada paso, dividimos el segmento actual en dos mitades (si aún no se ha convertido en un segmento de longitud 1).
  • El paso anterior se realiza recursivamente nuevamente en las mitades obtenidas de la array.
  • Para cada segmento, almacenamos el valor máximo así como la mayor suma de pares en un Node de árbol de segmentos.
  • La suma máxima de pares y el valor máximo para cada Node se pueden encontrar como:

    Suma máxima del par -> máximo (suma máxima del par del niño izquierdo, suma máxima del par del niño derecho, valor máximo del niño izquierdo + valor máximo del niño derecho)

    Valor máximo -> máximo (valor máximo del niño izquierdo, valor máximo del niño derecho)

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

// C++ program for range greatest
// pair sum query using segment tree
  
#include <bits/stdc++.h>
using namespace std;
  
// Defining the node
struct node {
    int maxVal, greatestPSum;
} st[100009];
  
// A utility function
node util(node x, node y)
{
    node ans;
  
    // Find the maximum pair sum
    ans.greatestPSum
        = max(x.maxVal + y.maxVal,
              max(x.greatestPSum,
                  y.greatestPSum));
    // Find the maximum value
    ans.maxVal = max(x.maxVal, y.maxVal);
    return ans;
}
  
// A utility function to get the
// middle index from corner indexes.
int getMid(int s, int e)
{
    return s + (e - s) / 2;
}
  
/* A recursive function to get the
greatest pair sum value in a given range 
of array indexes. Here:
  
index --> Index of current node in the 
          segment tree. Initially 0 is 
          passed as root is always at index 0 
ss & se --> Starting and ending indexes 
            of the segment represented 
            by current node, i.e., st[index] 
qs & qe --> Starting and ending indexes
            of query range */
node query(int ss, int se, int qs,
           int qe, int index)
{
    // If segment of this node is a part
    // of given range, then return
    // the min of the segment
    if (qs <= ss && qe >= se)
        return st[index];
  
    node temp;
    temp.maxVal = -1,
    temp.greatestPSum = -1;
  
    // If segment of this node
    // is outside the given range
    if (se < qs || ss > qe)
        return temp;
  
    // If a part of this segment
    // overlaps with the given range
    int mid = getMid(ss, se);
    return util(query(ss, mid, qs,
                      qe, 2 * index + 1),
  
                query(mid + 1, se, qs,
                      qe, 2 * index + 2));
}
  
// Function to return the greatest pair
// sum in the range from index
// qs (query start) to qe (query end)
node checkQuery(int n, int qs, int qe)
{
    node temp;
    temp.maxVal = -1, temp.greatestPSum = -1;
  
    // Check for erroneous input values
    if (qs < 0 || qe > n - 1 || qs > qe) {
        cout << "Invalid Input";
        return temp;
    }
  
    return query(0, n - 1, qs, qe, 0);
}
  
// A recursive function that constructs
// Segment Tree for array[ss..se].
// si is index of current node in segment tree
node constructST(int arr[], int ss,
                 int se, int si)
{
    // If there is one element in array,
    // store it in current node of
    // segment tree and return
    if (ss == se) {
        st[si].maxVal = arr[ss];
        st[si].greatestPSum = 0;
        return st[si];
    }
  
    // If there are more than one elements,
    // then recur for left and right subtrees
    int mid = getMid(ss, se);
    st[si] = util(constructST(arr, ss, mid,
                              si * 2 + 1),
  
                  constructST(arr, mid + 1, se,
                              si * 2 + 2));
    return st[si];
}
  
// Utility function to find the
// greatest pair sum for the given
// queries
void operation(int arr[], int n,
               int qs, int qe)
{
    // Build segment tree from given array
    constructST(arr, 0, n - 1, 0);
  
    node ans = checkQuery(n, qs, qe);
  
    // Print minimum value in arr[qs..qe]
    cout << ans.greatestPSum << endl;
}
  
// Driver code
int main()
{
    int arr[] = { 1, 3, 2, 7, 9, 11 };
    int n = sizeof(arr) / sizeof(arr[0]);
  
    int L = 1;
    int R = 4;
  
    operation(arr, n, L, R);
  
    return 0;
}
Producción:

16

Complejidad del tiempo:

  • La complejidad de tiempo para la construcción del árbol es O(N) donde N es el tamaño de la array.
  • La complejidad de tiempo para cada consulta es O(log(N)) donde N es el tamaño de la array.

Publicación traducida automáticamente

Artículo escrito por muskan_garg 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 *