Find the maximum value of Y for a given X from given set of lines

Given a set of lines represented by a 2-dimensional array arr consisting of slope(m) and intercept(c) respectively and Q queries such that each query contains a value x. The task is to find the maximum value of y for each value of x from all the given a set of lines.

The given lines are represented by the equation y = m*x + c.

Examples:

Input: arr[][2] ={ {1, 1}, {0, 0}, {-3, 3} }, Q = {-2, 2, 1}
Output: 9, 3, 2
For query x = -2, y values from the equations are -1, 0, 9. So the maximum value is 9
Similarly, for x = 2, y values are 3, 0, -3. So the maximum value is 3
And for x = 1, values of y = 2, 0, 0. So the maximum value is 2.

Input: arr[][] ={ {5, 6}, {3, 2}, {7, 3} }, Q = { 1, 2, 30 }
Output: 10, 17, 213



Naive Approach: The naive approach is to substitute the values of x in every line and compute the maximum of all the lines. For each query, it will take O(N) time and so the complexity of the solution becomes O(Q * N) where N is the number of lines and Q is the number of queries.

Efficient approach: The idea is to use convex hull trick:

  • From the given set of lines, the lines which carry no significance (for any value of x they never give the maximal value y) can be found and deleted thereby reducing the set.
  • Now, if the ranges (l, r) can be found where each line gives the maximum value, then each query can be answered using binary search.
  • Therefore, a sorted vector of lines, with decreasing order of slopes, is created and the lines are inserted in decreasing order of the slopes.

Below is the implementation of the above approach:

filter_none

edit
close

play_arrow

link
brightness_4
code

// C++ implementation of
// the above approach
  
#include <bits/stdc++.h>
using namespace std;
  
struct Line {
    int m, c;
  
public:
    // Sort the line in decreasing
    // order of their slopes
    bool operator<(Line l)
    {
  
        // If slopes aren't equal
        if (m != l.m)
            return m > l.m;
  
        // If the slopes are equal
        else
            return c > l.c;
    }
  
    // Checks if line L3 or L1 is better than L2
    // Intersection of Line 1 and
    // Line 2 has x-coordinate (b1-b2)/(m2-m1)
    // Similarly for Line 1 and
    // Line 3 has x-coordinate (b1-b3)/(m3-m1)
    // Cross multiplication will
    // give the below result
    bool check(Line L1, Line L2, Line L3)
    {
        return (L3.c - L1.c) * (L1.m - L2.m)
               < (L2.c - L1.c) * (L1.m - L3.m);
    }
};
  
struct Convex_HULL_Trick {
  
    // To store the lines
    vector<Line> l;
  
    // Add the line to the set of lines
    void add(Line newLine)
    {
  
        int n = l.size();
  
        // To check if after adding the new line
        // whether old lines are
        // losing significance or not
        while (n >= 2
               && newLine.check(l[n - 2],
                                l[n - 1],
                                newLine)) {
            n--;
        }
  
        l.resize(n);
  
        // Add the present line
        l.push_back(newLine);
    }
  
    // Function to return the y coordinate
    // of the specified line
    // for the given coordinate
    int value(int in, int x)
    {
        return l[in].m * x + l[in].c;
    }
  
    // Function to Return the maximum value
    // of y for the given x coordinate
    int maxQuery(int x)
    {
        // if there is no lines
        if (l.empty())
            return INT_MAX;
  
        int low = 0,
            high = (int)l.size() - 2;
  
        // Binary search
        while (low <= high) {
            int mid = (low + high) / 2;
  
            if (value(mid, x)
                < value(mid + 1, x))
                low = mid + 1;
            else
                high = mid - 1;
        }
  
        return value(low, x);
    }
};
  
// Driver code
int main()
{
    Line lines[] = { { 1, 1 },
                     { 0, 0 },
                     { -3, 3 } };
    int Q[] = { -2, 2, 1 };
    int n = 3, q = 3;
    Convex_HULL_Trick cht;
  
    // Sort the lines
    sort(lines, lines + n);
  
    // Add the lines
    for (int i = 0; i < n; i++)
        cht.add(lines[i]);
  
    // For each query in Q
    for (int i = 0; i < q; i++) {
        int x = Q[i];
        cout << cht.maxQuery(x) << endl;
    }
  
    return 0;
}

chevron_right


Output:

9
3
2

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.