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≤10^9,1≤g_i≤10^9,1≤b_i≤10^9)


传送门

分析:

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

2.其他思路:
每次都向最优的状态转移。

代码 (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
",ans);
    }
    return 0;
}

代码 (2)

#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);
}
int main()
{
    int t,nr,ng,nb;
    scanf("%d",&t);
    while(t--)
    {
        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);
        ans=get(r[1],g[1],b[1]);
        int i=1,j=1,k=1;
        while(i<=nr&&j<=ng&&k<=nb)
        {
            ll t1=3e18,t2=3e18,t3=3e18;
            if(i+1<=nr)
                t1=get(r[i+1],g[j],b[k]);
            if(j+1<=ng)
                t2=get(r[i],g[j+1],b[k]);
            if(k+1<=nb)
                t3=get(r[i],g[j],b[k+1]);
            ll res=min(t1,min(t2,t3));
            ans=min(ans,res);
            if(res==t1) i++;
            else if(res==t2) j++;
            else k++;
        }
        printf("%lld
",ans);
    }
    return 0;
}

参考博客

原文地址:https://www.cnblogs.com/1024-xzx/p/12728678.html