给定一个二维数组arr [] [] ,该函数由y = mx + c和Q个查询形式的大量行组成,由lope(m)和intercept(c)组成,并且每个查询包含一个值x 。任务是从所有给定的线集中为给定的x值找到y的最小值。
例子:
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
天真的方法:天真的方法是替换每行中x的值并计算所有行中的最小值。对于每个查询,将花费O(N)时间,因此解决方案的复杂度变为O(Q * N) ,其中N是行数,Q是查询数。
高效的方法:想法是使用凸包技巧:
- 从给定的线组中,可以找到并删除没有意义的线(对于x的任何值,它们永远不会给出最小值y),从而减少了线组。
- 现在,如果可以在每行给出最小值的地方找到范围(l,r),则可以使用二进制搜索来回答每个查询。
- 因此,创建了具有倾斜度降序的线的分类矢量,并且以倾斜度降序将线插入。
下面是上述方法的实现:
C++
// C++ implementation of the above approach
#include
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 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
{
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 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
输出:
-1
-3
0