• Codeforces Round #635 D. Xenia and Colorful Gems(暴力二分/好题)


    题目描述

    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 (xy)2+(yz)2+(zx)2 . As her dear friend, can you help her?

    输入格式

    The first line contains a single integer t t t ( 1≤t≤100 1le t le 100 1t100 ) — 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 1le n_r,n_g,n_ble 10^5 1nr,ng,nb105 ) — 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 1le r_i le 10^9 1ri109 ) — 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 1le g_i le 10^9 1gi109 ) — 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 1le b_i le 10^9 1bi109 ) — 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 nr105 , ∑ng≤105 sum n_g le 10^5 ng105 , ∑nb≤105 sum n_b le 10^5 nb105 (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(xy)2+(yz)2+(zx)2 最小。

    多组测试数据1≤ri,gi,bi≤1091 leq r_i,g_i,b_i leq 10^91ri,gi,bi109,1≤nr,ng,nb≤1051 leq n_r,n_g,n_b leq 10^51nr,ng,nb105,1≤∑nr,∑ng,∑nb≤1051 leq sum n_r, sum n_g,sum n_b leq 10^51nr,ng,nb105。

    翻译 by Meatherm

    输入输出样例

    输入 #1
    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
    输出 #1
    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;
    }


  • 相关阅读:
    sublime text 安装json插件
    通过坐标系求覆盖物面积
    关于大数据入门的相关闲聊
    渡月橋 ~君 想ふ~
    数据库快照
    oracle 11g安装与使用
    IaaS、PaaS、SaaS介绍(非原创)
    Android项目模块化/组件化开发(非原创)
    开发人员必备的网络知识(非原创)
    公司常见管理系统介绍(非原创)
  • 原文地址:https://www.cnblogs.com/lipoicyclic/p/12715501.html
Copyright © 2020-2023  润新知