Codeforces Round #635 (Div. 2) D. Xenia and Colorful Gems 题解(二分)

题目链接

题目大意

三个数组,每个数组中挑出来一个数,求 (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;
}

你可能感兴趣的:(数论)