Open In App

Maximize value of a pair from two given arrays based on given conditions

Last Updated : 22 Mar, 2023
Improve
Improve
Like Article
Like
Save
Share
Report

Given two arrays A[] and B[] consisting of N integers and an integer K, the task is to find the maximum value of B[i] + B[j] + abs(A[i] – A[j]) by choosing any pair (i, j) such that abs(A[i] – A[j]) ? K.

Examples:

Input: A[] = {5, 6, 9, 10}, B[] = {3, 0, 10, -10}, K = 1
Output: 4
Explanation:
Only two pairs can be chosen, i.e. (0, 1) and (2, 3), because abs(A[0] – A[1]) ? K and abs(A[2] – A[3]) ? K.
The value of (0, 1) pair is B[0] + B[1] + abs(A[0] – A[1]) = 3 + 0 + 1 = 4.
The value of (2, 3) pair is B[2] + B[3] + abs(A[2] – A[3]) = 10 + (-10) + 1 = 1.
Hence, the maximum value from all possible pairs is 4.

Input: A[] = {1, 2, 3, 4}, B[] = {0, 8, 6, 9}, K = 2
Output: 19

Naive Approach: The simplest approach is to generate all possible pairs from the given array and count those pairs that satisfy the given conditions. After checking all the pairs print the count of all pairs.

Time Complexity: O(N2)
Auxiliary Space: O(N)

Efficient Approach: To optimize the above approach, the idea is to use Segment Trees, Binary Search, and Sorting of the array according to the value of array A[]. Observe that, from the given equation it is clear that B[i] + B[j] + abs(A[i] – A[j]) equals to any of the below values: 

  • B[i] + B[j] + (A[i] – A[j])
  • B[i] + B[j] + (A[j] – A[i])

Consider 2nd equation:

B[i] + B[j] + A[j] – A[i] = B[i] – A[i] + (B[j] + A[j])

  • Here, it is observed that for each i in the array A[], finding the right most index of value smaller than of equal to A[i] + K. Let the rightmost index be right.
  • Now, calculate B[i] – A[i] + max value of B[j] + A[j] where i + 1 <= j <= right. This will give the maximum value of selected pair.
  • To calculate the maximum value each time in a range, segment trees can be used.

Follow the below steps to solve the problem:

  • Sort all values, B[i] and B[i] + A[i] according to the values of array A[].
  • Initialize maxValue as INT_MIN to store the final maximum answer and initialize a range maximum query segment tree storing all values, A[i] + B[i].
  • Traverse the array A[] and perform the following:
    • For each element find the index, say right, such that abs(A[i] – A[right]) <= K using Binary Search.
    • Then, find the maximum value, of (A[j] + B[j]) where i+1 <= j <= right.
    • Update maxValue as maxValue = max(maxValue, B[i] – A[i] + A[j] + B[j]).
  • After the above steps, print the value of maxValue as the result.

Below is the implementation of the above approach:

C++




#include <bits/stdc++.h>
using namespace std;
 
// c++ code for the above approach
// Class to store the values of a[i], b[i], a[i] + b[i]
class Triplet {
    public:
    int a, b, c;
    Triplet(int d, int e, int f) {
        a = d;
        b = e;
        c = f;
    }
};
 
// Stores the segment tree
vector<int> seg;
 
 
 
// Function to search floor of
// the current value
int search(vector<Triplet> arr,int val)
{
 
    // Initialise low and high values
    int low = 0;
    int high = arr.size() - 1;
    int ans = -1;
 
    // Perform Binary Search
    while (low <= high) {
        int mid = low + (high-low)/2;
 
        // If the current value is
        // <= val then store the
        // candidate answer and
        // find for rightmost one
        if (arr[mid].a <= val) {
            ans = mid;
            low = mid + 1;
        } else {
            high = mid - 1;
        }
    }
    return ans;
}
 
// Function to build segment tree
void build(vector<Triplet> arr,int index,int s,int e)
{
 
    // Base Case
    if (s == e) {
        seg[index] = arr[s].c;
        return;
    }
    int mid = s + (e - s) / 2;
 
    // Buildthe left and right
    // segment trees
    build(arr, 2 * index + 1, s, mid);
    build(arr, 2 * index + 2, mid + 1, e);
 
    // Update current index
    seg[index] = max(seg[2 * index + 1], seg[2 * index + 2]);
}
 
