二分写成死循环n次,我是废物。
题目地址
思路:
在三个数组里各找一个值x,y,z,使
(
x
−
y
)
2
+
(
y
−
z
)
2
+
(
z
−
x
)
2
(x−y)^2+(y−z)^2+(z−x)^2
(x−y)2+(y−z)2+(z−x)2最小。那就是要找三个离得最近的数。
假设x<=y<=z,那就是要遍历第二个数组,对每一个元素求第一个数组里比它小的最大值和第三个数组里比它大的最小值。排列三个数组然后二分即可。
#include <bits/stdc++.h>
#define LONG_LONG_MAX 0x7fffffffffffffff
using namespace std;
const int maxn = 1e5 + 7;
int lena, lenb, lenc;
int a[maxn], b[maxn], c[maxn];
void input(int* a, int len) {
for (int i = 1; i <= len; i++) {
cin >> a[i];
}
a[0] = len;
sort(a + 1, a + 1 + len);
}
long long squ(long long a) {
return a * a;
}
long long calc(int a, int b, int c) {
long long x = a;
long long y = b;
long long z = c;
return squ(x - y) + squ(y - z) + squ(z - x);
}
int lower_search(int* a, int target) {
int l = 1, r = a[0];
while (l < r) {
int mid = (l + r + 1) / 2;
if (a[mid] <= target) {
l = mid;
}
else {
r = mid-1;
}
}
return l;
}
int upper_search(int* a, int target) {
int l = 1, r = a[0];
while (l < r) {
int mid = (l + r) / 2;
if (a[mid] >= target) {
r = mid;
}
else {
l = mid + 1;
}
}
return l;
}
void solve(int* a, int* b, int* c, long long* ans) {
for (int i = 1; i <= b[0]; i++) {
int x = b[i];
int y = a[lower_search(a, x)];
int z = c[upper_search(c, x)];
//cout<<x<<" "<<y<<" "<<z<<endl;
*ans = min(*ans, calc(x, y, z));
}
}
void test() {
int a[100];
a[0] = 99;
for (int i = 1; i < 100; i++)a[i] = i;
for (int i = 1; i < 100; i++) {
cout << lower_search(a, i) << " " << upper_search(a, i) << endl;
}
}
int main() {
int t;
//test();
cin >> t;
while (t--) {
cin >> lena >> lenb >> lenc;
input(a, lena);
input(b, lenb);
input(c, lenc);
long long ans = LONG_LONG_MAX;
solve(a, b, c, &ans);
solve(a, c, b, &ans);
solve(b, a, c, &ans);
solve(b, c, a, &ans);
solve(c, a, b, &ans);
solve(c, b, a, &ans);
cout << ans << endl;
}
}