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:Â
CPP
// 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 codeint 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;} |
Python3
# Python3 implementation of the above approachclass Line:     def __init__(self, a = 0, b = 0):        self.m = a;        self.c = b;          # Sort the line in decreasing    # order of their slopes    def __gt__(self, l):              # If slopes arent equal        if (self.m != l.m):            return self.m > l.m;Â
        # If the slopes are equal        else:            return self.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    def check(self, L1, L2, L3):              return (L3.c - L1.c) * (L1.m - L2.m) < (L2.c - L1.c) * (L1.m - L3.m);      class Convex_HULL_Trick :Â
    # To store the lines    def __init__(self):              self.l = [];          # Add the line to the set of lines    def add(self, newLine):        n = len(self.l)Â
        # To check if after adding the new line        # whether old lines are        # losing significance or not        while (n >= 2 and newLine.check((self.l)[n - 2], (self.l)[n - 1], newLine)):             n -= 1;                  # Add the present line        (self.l).append(newLine);          # Function to return the y coordinate    # of the specified line for the given coordinate    def value(self, ind, x):        return (self.l)[ind].m * x + (self.l)[ind].c;                # Function to Return the maximum value    # of y for the given x coordinate    def maxQuery(self, x):             # if there is no lines        if (len(self.l) == 0):            return 999999999;Â
        low = 0        high = len(self.l) - 2;Â
        # Binary search        while (low <= high):            mid = int((low + high) / 2);Â
            if (self.value(mid, x) < self.value(mid + 1, x)):                low = mid + 1;            else:                high = mid - 1;                 return self.value(low, x);     # Driver codelines = [ Line(1, 1), Line(0, 0), Line(-3, 3)]Â
Q = [ -2, 2, 1];n = 3q = 3;cht = Convex_HULL_Trick();Â
# Sort the lineslines.sort(reverse = True)Â
# Add the linesfor i in range(n):Â Â Â Â cht.add(lines[i]);Â
# For each query in Qfor i in range(q): Â Â Â Â x = Q[i];Â Â Â Â print(cht.maxQuery(x));Â Â # This code is contributed by phasing17. |
C#
// C# implementation of// the above approachÂ
using System;using System.Collections.Generic;Â
class Line : IComparable<Line> {Â Â public int m, c;Â
  public Line(int m1, int c1)  {    m = m1;    c = c1;  }Â
  // Sort the line in decreasing  // order of their slopes  public int CompareTo(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  public 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);  }};Â
class Convex_HULL_Trick {Â
  // To store the lines  List<Line> l;Â
  public Convex_HULL_Trick() { l = new List<Line>(); }Â
  // Add the line to the set of lines  public void add(Line newLine)  {Â
    int n = l.Count;Â
    // 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--;    }Â
    // Add the present line    l.Add(newLine);  }Â
  // Function to return the y coordinate  // of the specified line  // for the given coordinate  public int value(int ind, int x)  {    return l[ind].m * x + l[ind].c;  }Â
  // Function to Return the maximum value  // of y for the given x coordinate  public int maxQuery(int x)  {    // if there is no lines    if (l.Count == 0)      return Int32.MaxValue;Â
    int low = 0, high = (int)l.Count - 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);  }};Â
