Queries for greatest pair sum in the given index range using Segment Tree

Given an array arr[] containing N integers and an array Q[] representing the range [L, R], the task is to find the greatest pair sum value in the range [L, R] where 0 ≤ L ≤ R ≤ N – 1.

Examples:

Input: arr[] = {1, 3, 2, 7, 9, 11}, Q[] = {1, 4}
Output: 16
Explanation:
The greatest pair sum in range 1 to 4 is 7 + 9 = 16.

Input: arr[] = {0, 1, 2, 3, 4, 5, 6, 7}, Q[] = {5, 7}
Output: 13
Explanation:
The greatest pair sum in range 5 to 7 is 6 + 7 = 13.

Naive Approach: The naive approach for this problem is to run a loop from [L, R] and find the two greatest elements in the given range. Their sum is always the greatest pair sum in the given index range. The time complexity of this approach is O(N) for every query.



Efficient Approach: The idea is to use a Segment tree in order to perform some preprocessing and find the value for every query in logarithmic time.

Representation of the Segment tree:

  1. Leaf Nodes are the elements of the input array.
  2. Each internal node contains the greatest pair sum as well as the maximum element of all leaves under it.

An array representation of the tree is used to represent the Segment Tree. For each node at the index ‘i’, the left child is at index ((2 * i) + 1), the right child is at the index ((2 * i) + 2) and the parent is at the index ((i – 1)/2).

Construction of Segment Tree from given array:

  • We start with a segment from the given array arr[].
  • At each step, we divide the current segment into two halves(if it has not yet become a segment of length 1).
  • The above step is performed recursively again on the obtained halves of the array.
  • For every segment, we store the maximum value as well as the greatest pair sum in a segment tree node.
  • The maximum pair sum and the maximum value for every node can be found as:

    Maximum Pair Sum-> maximum( Left child’s maximum pair sum, Right child’s maximum pair sum, Left child’s maximum value + Right child’s maximum value)

    Maximum Value -> maximum(Left child’s maximum value, Right child’s maximum value )

Below is the implementation of the above approach:

filter_none

edit
close

play_arrow

link
brightness_4
code

// 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;
}

chevron_right


Output:

16

Time Complexity:

  • The time complexity for tree construction is O(N) where N is the size of the array.
  • The time complexity for each query is O(log(N)) where N is the size of the array.

Attention reader! Don’t stop learning now. Get hold of all the important DSA concepts with the DSA Self Paced Course at a student-friendly price and become industry ready.




My Personal Notes arrow_drop_up

Check out this Author's contributed articles.

If you like GeeksforGeeks and would like to contribute, you can also write an article using contribute.geeksforgeeks.org or mail your article to contribute@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.

Please Improve this article if you find anything incorrect by clicking on the "Improve Article" button below.