// Function to get maximum value
// in the range [qs, qe]
int getMax(vector<Triplet> arr,int index,int s,int e,int qs,int qe)
{
 
    // If segment is not in range
    if (qe < s || e < qs)
    {
        return INT_MIN;
    }
 
    // If segment is fully in range
    if (qs <= s && e <= qe) {
        return seg[index];
    }
 
    // If a part of this segment is
    // in range
    int mid = s + (e - s) / 2;
    int left = getMax(arr, 2 * index + 1, s, mid, qs, qe);
    int right = getMax(arr, 2 * index + 2, mid + 1, e, qs, qe);
 
    // Return the maximum value
    return max(left, right);
}
 
// Function to find the maximum
// possible value according to the
// given condition
void maxValue(vector<int> a,vector<int> b,int  n,int k)
{
 
    // Initialize triplet array
    vector<Triplet> arr;
 
    // Store the values a[i], b[i],
    // a[i] + b[i]
    for (int i = 0; i < n; i++) {
        arr.push_back(Triplet(a[i], b[i], a[i] + b[i]));
    }
 
    // Sort the array according
    // to array a[]
    sort(arr.begin(), arr.end(), [] (const Triplet &x, const Triplet &y){
        return x.a - y.a;
    });
 
    // Build segment tree
    seg.resize(4*n);
    int x = 5;
    build(arr, 0, 0, n - 1);
 
    // Initialise the maxvalue of
    // the selected pairs
    int maxvalue = INT_MIN;
 
    // Traverse the array
    for (int i = 0; i < n; i++)
    {
 
        // For each value find the
        // floor(arr[i] + k)
        int right = search(arr, arr[i].a + k);
 
        // Find the maximum value of
        // the select pairs i and max
        // from (i + 1, right)
        if (right != -1) {
            maxvalue = max(maxvalue, arr[i].b - arr[i].a + getMax(arr, 0, 0, n - 1, i + 1, right));
        }
    }
 
    // Print the maximum value
    cout << maxvalue - x;
}
 
// Driver code
int main(){
     
    vector<int> a = {5, 6, 9, 10};
    vector<int> b = {3, 0, 10, -10};
    int N = 4;
    int K = 1;
 
    maxValue(a, b, N, K);
    return 0;
}
 
// This code is contributed by Arushi Jindal.


Java




// Java program for the above approach
 
import java.util.*;
 
// Class to store the values of a[i],
// b[i], a[i] + b[i]
class triplet implements Comparable<triplet> {
 
    int a, b, c;
 
    // Constructor
    triplet(int a, int b, int c)
    {
        this.a = a;
        this.b = b;
        this.c = c;
    }
 
    // Sort values according to array
    public int compareTo(triplet o)
    {
        return this.a - o.a;
    }
}
 
class GFG {
 
    // Stores the segment tree
    static int seg[];
 
    // Function to find the maximum
    // possible value according to the
    // given condition
    public static void maxValue(
        int a[], int b[], int n, int k)
    {
        // Initialize triplet array
        triplet arr[] = new triplet[n];
 
        // Store the values a[i], b[i],
        // a[i] + b[i]
        for (int i = 0; i < n; i++) {
 
            arr[i] = new triplet(a[i], b[i],
                                 a[i] + b[i]);
        }
 
        // Sort the array according
        // to array a[]
        Arrays.sort(arr);
 
        // Build segment tree
        seg = new int[4 * n];
        build(arr, 0, 0, n - 1);
 
        // Initialise the maxvalue of
        // the selected pairs
        int maxvalue = Integer.MIN_VALUE;
 
        // Traverse the array
        for (int i = 0; i < n; i++) {
 
            // For each value find the
            // floor(arr[i] + k)
            int right = search(arr,
                               arr[i].a + k);
 
            // Find the maximum value of
            // the select pairs i and max
            // from (i + 1, right)
            if (right != -1) {
 
                maxvalue = Math.max(
                    maxvalue, arr[i].b - arr[i].a
                                  + getMax(arr, 0, 0, n - 1,
                                           i + 1, right));
            }
        }
 
        // Print the maximum value
        System.out.println(maxvalue);
    }
 
