三个数组,每个数组中挑出来一个数,求 (x−y)^ 2 + (x−z)^ 2+(y−z)^2的最小值。
暴力是o(n^3)肯定会爆,但是显然这个答案要使得这三个值最接近。
枚举中间值,然后二分寻找比他大的最小值和比他小的最大值即可
#include
using namespace std;
typedef long long ll;
int t,n1,n2,n3;
ll cal(ll x,ll y,ll z){
return (x-y)*(x-y)+(x-z)*(x-z)+(y-z)*(y-z);
}
int main(){
scanf("%d",&t);
while(t--){
scanf("%d%d%d",&n1,&n2,&n3);
vector<int> vec[4];
for(int i=1,x;i<=n1;i++){
scanf("%d",&x);
vec[1].push_back(x);
}
for(int i=1,x;i<=n2;i++){
scanf("%d",&x);
vec[2].push_back(x);
}
for(int i=1,x;i<=n3;i++){
scanf("%d",&x);
vec[3].push_back(x);
}
for(int i=1;i<=3;i++){
sort(vec[i].begin(),vec[i].end());
}
ll ans=9e18;
for(int i=1;i<=3;i++){
for(int j=1;j<=3;j++){
for(int k=1;k<=3;k++){
if(i!=j&&i!=k&&j!=k){
for(auto x:vec[i]){
auto y = lower_bound(vec[j].begin(), vec[j].end(), x);
auto z = upper_bound(vec[k].begin(), vec[k].end(), x);
// z<=x<=y
if(y!=vec[j].end()&&z!=vec[k].begin()){
z--;
ans=min(ans,cal(x,*y,*z));
}
}
}
}
}
}
printf("%lld\n",ans);
}
return 0;
}