class GFG {Â
  public static void Main(string[] args)  {    Line[] lines = { new Line(1, 1), new Line(0, 0),                    new Line(-3, 3) };    int[] Q = { -2, 2, 1 };    int n = 3, q = 3;    Convex_HULL_Trick cht = new Convex_HULL_Trick();Â
    // Sort the lines    Array.Sort(lines);Â
    // 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];      Console.WriteLine(cht.maxQuery(x));    }  }}Â
// This code is contributed by phasing17 |
Javascript
// JS implementation of// the above approachÂ
class Line {    constructor(a = 0, b = 0 )    {        this.m = a        this.c = b    }Â
Â
Â
    // Sort the line in decreasing    // order of their slopes     compare (l)    {Â
        // If slopes aren't equal        if (this.m != l.m)            return this.m > l.m;Â
        // If the slopes are equal        else            return this.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     check(L1, L2, L3)    {        return (L3.c - L1.c) * (L1.m - L2.m)            < (L2.c - L1.c) * (L1.m - L3.m);    }};Â
class Convex_HULL_Trick {Â
    // To store the lines    constructor()    {        this.l = new Array();      }Â
    // Add the line to the set of lines     add( newLine)    {Â
        let n = (this.l).length;Â
        // To check if after adding the new line        // whether old lines are        // losing significance or not        while (n >= 2            && newLine.check((this.l)[n - 2],                                (this.l)[n - 1],                                newLine)) {            n--;        }                 while ((this.l).length > n)            (this.l).pop();                  while ((this.l).length < n)            (this.l).push(new Line());         Â
        // Add the present line        (this.l).push(newLine);    }Â
    // Function to return the y coordinate    // of the specified line    // for the given coordinate     value(ind, x)    {        return (this.l)[ind].m * x + (this.l)[ind].c;    }Â
    // Function to Return the maximum value    // of y for the given x coordinate     maxQuery( x)    {        // if there is no lines        if ((this.l).length == 0)            return 999999999;Â
        let low = 0,            high = (this.l).length - 2;Â
        // Binary search        while (low <= high) {            let mid = Math.floor((low + high) / 2);Â
            if (this.value(mid, x)    < this.value(mid + 1, x))                low = mid + 1;            else                high = mid - 1;        }Â
        return this.value(low, x);    }};Â
// Driver codelet lines = [ new Line(1, 1), new Line(0, 0), new Line(-3, 3)]Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â let Q = [ -2, 2, 1 ];let n = 3, q = 3;let cht = new Convex_HULL_Trick();Â
    // Sort the lines    lines.sort(function(a, b)    {        if (a.m == b.m)            return a.c < b.c;       return a.m < b.c;    })     Â
    // Add the lines    for (var i = 0; i < n; i++)        cht.add(lines[i]);Â
    // For each query in Q    for (var i = 0; i < q; i++) {        var x = Q[i];        console.log(cht.maxQuery(x))    }Â
// This code is contributed by phasing17 |
Java
// Java implementation of// the above approachÂ
import java.util.*;Â
Â
class GFG {Â
static class Line implements Comparable<Line> {Â Â public int m, c;Â
  public Line(int m1, int c1)  {    m = m1;    c = c1;  }Â
  // Sort the line in decreasing  // order of their slopes  public int compareTo(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  public boolean check(Line L1, Line L2, Line L3)  {    return (L3.c - L1.c) * (L1.m - L2.m)      < (L2.c - L1.c) * (L1.m - L3.m);  }};Â
static class Convex_HULL_Trick {Â
  // To store the lines  ArrayList<Line> l;Â
  public Convex_HULL_Trick() { l = new ArrayList<Line>(); }Â
  // Add the line to the set of lines  public 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.get(n - 2), l.get(n - 1), newLine)) {      n--;    }Â
    // Add the present line    l.add(newLine);  }Â
  // Function to return the y coordinate  // of the specified line  // for the given coordinate  public int value(int ind, int x)  {    return (l.get(ind)).m * x + (l.get(ind)).c;  }Â
  // Function to Return the maximum value  // of y for the given x coordinate  public int maxQuery(int x)  {    // if there is no lines    if (l.size() == 0)      return Integer.MAX_VALUE;Â
    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);  }};Â
  public static void main(String[] args)  {    Line[] lines = { new Line(1, 1), new Line(0, 0),                    new Line(-3, 3) };    int[] Q = { -2, 2, 1 };    int n = 3, q = 3;    Convex_HULL_Trick cht = new Convex_HULL_Trick();Â
    // Sort the lines    Arrays.sort(lines);Â
    // 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];      System.out.println(cht.maxQuery(x));    }  }}Â
// This code is contributed by phasing17 |
9 3 2
Ready to dive in? Explore our Free Demo Content and join our DSA course, trusted by over 100,000 neveropen!

… [Trackback]
[…] Info on that Topic: geeksforgeeks.org/find-the-maximum-value-of-y-for-a-given-x-from-given-set-of-lines/ […]
… [Trackback]
[…] Read More on that Topic: geeksforgeeks.org/find-the-maximum-value-of-y-for-a-given-x-from-given-set-of-lines/ […]
… [Trackback]
[…] Find More Information here on that Topic: geeksforgeeks.org/find-the-maximum-value-of-y-for-a-given-x-from-given-set-of-lines/ […]