fork download
  1. #include <bits/stdc++.h>
  2.  
  3. using namespace std;
  4.  
  5. typedef long long ll;
  6. typedef pair<int, int> ii;
  7.  
  8. const int INF = 1e9;
  9. const ll LINF = 1e18;
  10.  
  11. const int N = 1e5 + 5;
  12.  
  13. // Nhận xét: Với khoảng cách d càng lớn thì vị trí của d trong dãy sau khi sort càng lớn
  14. // => Tìm kiếm nhị phân khoảng cách d đầu tiên có vị trí >= k
  15. // Vị trí của d = (Số cặp (i, j) sao cho dist(i, j) <= d), với dist(i, j) là khoảng cách giữa 2 ngôi nhà i, j
  16. // Nhận xét: dist(i, j) = max(|x(i) - x(j)|, |y(i) - y(j)|) hay còn gọi là khoảng cách Chebyshev
  17. // dist(i, j) <= d <=> max(|x(i) - x(j)|, |y(i) - y(j)|) <= d
  18. // <=> |x(i) - x(j)| <= d và |y(i) - y(j)| <= d
  19. // Do đó để đơn giản hơn cho việc tính toán vị trí của d thì ta sẽ sort lại toạ độ của các ngôi nhà theo x
  20. // Khi xét đến ngôi nhà thứ i, ta sẽ đếm xem có bao nhiêu ngôi nhà j > i sao cho dist(i, j) <= d
  21. // Vì các ngôi nhà đã được sort lại theo x nên lúc này |x(i) - x(j)| = x(j) - x(i)
  22. // Để x(j) - x(i) <= d thì x(j) <= x(i) + d
  23. // Nên với mỗi i, cần tìm j xa nhất thoả mãn x(j) <= x(i) + d, tạm gọi là rj
  24. // Lúc này cần đếm xem có bao nhiêu chỉ số j thuộc [i + 1, rj] sao cho |y(i) - y(j)| <= d
  25. // <=> y(j) thuộc đoạn [y(i) - d, y(i) + d]
  26. // => Có thể áp dụng kĩ thuật 2 con trỏ và duy trì thêm 1 CTDL như BIT trong quá trình 2 con trỏ
  27. struct Point {
  28. int x, y;
  29. bool operator<(const Point& other) const {
  30. return x < other.x;
  31. }
  32. };
  33.  
  34. struct fenwick {
  35. int n;
  36. vector<int> ft;
  37.  
  38. fenwick(int n): n(n) {
  39. ft.resize(n, 0);
  40. }
  41.  
  42. void update(int pos, int val) {
  43. for (; pos < n; pos = pos | (pos + 1)) ft[pos] += val;
  44. }
  45.  
  46. int get(int pos) {
  47. int ans = 0;
  48. for (; pos >= 0; pos = (pos & (pos + 1)) - 1) ans += ft[pos];
  49. return ans;
  50. }
  51. };
  52.  
  53. int n; ll k;
  54. Point a[N];
  55.  
  56. vector<int> vals; // Danh sách những giá trị cần nén
  57.  
  58. // Giá trị nén của x
  59. int getVal(int x) {
  60. return lower_bound(vals.begin(), vals.end(), x) - vals.begin();
  61. }
  62.  
  63. bool check(ll d) {
  64. fenwick BIT(vals.size());
  65. ll pos = 0;
  66. for (int i = 1, j = 0; i <= n; i++) {
  67. // j xa nhất thoả mãn a[j].x <= a[i].x + d
  68. while (j + 1 <= n && a[j + 1].x <= a[i].x + d) {
  69. j++;
  70. int u = getVal(a[j].y);
  71. BIT.update(u, 1);
  72. }
  73.  
  74. // Đếm số lượng j thoả mãn a[j].y thuộc đoạn [a[i].y - d, a[i].y + d]
  75. int l = lower_bound(vals.begin(), vals.end(), a[i].y - d) - vals.begin() - 1; // Giá trị nén của phần tử lớn nhất < a[i].y - d
  76. int r = upper_bound(vals.begin(), vals.end(), a[i].y + d) - vals.begin() - 1; // Giá trị nén của phần tử lớn nhất <= a[i].y + d
  77. pos += BIT.get(r) - BIT.get(l);
  78. pos -= 1; // Trừ trường hợp j = i
  79.  
  80. int u = getVal(a[i].y);
  81. BIT.update(u, -1);
  82. }
  83. return (pos >= k);
  84. }
  85.  
  86. int main() {
  87. ios::sync_with_stdio(false);
  88. cin.tie(nullptr);
  89. cin >> n >> k;
  90.  
  91. for (int i = 1; i <= n; i++) {
  92. cin >> a[i].x >> a[i].y;
  93. vals.push_back(a[i].y);
  94. }
  95.  
  96. sort(a + 1, a + n + 1);
  97.  
  98. sort(vals.begin(), vals.end());
  99. vals.resize(unique(vals.begin(), vals.end()) - vals.begin());
  100.  
  101. ll l = 0, r = 2e9, ans = -1;
  102. while (l <= r) {
  103. ll mid = (l + r) >> 1;
  104.  
  105. if (check(mid)) {
  106. ans = mid;
  107. r = mid - 1;
  108. }
  109. else {
  110. l = mid + 1;
  111. }
  112. }
  113.  
  114. cout << ans << '\n';
  115. }
Success #stdin #stdout 0.01s 5276KB
stdin
4 3
3 1
1 -1
0 5
-2 1
stdout
4