    // Function to search floor of
    // the current value
    public static int search(
        triplet arr[], int val)
    {
        // Initialise low and high values
        int low = 0, high = arr.length - 1;
        int ans = -1;
 
        // Perform Binary Search
        while (low <= high) {
            int mid = low + (high - low) / 2;
 
            // If the current value is
            // <= val then store the
            // candidate answer and
            // find for rightmost one
            if (arr[mid].a <= val) {
                ans = mid;
                low = mid + 1;
            }
            else
                high = mid - 1;
        }
        return ans;
    }
 
    // Function to build segment tree
    public static void build(
        triplet arr[], int index,
        int s, int e)
    {
        // Base Case
        if (s == e) {
            seg[index] = arr[s].c;
            return;
        }
        int mid = s + (e - s) / 2;
 
        // Build the left and right
        // segment trees
        build(arr, 2 * index + 1, s, mid);
        build(arr, 2 * index + 2, mid + 1, e);
 
        // Update current index
        seg[index] = Math.max(seg[2 * index + 1],
                              seg[2 * index + 2]);
    }
 
    // Function to get maximum value
    // in the range [qs, qe]
    public static int getMax(
        triplet arr[], int index, int s,
        int e, int qs, int qe)
    {
        // If segment is not in range
        if (qe < s || e < qs)
            return Integer.MIN_VALUE / 2;
 
        // If segment is completely
        // inside the query
        if (s >= qs && e <= qe)
            return seg[index];
 
        // Calculate the maximum value
        // in left and right half
        int mid = s + (e - s) / 2;
        return Math.max(
            getMax(arr, 2 * index + 1,
                   s, mid, qs, qe),
            getMax(arr, 2 * index + 2,
                   mid + 1, e, qs, qe));
    }
 
    // Driver Code
    public static void main(String args[])
    {
        int N = 4, K = 1;
        int A[] = { 5, 6, 9, 10 };
        int B[] = { 3, 0, 10, -10 };
 
        // Function call
        maxValue(A, B, N, K);
    }
}


Python3




# Class to store the values of a[i], b[i], a[i] + b[i]
class Triplet:
    def __init__(self, a, b, c):
        self.a = a
        self.b = b
        self.c = c
 
    # Sort values according to array
    def __lt__(self, other):
        return self.a < other.a
 
# Stores the segment tree
seg = []
 
# Function to find the maximum
# possible value according to the
# given condition
def maxValue(a, b, n, k):
 
    global seg
 
    # Initialize triparray
    arr = [Triplet(0, 0, 0) for i in range(n)]
 
    # Store the values a[i], b[i],
    # a[i] + b[i]
    for i in range(n):
        arr[i] = Triplet(a[i], b[i], a[i] + b[i])
 
    # Sort the array according
    # to array a[]
    arr.sort()
 
    # Build segment tree
    seg = [0] * (4 * n)
    build(arr, 0, 0, n - 1)
 
    # Initialise the maxvalue of
    # the selected pairs
    maxvalue = float('-inf')
 
    # Traverse the array
    for i in range(n):
 
        # For each value find the
        # floor(arr[i] + k)
        right = search(arr, arr[i].a + k)
 
        # Find the maximum value of
        # the select pairs i and max
        # from (i + 1, right)
        if right != -1:
            maxvalue = max(
                maxvalue, arr[i].b - arr[i].a + getMax(arr, 0, 0, n - 1, i + 1, right))
 
    # Print the maximum value
    print(maxvalue)
 
# Function to search floor of
# the current value
def search(arr, val):
 
    # Initialise low and high values
    low = 0
    high = len(arr) - 1
    ans = -1
 
    # Perform Binary Search
    while low <= high:
        mid = low + (high - low) // 2
 
        # If the current value is
        # <= val then store the
        # candidate answer and
        # find for rightmost one
        if arr[mid].a <= val:
            ans = mid
            low = mid + 1
        else:
            high = mid - 1
 
    return ans
 
# Function to build segment tree
def build(arr, index, s, e):
 
    # Base Case
    if s == e:
        seg[index] = arr[s].c
        return
 
    mid = s + (e - s) // 2
 
    # Build the left and right
    # segment trees
    build(arr, 2 * index + 1, s, mid)
    build(arr, 2 * index + 2, mid + 1, e)
 
    # Update current index
    seg[index] = max(seg[2 * index + 1], seg[2 * index + 2])
 
