[CF685C] Optimal Point

链接

考虑二分答案,查看有无可行解。

因为绝对值非常不好处理,直接拆掉。由于外面是 max 所以可以转化为 \(4\) 类限制。

\[l_1\leq x+y+z\leq r_1\\ l_2\leq x+y-z\leq r_2\\ l_3\leq x-y+z\leq r_3\\ l_4\leq -x+y+z\leq r_4\\ \]

令:

\[x+y-z=A\\ x-y+z=B\\ -x+y+z=C \]

有:

\[A\in[l_2,r_2]\\ B\in[l_3,r_3]\\ C\in[l_4,r_4]\\ A+B+C\in[l_1,r_1]\\ x=\lfloor\frac{A+B}{2}\rfloor\\ y=\lfloor\frac{A+C}{2}\rfloor\\ z=\lfloor\frac{B+C}{2}\rfloor\\ \]

由于 \((x,y,z)\) 要求是整数,直接枚举 \(A,B,C\) 的奇偶性:

\[A\leftarrow 2\widetilde A+r\\ B\leftarrow 2\widetilde B+r\\ C\leftarrow 2\widetilde C+r\\ \widetilde A\in[l_A,r_A],\widetilde B\in[l_B,r_B],\widetilde C\in[l_C,r_C]\\ \widetilde A+\widetilde B+\widetilde C\in[l,r] \]

剩下式子考虑调整法,一开始让 \(\widetilde A=l_A\)\(B,C\) 同理,如果满足第四个限制直接构造出一组解,否则依次让 \(A\)\(l-l_B-l_C\) 如果取不到就取 \(r_A\),查看是否合法,如果不合法再处理 \(B,C\)

最后用该解去构造 \((x,y,z)\)

复杂度 \(O(n\log W)\)

#include<iostream>
#include<cstdio>
#include<cstring>
#define N 100010
#define ll long long
#define inf 4000000000000000000
using namespace std;
ll x[N],y[N],z[N];
ll L1=-inf,R1=inf,L2=-inf,R2=inf,L3=-inf,R3=inf,L4=-inf,R4=inf;
ll dn(ll x,int i){return x+((x^i)&1);}
ll up(ll x,int i){return x-((x^i)&1);}
ll ax,ay,az;
bool solve(ll d)
{
    for(int i=0;i<=1;i++)
    {
        ll l=up(L1-d,i),l1=up(L2-d,i),l2=up(L3-d,i),l3=up(L4-d,i);
        ll r=dn(R1+d,i),r1=dn(R2+d,i),r2=dn(R3+d,i),r3=dn(R4+d,i);
        if(l1>r1 || l2>r2 || l3>r3 || l>r) continue;
        if(l1+l2+l3>r || r1+r2+r3<l) continue;
        if(l1+l2+l3<l) l1=min(r1,l-l2-l3);
        if(l1+l2+l3<l) l2=min(r2,l-l1-l3);
        if(l1+l2+l3<l) l3=min(r3,l-l1-l2);
        if(l1+l2+l3>=l){ax=(l1+l2)/2,ay=(l1+l3)/2,az=(l2+l3)/2;return true;}
    }
    return false;
}
int main()
{
    int t;
    scanf("%d",&t);
    while(t --> 0)
    {
        int n;scanf("%d",&n);
        L1=L2=L3=L4=-inf,R1=R2=R3=R4=inf;
        for(int i=1;i<=n;i++)
        {
            scanf("%lld%lld%lld",&x[i],&y[i],&z[i]);
            L1=max(L1,x[i]+y[i]+z[i]);
            L2=max(L2,x[i]+y[i]-z[i]);
            L3=max(L3,x[i]-y[i]+z[i]);
            L4=max(L4,-x[i]+y[i]+z[i]);
            R1=min(R1,x[i]+y[i]+z[i]);
            R2=min(R2,x[i]+y[i]-z[i]);
            R3=min(R3,x[i]-y[i]+z[i]);
            R4=min(R4,-x[i]+y[i]+z[i]);
        }
        ll l=-1,r=inf;
        while(l<=r)
        {
            ll mid=(l+r)>>1;
            if(solve(mid)) r=mid-1;
            else l=mid+1;
        }
        printf("%lld %lld %lld\n",ax,ay,az);
    }
    return 0;
}
posted @ 2021-10-14 16:32  Flying2018  阅读(46)  评论(0编辑  收藏  举报