题目描述
Xenia is a girl being born a noble. Due to the inflexibility and harshness of her family, Xenia has to find some ways to amuse herself.
Recently Xenia has bought nr n_r nr red gems, ng n_g ng green gems and nb n_b nb blue gems. Each of the gems has a weight.
Now, she is going to pick three gems.
Xenia loves colorful things, so she will pick exactly one gem of each color.
Xenia loves balance, so she will try to pick gems with little difference in weight.
Specifically, supposing the weights of the picked gems are x x x , y y y and z z z , Xenia wants to find the minimum value of (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 . As her dear friend, can you help her?
输入格式
The first line contains a single integer t t t ( 1≤t≤100 1\le t \le 100 1≤t≤100 ) — the number of test cases. Then t t t test cases follow.
The first line of each test case contains three integers nr,ng,nb n_r,n_g,n_b nr,ng,nb ( 1≤nr,ng,nb≤105 1\le n_r,n_g,n_b\le 10^5 1≤nr,ng,nb≤105 ) — the number of red gems, green gems and blue gems respectively.
The second line of each test case contains nr n_r nr integers r1,r2,…,rnr r_1,r_2,\ldots,r_{n_r} r1,r2,…,rnr ( 1≤ri≤109 1\le r_i \le 10^9 1≤ri≤109 ) — ri r_i ri is the weight of the i i i -th red gem.
The third line of each test case contains ng n_g ng integers g1,g2,…,gng g_1,g_2,\ldots,g_{n_g} g1,g2,…,gng ( 1≤gi≤109 1\le g_i \le 10^9 1≤gi≤109 ) — gi g_i gi is the weight of the i i i -th green gem.
The fourth line of each test case contains nb n_b nb integers b1,b2,…,bnb b_1,b_2,\ldots,b_{n_b} b1,b2,…,bnb ( 1≤bi≤109 1\le b_i \le 10^9 1≤bi≤109 ) — bi b_i bi is the weight of the i i i -th blue gem.
It is guaranteed that ∑nr≤105 \sum n_r \le 10^5 ∑nr≤105 , ∑ng≤105 \sum n_g \le 10^5 ∑ng≤105 , ∑nb≤105 \sum n_b \le 10^5 ∑nb≤105 (the sum for all test cases).
输出格式
For each test case, print a line contains one integer — the minimum value which Xenia wants to find.
题意翻译
给定三个正整数数列 r,g,br,g,br,g,b,长度分别为 nr,ng,nbn_r,n_g,n_bnr,ng,nb。
您需要在三个数列中各取一个整数 x,y,zx,y,zx,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 最小。
多组测试数据,1≤ri,gi,bi≤1091 \leq r_i,g_i,b_i \leq 10^91≤ri,gi,bi≤109,1≤nr,ng,nb≤1051 \leq n_r,n_g,n_b \leq 10^51≤nr,ng,nb≤105,1≤∑nr,∑ng,∑nb≤1051 \leq \sum n_r, \sum n_g,\sum n_b \leq 10^51≤∑nr,∑ng,∑nb≤105。
翻译 by Meatherm
输入输出样例
5 2 2 3 7 8 6 3 3 1 4 1 1 1 1 1 1000000000 2 2 2 1 2 5 4 6 7 2 2 2 1 2 3 4 6 7 3 4 1 3 2 1 7 3 3 4 6
14 1999999996000000002 24 24 14
要使答案最小,肯定要让这三个数尽可能靠的近一点,就能知道这个题应该是枚举+二分优化,关键在于二分查找找的是什么。
首先的首先,二分查找的前提是序列满足单调性,因此要sort三个数组。
我们先不妨假设一种情况:a属于r数组,b属于g数组,a<=b,然后从找一个c属于b数组满足a<=b<=c,使得答案最小,这时肯定满足a~b这个区间范围尽可能小。对于a肯定是要枚举r数组的每一个元素,无法优化。对于b,可以lower_bound在g数组里查找第一个大于等于a的数。这样a,b都能固定下来了。由数学常识,当c尽可能靠近(a+b)/2时答案能取最小,因此要在最后一个数组里查找第一个大于等于(a+b)/2的数以及最后一个小于等于(a+b)的数,更新答案。
但是不要忘了,这是先固定a和b再查找c,实际上一共有6种情况:a<=b a<=c b<=a b<=c c<=a c<=b,因此还要枚举这六种情况。
#include <bits/stdc++.h> #define N 100005 using namespace std; int r[100005],g[100005],b[100005],nr,ng,nb,pos; long long ans=9e18; long long calc(long long a,long long b,long long c) { long long temp=(a-b)*(a-b)+(a-c)*(a-c)+(b-c)*(b-c); return temp; } int bsearch(int a[],int len,int k)//自己写的二分查找函数,在l~r里(升序)找最大的小于等于k的数 { int l=1,r=len,mid,ans=0; while(l<r) { mid=(l+r)>>1; if(a[mid]>k) r=mid; else if(a[mid]==k) return mid; else { if(a[mid+1]>k) return mid; else if(a[mid+1]==k) return mid+1; else l=mid+1; } } return l; } void process(int a[],int b[],int c[],int lena,int lenb,int lenc) { int i,aa,bb,cc1,cc2,pos; for(i=1;i<=lena;i++) { aa=a[i]; pos=lower_bound(b+1,b+lenb+1,aa)-b; if(!(pos>=1&&pos<=lenb&&b[pos]>=aa))continue; bb=b[pos]; int mid=(aa+bb)/2;//在c数组找(aa+bb)/2两边的两个数 pos=lower_bound(c+1,c+lenc+1,mid)-c; if(pos>=1&&pos<=lenc&&c[pos]>=mid)//保证找出来的pos是正确的 { cc1=c[pos]; ans=min(ans,calc((long long)aa,(long long)bb,(long long)cc1));//普通乘法会爆 } pos=bsearch(c,lenc,mid); if(pos<=lenc&&pos>=1&&c[pos]<=mid) { cc2=c[pos]; ans=min(ans,calc((long long)aa,(long long)bb,(long long)cc2)); } } } int main() { int t; cin>>t; while(t--) { ans=9e18;//每轮别忘重置! int i; scanf("%d%d%d",&nr,&ng,&nb); for(i=1;i<=nr;i++)scanf("%d",&r[i]); for(i=1;i<=ng;i++)scanf("%d",&g[i]); for(i=1;i<=nb;i++)scanf("%d",&b[i]); sort(r+1,r+nr+1),sort(g+1,g+ng+1),sort(b+1,b+nb+1); process(r,g,b,nr,ng,nb); process(r,b,g,nr,nb,ng); process(g,r,b,ng,nr,nb); process(g,b,r,ng,nb,nr); process(b,r,g,nb,nr,ng); process(b,g,r,nb,ng,nr); cout<<ans<<endl; } return 0; }