Xenia and Colorful Gems

题意:

给出3个序列各有:\(n_r,n_g,n_g\) 个。现在在每个序列中选择一个数:\(x,y,z\),使得 \((x-y)^2+(x-z)^2+(y-z)^2\) 最小,求出该最小值。
数据范围:\(1≤n_r,n_g,n_b≤10^5,1≤r_i≤109,1≤g_i≤10^9,1≤b_i≤10^9\)

传送门

分析:

1.官方题解思路:
首先,大概思路是:枚举一个值,然后可以求出另外两个。
假定:\(r_i\leq g_i \leq b_i\),那么 \(r_i\)\(b_i\) 必然是越接近 \(g_i\) ,整个的值越小。因此,可以借助二分来求出 \(r_i\)\(b_i\)
按照分析,有六种可能的排列顺序,枚举进行处理即可。
反思:大概思路想到了,但就是没有想到可以按顺序取分情况处理。

代码 \(1\)

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e5+5;
int r[N],g[N],b[N];
ll ans;
ll get(int x,int y,int z)
{
    return 1LL*(x-y)*(x-y)+1LL*(x-z)*(x-z)+1LL*(y-z)*(y-z);
}
void solve(int a[],int c[],int d[],int x,int y,int z)
{
    for(int i=1;i<=y;i++)
    {
        int t1=lower_bound(a+1,a+1+x,c[i])-a;
        int t2=lower_bound(d+1,d+1+z,c[i])-d;
        if(t1>x||t1<=x&&a[t1]>c[i])
            t1--;
        if(t1>=1&&t1<=x&&t2>=1&&t2<=z)
        {
            ll res=get(a[t1],c[i],d[t2]);//cout<<"res="<<res<<endl;
            ans=min(ans,res);
        }
    }
}
int main()
{
    int t,nr,ng,nb;
    scanf("%d",&t);
    while(t--)
    {
        ans=3e18;
        scanf("%d%d%d",&nr,&ng,&nb);
        for(int i=1;i<=nr;i++)
            scanf("%d",&r[i]);
        for(int i=1;i<=ng;i++)
            scanf("%d",&g[i]);
        for(int i=1;i<=nb;i++)
            scanf("%d",&b[i]);
        sort(r+1,r+1+nr);
        sort(g+1,g+1+ng);
        sort(b+1,b+1+nb);
        for(int i=1;i<=6;i++)
        {
            if(i==1)
                solve(r,g,b,nr,ng,nb);
            else if(i==2)
                solve(b,g,r,nb,ng,nr);
            else if(i==3)
                solve(g,r,b,ng,nr,nb);
            else if(i==4)
                solve(b,r,g,nb,nr,ng);
            else if(i==5)
                solve(g,b,r,ng,nb,nr);
            else
                solve(r,b,g,nr,nb,ng);
        }
        printf("%lld\n",ans);
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/1024-xzx/p/12728678.html