/*
PROBLEM: Minimize Maximum Difference with Card Flips
Given:
- N cards, each card i has two values: A[i] (front) and B[i] (back)
- You can flip at most M cards (change from front to back)
- Initially all cards show their front value A[i]
Task: Choose which cards to flip (at most M) to minimize the difference
between the largest and smallest visible values.
Example:
N=3, M=1
Cards: (A[0]=1, B[0]=10), (A[1]=5, B[1]=6), (A[2]=9, B[2]=2)
Initially showing: [1, 5, 9] → max-min = 9-1 = 8
If we flip card 2: [1, 5, 2] → max-min = 5-1 = 4
Answer: 4
Key Insight:
- Goal: Pack all N visible values into smallest possible range
- Binary search on answer: "Can we achieve max-min <= X?"
- Use sliding window on sorted values to find valid ranges
Approach:
1. Collect all 2N possible values (both sides of each card)
2. Sort these values
3. Binary search on answer X
4. For each X, sliding window to check if any range of size X works:
- Must include at least one value from EVERY card
- Count cards where only back value is in range (these MUST be flipped)
- If flips needed <= M, then X is achievable
Time: O(N log N + log(range) * N)
*/
#include <bits/stdc++.h>
using namespace std;
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n, m;
cin >> n >> m;
vector<long long> a(n), b(n);
// Store all values: {value, card_number, which_side}
// which_side: 0 = front (a), 1 = back (b)
vector<tuple<long long, int, int>> v;
long long mn = LLONG_MAX, mx = LLONG_MIN;
for (int i = 0; i < n; i++) {
cin >> a[i] >> b[i];
v.push_back({a[i], i, 0});
v.push_back({b[i], i, 1});
mn = min(mn, min(a[i], b[i]));
mx = max(mx, max(a[i], b[i]));
}
// Sort all values
sort(v.begin(), v.end());
// Check if we can fit all cards in a range of size x
auto ok = [&](long long x) -> bool {
// Track which side of each card is in current window
vector<bool> hasA(n, false); // Is front in window?
vector<bool> hasB(n, false); // Is back in window?
int l = 0;
// Try all possible windows
for (int r = 0; r < 2 * n; r++) {
auto [val, id, side] = v[r];
// Add right value to window
if (side == 0) hasA[id] = true;
else hasB[id] = true;
// Shrink window if range too big
while (val - get<0>(v[l]) > x) {
auto [lval, lid, lside] = v[l];
// Remove left value from window
if (lside == 0) hasA[lid] = false;
else hasB[lid] = false;
l++;
}
// Count cards covered and flips needed
int covered = 0; // Cards with at least one value in window
int flips = 0; // Cards with only back in window (must flip)
for (int i = 0; i < n; i++) {
// Does card i have any value in window?
if (hasA[i] || hasB[i]) covered++;
// Does card i have ONLY back in window?
if (!hasA[i] && hasB[i]) flips++;
}
// Valid if all cards covered and flips allowed
if (covered == n && flips <= m) return true;
}
return false;
};
// Binary search on answer
long long lo = 0, hi = mx - mn;
while (lo < hi) {
long long mid = lo + (hi - lo) / 2;
if (ok(mid)) {
hi = mid; // Can do mid, try smaller
} else {
lo = mid + 1; // Can't do mid, try bigger
}
}
cout << lo << "\n";
return 0;
}