Place for a Selfie (Codeforces 1805C)
Tags: Math, geometry

The universe is a coordinate plane. There are $$$n$$$ space highways, each of which is a straight line $$$y=kx$$$ passing through the origin $$$(0, 0)$$$. Also, there are $$$m$$$ asteroid belts on the plane, which we represent as open upwards parabolas, i. e. graphs of functions $$$y=ax^2+bx+c$$$, where $$$a > 0$$$.You want to photograph each parabola. To do this, for each parabola you need to choose a line that does not intersect this parabola and does not touch it. You can select the same line for different parabolas. Please find such a line for each parabola, or determine that there is no such line.

Input: Each test contains multiple test cases. The first line contains the number of test cases $$$t$$$ ($$$1 \le t \le 10^4$$$). The description of the test cases follows.The first line of each test case contains $$$2$$$ integers $$$n$$$ and $$$m$$$ ($$$1 \le n, m \le 10^5$$$) —the number of lines and parabolas, respectively.Each of the next $$$n$$$ lines contains one integer $$$k$$$ ($$$|k| \le 10^8$$$), denoting a line that is described with the equation $$$y=kx$$$. The lines are not necessarily distinct, $$$k$$$ can be equal to $$$0$$$.Each of the next $$$m$$$ lines contains $$$3$$$ integers $$$a$$$, $$$b$$$, and $$$c$$$ ($$$a, |b|, |c| \le 10^8$$$, $$$a > 0$$$) — coefficients of equations of the parabolas $$$ax^2+bx+c$$$. The parabolas are not necessarily distinct.It is guaranteed that the sum $$$n$$$ over all test cases does not exceed $$$10^5$$$, and the sum $$$m$$$ over all test cases also does not exceed $$$10^5$$$.

Output: For each test case, output the answers for each parabola in the given order. If there is a line that does not intersect the given parabola and doesn't touch it, print on a separate line the word "YES", and then on a separate line the number $$$k$$$ — the coefficient of this line. If there are several answers, print any of them. If the line does not exist, print one word "NO".You can output the answer in any case (upper or lower). For example, the strings "yEs", "yes", "Yes", and "YES" will be recognized as positive responses.The empty lines in the output in the example are given only for illustration, you do not need to output them (but you can).

Note: In the first test case, both parabolas do not intersect the only given line $$$y=1\cdot x$$$, so the answer is two numbers $$$1$$$.  In the second test case, the line $$$y=x$$$ and the parabola $$$2x^2+5x+1$$$ intersect, and also the line $$$y=4x$$$ and the parabola $$$x^2+2x+1$$$ touch, so these pairs do not satisfy the condition. So for the first parabola, the answer is $$$1$$$ ($$$y=1x$$$), and for the second parabola — $$$4$$$.  In the third test set, the line and the parabola intersect, so the answer is "NO".

Sample Inputs:
5
1 2
1
1 -1 2
1 -1 3
2 2
1
4
1 2 1
2 5 1
1 1
0
1 0 0
1 1
100000000
100000000 100000000 100000000
2 3
0
2
2 2 1
1 -2 1
1 -2 -1

Sample Outputs:
YES
1
YES
1

YES
1
YES
4

NO

YES
100000000

YES
0
NO
NO

Solution (Python):
import sys
read = sys.stdin.readline
write = sys.stdout.write
from bisect import bisect_left, bisect_right

def testcase():
    (n, m) = map(int, read().split())
    lines = [int(read()) for _ in range(n)]
    lines.sort()
    for _ in range(m):
        (a, b, c) = map(int, read().split())
        idx = bisect_left(lines, b)
        if idx > 0 and (b - lines[idx - 1]) ** 2 - 4 * a * c < 0:
            write(f'YES\n{lines[idx - 1]}\n')
        elif idx < n and (b - lines[idx]) ** 2 - 4 * a * c < 0:
            write(f'YES\n{lines[idx]}\n')
        else:
            write('NO\n')
for _ in range(int(read())):
    testcase()

Solution (Python):
from bisect import bisect_right
import sys
input = sys.stdin.readline

def solve():
    (n, m) = map(int, input().split())
    lns = []
    para = []
    for i in range(n):
        t = int(input())
        lns.append(t)
    for i in range(m):
        (a, b, c) = map(int, input().split())
        para.append((a, b, c))
    lns.sort()
    for i in para:
        (a, b, c) = (i[0], i[1], i[2])
        idx = bisect_right(lns, b)
        if idx < n:
            k = lns[idx]
            if (k - b) ** 2 < 4 * a * c:
                print('YES')
                print(k)
                continue
        if idx > 0:
            k = lns[idx - 1]
            if (b - k) ** 2 < 4 * a * c:
                print('YES')
                print(k)
                continue
        print('NO')
for _ in range(int(input())):
    solve()

Solution (Python):
import bisect

def get_closest(lst, k):
    index = bisect.bisect_left(lst, k)
    if index == 0:
        closest = lst[0]
    elif index == len(lst):
        closest = lst[-1]
    else:
        before = lst[index - 1]
        after = lst[index]
        closest = before if after - k > k - before else after
    return closest
t = int(input())
for _ in range(t):
    (n, m) = list(map(int, input().split()))
    L = []
    for _ in range(n):
        x = int(input())
        L.append(x)
    L.sort()
    P = []
    for _ in range(m):
        (a, b, c) = list(map(int, input().split()))
        P.append([a, b, c])
    for (a, b, c) in P:
        k = get_closest(L, b)
        if (b - k) ** 2 < 4 * a * c:
            print('YES')
            print(k)
        else:
            print('NO')