# Function to get maximum value
# in the range [qs, qe]
def getMax(arr, index, s, e, qs, qe):
 
    # If segment is not in range
    if qe < s or e < qs:
        return float('-inf')
 
    # If segment is fully in range
    if qs <= s and e <= qe:
        return seg[index]
 
    # If a part of this segment is
    # in range
    mid = s + (e - s) // 2
    left = getMax(arr, 2 * index + 1, s, mid, qs, qe)
    right = getMax(arr, 2 * index + 2, mid + 1, e, qs, qe)
 
    # Return the maximum value
    return max(left, right)
 
# Driver code
a = [5, 6, 9, 10]
b = [3, 0, 10, -10]
N = 4
K = 1
maxValue(a, b, N, K)
 
# This code is contributed by phasing17


C#




// C# program for the above approach
using System;
using System.Collections.Generic;
 
// Class to store the values of a[i],
// b[i], a[i] + b[i]
public class triplet : IComparable<triplet> {
 
    public int a, b, c;
 
    // Constructor
    public triplet(int a, int b, int c)
    {
        this.a = a;
        this.b = b;
        this.c = c;
    }
 
    // Sort values according to array
    public int CompareTo(triplet o)
    {
        return this.a - o.a;
    }
}
 
public class GFG {
 
    // Stores the segment tree
    static int []seg;
 
    // Function to find the maximum
    // possible value according to the
    // given condition
    public  void maxValue(
        int []a, int []b, int n, int k)
    {
        // Initialize triplet array
        triplet []arr = new triplet[n];
 
        // Store the values a[i], b[i],
        // a[i] + b[i]
        for (int i = 0; i < n; i++) {
 
            arr[i] = new triplet(a[i], b[i],
                                 a[i] + b[i]);
        }
 
        // Sort the array according
        // to array []a
        Array.Sort(arr);
 
        // Build segment tree
        seg = new int[4 * n];
        build(arr, 0, 0, n - 1);
 
        // Initialise the maxvalue of
        // the selected pairs
        int maxvalue = int.MinValue;
 
        // Traverse the array
        for (int i = 0; i < n; i++) {
  
            // For each value find the
            // floor(arr[i] + k)
            int right = search(arr,
                               arr[i].a + k);
 
            // Find the maximum value of
            // the select pairs i and max
            // from (i + 1, right)
            if (right != -1) {
 
                maxvalue = Math.Max(
                    maxvalue, arr[i].b - arr[i].a
                                  + getMax(arr, 0, 0, n - 1,
                                           i + 1, right));
            }
        }
 
        // Print the maximum value
        Console.WriteLine(maxvalue);
    }
 
    // Function to search floor of
    // the current value 
    public int search(
        triplet []arr, int val)
    {
        // Initialise low and high values
        int low = 0, high = arr.Length - 1;
        int ans = -1;
 
        // Perform Binary Search
        while (low <= high) {
            int mid = low + (high - low) / 2;
 
            // If the current value is
            // <= val then store the
            // candidate answer and
            // find for rightmost one
            if (arr[mid].a <= val) {
                ans = mid;
                low = mid + 1;
            }
            else
                high = mid - 1;
        }
        return ans;
    }
 
    // Function to build segment tree
    public static void build(
        triplet []arr, int index,
        int s, int e)
    {
        // Base Case
        if (s == e) {
            seg[index] = arr[s].c;
            return;
        }
        int mid = s + (e - s) / 2;
 
        // Build the left and right
        // segment trees
        build(arr, 2 * index + 1, s, mid);
        build(arr, 2 * index + 2, mid + 1, e);
 
        // Update current index
        seg[index] = Math.Max(seg[2 * index + 1],
                              seg[2 * index + 2]);
    }
 
    // Function to get maximum value
    // in the range [qs, qe]
    public static int getMax(
        triplet []arr, int index, int s,
        int e, int qs, int qe)
    {
        // If segment is not in range
        if (qe < s || e < qs)
            return int.MinValue / 2;
 
        // If segment is completely
        // inside the query
        if (s >= qs && e <= qe)
            return seg[index];
 
        // Calculate the maximum value
        // in left and right half
        int mid = s + (e - s) / 2;
        return Math.Max(
            getMax(arr, 2 * index + 1,
                   s, mid, qs, qe),
            getMax(arr, 2 * index + 2,
                   mid + 1, e, qs, qe));
    }
 
