7-142 Distance of Triples

题目

给定数集 \(S_1,S_2,S_3\),要求:

\[\min_{a\in {S_1},b\in {S_2},c\in _{S_3}}|a-b|+|b-c|+|c-a| \]

\(|S_1,S_2,S_3|\le 10^4\)


解题报告

定义 \(x=\min(a,b,c),y=\max(a,b,c)\),那么 \(D(a,b,c)=2(y-x)\)

考虑每个集合内的元素作为 \(x\) 时,需要从另外两个集合找到 \(\ge x\) 的最小值,使得 \(D(a,b,c)\) 最小。

那么就可以枚举每个集合作为 \(x\) 的情况,然后三指针扫过去更新答案。

但是呢,我们注意到:对于当前的 \(a\le b\le c\)(这样定义的 \(a,b,c\) 并没有规定哪个属于哪个集合),影响答案的实质只有 \(a\)\(c\),那么 \(b\) 可以取当前满足 \(\le c\) 的最大值。可是上面跑出来的 \(b\) 是满足 \(\ge a\) 的最小值。这样会不满足 最大的三元组 这个条件。

为了解决这个问题,有两种写法,一种是枚举中间值,就不会出现这种情况,不过需要扫过去 \(6\) 次,复杂度有个大常数 \(2\)

另一种就是我的写法,另外又维护两个指针,分别是 \(b\)\(c\) 所属集合中满足 \(\le\) \(c/b\) 的最大值。

这道题的数据比较弱,是我我就把 \(n\) 开到 \(10^7\),毕竟 \(\operatorname O(n)\) 可做。


Code

#include <stdio.h>
#include <algorithm>
#define LL long long
using namespace std;
const int Rea=1e5+3;
struct Rin
{
    char c;
    inline char gc()
    {
        static char rea[Rea];
        static char *head,*tail;
        return head==tail&&(tail=(head=rea)+fread(rea,1,Rea,stdin),head==tail)?EOF:*head++;
    }
    inline Rin&operator >>(int &x)
    {
        x=0;
        bool tag=false;
        for(c=gc();c>'9'||c<'0';c=gc())if(c=='-'){c=gc();tag=true;break;}
        for(;c>='0'&&c<='9';c=gc())x=(x<<1)+(x<<3)+(c^'0');
        if(tag)x=-x;
        return *this;
    }
}rin;
inline void jh(int &x,int &y){x^=y^=x^=y;return;}

int ans;
int A,B,C;
inline void right_order(int &a,int &b,int &c,int tag){if(tag>2)jh(a,c);if(tag>1)jh(a,b);return;}
inline void change(int a,int b,int c,int tag){right_order(a,b,c,tag);A=a;B=b;C=c;return;}
inline bool check(int a,int b,int c,int tag){right_order(a,b,c,tag);return A==a?(B==b?c>C:b>B):a>A;}
inline void work(int *a,int *b,int *c,int *n,int tag)
{
    for(int i=1,j=1,k=1,l=0,r=0;i<=n[0];i++)
    {
        for(;j<=n[1]&&b[j]<a[i];j++);for(;l<n[2]&&c[l+1]<=b[j];l++);
        for(;k<=n[2]&&c[k]<a[i];k++);for(;r<n[1]&&b[r+1]<=c[k];r++);
        if(j>n[1]||k>n[2])break;
        int a_,b_,c_;
        if(b[j]>=c[k])a_=a[i],b_=b[j],c_=c[l];else a_=a[i],b_=b[r],c_=c[k];
        if(ans==((max(b[j],c[k])-a[i])<<1)&&check(a_,b_,c_,tag))change(a_,b_,c_,tag);
        if(ans>((max(b[j],c[k])-a[i])<<1))ans=((max(b[j],c[k])-a[i])<<1),change(a_,b_,c_,tag);
    }
    return;
}

const int N=1e4+3;
int n[3];
int a[N];
int b[N];
int c[N];
int main()
{
    rin>>n[0]>>n[1]>>n[2];
    for(int j=1;j<=n[0];j++)rin>>a[j];sort(a+1,a+n[0]+1);
    for(int j=1;j<=n[1];j++)rin>>b[j];sort(b+1,b+n[1]+1);
    for(int j=1;j<=n[2];j++)rin>>c[j];sort(c+1,c+n[2]+1);
    ans=2e9+3;
    work(a,b,c,n,1);
    jh(n[0],n[1]);work(b,a,c,n,2);
    jh(n[0],n[2]);work(c,a,b,n,3);
    printf("MinD(%d, %d, %d) = %d\n",A,B,C,ans);
    return 0;
}

\[\texttt{El Psy Congroo} \]

posted @ 2021-02-27 10:57  zjjws  阅读(294)  评论(0)    收藏  举报