Skip to content
Related Articles

Related Articles

Improve Article
Save Article
Like Article

Find minimum value of y for the given x values in Q queries from all the given set of lines

  • Last Updated : 21 Jan, 2021

Given a 2 dimensional array arr[][] consisting of slope(m) and intercept(c) for large number of lines of the form y = mx + c and Q queries such that each query contains a value x. The task is to find the minimum value of y for the given x values from all the given set of lines.

Examples:  

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.  To complete your preparation from learning a language to DS Algo and many more,  please refer Complete Interview Preparation Course.

In case you wish to attend live classes with experts, please refer DSA Live Classes for Working Professionals and Competitive Programming Live for Students.

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



Input: arr[][] ={ {5, 6}, {3, 2}, {7, 3} }, Q = { 1, 2, 30 } 
Output: 5, 8, 92  

Naive Approach: The naive approach is to substitute the values of x in every line and compute the minimum 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 minimal 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 minimum 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:  

C++




// 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 arent 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 minimum value
    // of y for the given x coordinate
    int minQuery(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, 0 };
    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.minQuery(x) << endl;
    }
 
    return 0;
}

Java




// Java implementation of the above approach
import java.util.ArrayList;
import java.util.Arrays;
 
class GFG{
 
static class Line implements Comparable<Line>
{
    int m, c;
 
    public Line(int m, int c)
    {
        this.m = m;
        this.c = c;
    }
 
    // Sort the line in decreasing
    // order of their slopes
    @Override
    public int compareTo(Line l)
    {
         
        // If slopes arent equal
        if (m != l.m)
            return l.m - this.m;
 
        // If the slopes are equal
        else
            return l.c - this.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
    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 = new ArrayList<>();
 
    // 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.get(n - 2),
                             l.get(n - 1), newLine))
        {
            n--;
        }
 
        // l = new Line[n];
 
        // Add the present line
        l.add(newLine);
    }
 
    // Function to return the y coordinate
    // of the specified line for the given
    // coordinate
    int value(int in, int x)
    {
        return l.get(in).m * x + l.get(in).c;
    }
 
    // Function to Return the minimum value
    // of y for the given x coordinate
    int minQuery(int x)
    {
         
        // If there is no lines
        if (l.isEmpty())
            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);
    }
};
 
// Driver code
public static void main(String[] args)
{
    Line[] lines = { new Line(1, 1),
                     new Line(0, 0),
                     new Line(-3, 3) };
    int Q[] = { -2, 2, 0 };
    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.minQuery(x));
    }
}
}
 
// This code is contributed by sanjeev2552
Output: 
-1
-3
0

 




My Personal Notes arrow_drop_up
Recommended Articles
Page :

Start Your Coding Journey Now!