    // Driver Code
    public static void Main(String []args)
    {
        int N = 4, K = 1;
        int []A = { 5, 6, 9, 10 };
        int []B = { 3, 0, 10, -10 };
 
        // Function call
        new GFG().maxValue(A, B, N, K);
    }
}
 
// This code is contributed by 29AjayKumar


Javascript




       // JavaScript code for the above approach
       // Class to store the values of a[i], b[i], a[i] + b[i]
       class Triplet {
           constructor(a, b, c) {
               this.a = a;
               this.b = b;
               this.c = c;
           }
 
           // Sort values according to array
           compareTo(other) {
               return this.a - other.a;
           }
       }
 
       // Stores the segment tree
       let seg = [];
 
       // Function to find the maximum
       // possible value according to the
       // given condition
       function maxValue(a, b, n, k)
       {
        
           // Initialize triplet array
           let arr = new Array(n);
 
           // Store the values a[i], b[i],
           // a[i] + b[i]
           for (let i = 0; i < n; i++) {
               arr[i] = new Triplet(a[i], b[i], a[i] + b[i]);
           }
 
           // Sort the array according
           // to array a[]
           arr.sort((a, b) => a.compareTo(b));
 
           // Build segment tree
           seg = new Array(4 * n);
           build(arr, 0, 0, n - 1);
 
           // Initialise the maxvalue of
           // the selected pairs
           let maxvalue = Number.MIN_SAFE_INTEGER;
 
           // Traverse the array
           for (let i = 0; i < n; i++)
           {
            
               // For each value find the
               // floor(arr[i] + k)
               let right = search(arr, arr[i].a + k);
 
               // Find the maximum value of
               // the select pairs i and max
               // from (i + 1, right)
               if (right !== -1) {
                   maxvalue = Math.max(maxvalue, arr[i].b - arr[i].a + getMax(arr, 0, 0, n - 1, i + 1, right));
               }
           }
 
           // Print the maximum value
           console.log(maxvalue);
       }
 
       // Function to search floor of
       // the current value
       function search(arr, val)
       {
        
           // Initialise low and high values
           let low = 0;
           let high = arr.length - 1;
           let ans = -1;
 
           // Perform Binary Search
           while (low <= high) {
               let mid = low + Math.floor((high - low) / 2);
 
               // If the current value is
               // <= val then store the
               // candidate answer and
               // find for rightmost one
               if (arr[mid].a <= val) {
                   ans = mid;
                   low = mid + 1;
               } else {
                   high = mid - 1;
               }
           }
           return ans;
       }
 
       // Function to build segment tree
       function build(arr, index, s, e)
       {
        
           // Base Case
           if (s === e) {
               seg[index] = arr[s].c;
               return;
           }
           let mid = s + Math.floor((e - s) / 2);
 
           // Buildthe left and right
           // segment trees
           build(arr, 2 * index + 1, s, mid);
           build(arr, 2 * index + 2, mid + 1, e);
 
           // Update current index
           seg[index] = Math.max(seg[2 * index + 1], seg[2 * index + 2]);
       }
 
       // Function to get maximum value
       // in the range [qs, qe]
       function getMax(arr, index, s, e, qs, qe)
       {
        
           // If segment is not in range
           if (qe < s || e < qs)
           {
               return Number.MIN_SAFE_INTEGER;
           }
 
           // If segment is fully in range
           if (qs <= s && e <= qe) {
               return seg[index];
           }
 
           // If a part of this segment is
           // in range
           let mid = s + Math.floor((e - s) / 2);
           let left = getMax(arr, 2 * index + 1, s, mid, qs, qe);
           let right = getMax(arr, 2 * index + 2, mid + 1, e, qs, qe);
 
           // Return the maximum value
           return Math.max(left, right);
       }
        
       // Driver code
       let a = [5, 6, 9, 10]
       let b = [3, 0, 10, -10]
       let N = 4
       let K = 1
       maxValue(a, b, N, K);
 
// This code is contributed by Potta Lokesh


Output

4

Time Complexity: O(N*log N)
Auxiliary Space: O(N)

 



Like Article
Suggest improvement
Previous
Next
Share your thoughts in the comments

Similar Reads