Solution & Algorithm Analysis
Cow at $y_c$, target point $(x, y)$, slope $s$.
Linear Equation: $$y_c = y - s \cdot x$$
The problem can be decoupled into two independent parts:
The Challenge: What about the points on the left edge $(x_1)$?
$\rightarrow$ Assign them greedily!
To minimize the total range ($\max - \min$), we want the Positive Group to start as high as possible and the Negative Group as low as possible (conceptually separating them).
Focus on the Positive Slope Group:
Since slopes and coordinates are integers, we can binary search for $y_{cow}$.
Time Complexity: $O(N \log N \cdot \log(\text{Range}))$.
We don't need to write separate logic for negative slopes.
$$y_c = y - s \cdot x \iff (-y_c) = (-y) - (-s) \cdot x$$
solve() function used for the positive group.Final Answer: $Ans_{total} = (-Ans_{neg}) - Ans_{pos}$
bool check(vector<pi> &pts, vector<int> &slopes, long long y) {
multiset<int> ss;
for (auto s: slopes) ss.insert(s);
for (auto p: pts) {
// Calculate max allowable slope for this point given cow at y
long long s0 = (p.second - y) / p.first;
// Find largest slope in set <= s0
auto it = ss.lower_bound(s0);
if (it == ss.end() || *it > s0) {
if (it == ss.begin()) return false; // No valid slope found
it--;
}
ss.erase(it); // Use this slope
}
return true;
}
// Maximize the minimum y for a set of points and positive slopes
ll solve(vector<pi> &pts, vector<int> &slopes) {
long long l = -2e14, r = 2e14; // Sufficiently large range
long long ans = -2e14;
while (l <= r) {
long long mid = (l + r) / 2;
// Adjust for negative division behavior in C++ if necessary
if (l+r < 0 && (l+r)%2 != 0) mid = (l+r-1)/2;
if (check(pts, slopes, mid)) {
ans = mid;
l = mid + 1; // Try to go higher
} else {
r = mid - 1;
}
}
return ans;
}
// 1. Separate Slopes
for (int i=0; i<4*n; i++) {
if (s[i] > 0) slopes[0].push_back(s[i]);
else slopes[1].push_back(-s[i]); // Store as positive for reuse
}
// 2. Assign Corner Points (Top-Right vs Bottom-Right)
for (int i=0; i<n; i++) {
pts[0].push_back({x2[i], y1[i]}); // To Pos Group
pts[1].push_back({x2[i], -y2[i]}); // To Neg Group (Negated)
}
// 3. Greedy Assignment of Left Edge
vector<int> y_all;
for (int i=0; i<n; i++) { y_all.push_back(y1[i]); y_all.push_back(y2[i]); }
sort(y_all.begin(), y_all.end());
for (auto y: y_all) {
if (pts[1].size() < 2*n) pts[1].push_back({x1, -y}); // Lower halves
else pts[0].push_back({x1, y}); // Upper halves
}