【Codeforces 685C】Optimal Point
二分答案
题目大意:
给定 $n$ 个三维平面的整点,要求找到一个整点,使得给定的 $n$ 个点中,离它曼哈顿距离最远的那个点离它的曼哈顿距离最近。
题解:
显然可以二分答案。
我们可以确定出以下式子:
令 $a=-x+y+z,b=x-y+z,c=x+y-z$,那么有
由于 $x,y,z$ 均为整数,所以 $a,b,c$ 奇偶性要相同。分别对奇数和偶数判断即可。
判断的时候,先令 $a,b,c$ 最小,这时 $x+y+z$ 最小。然后分别把 $a,b,c$ 改到最大或尽可能大,满足 $x+y+z$ 恰好为上限。这时的答案显然合法。
一开始时先把不等式冲突的情况判掉即可。
不等式相关信息可以在二分外面求出来。
时间复杂度 $O(n+\log w)$。
Code:
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
#define rep(i,x,y)for(int i=(x);i<=(y);++i)
typedef long long LL;
const int N=1e5+5;
int n,T;
LL X[N],Y[N],Z[N];
LL w[8],sx,sy,sz;
inline bool check(LL k){
rep(_,0,1){
LL aL=-w[4]-k,bL=-w[2]-k,cL=-w[1]-k,aR=w[3]+k,bR=w[5]+k,cR=w[6]+k;
LL sL=-w[0]-k,sR=w[7]+k;
if((aL&1)!=_)++aL;
if((bL&1)!=_)++bL;
if((cL&1)!=_)++cL;
if((sL&1)!=_)++sL;
if((aR&1)!=_)--aR;
if((bR&1)!=_)--bR;
if((cR&1)!=_)--cR;
if((sR&1)!=_)--sR;
if(aL>aR||bL>bR||cL>cR||sL>sR||aL+bL+cL>sR||aR+bR+cR<sL)continue;
LL a=aL,b=bL,c=cL;
if(aR+b+c<=sR)a=aR;else a=a+(sR-a-b-c);
if(a+bR+c<=sR)b=bR;else b=b+(sR-a-b-c);
if(a+b+cR<=sR)c=cR;else c=c+(sR-a-b-c);
sx=b+c>>1,sy=a+c>>1,sz=a+b>>1;
return 1;
}
return 0;
}
int main(){
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
for(cin>>T;T--;){
cin>>n;
rep(i,1,n)cin>>X[i]>>Y[i]>>Z[i];
memset(w,0x3f,sizeof w);
rep(_1,0,1)rep(_2,0,1)rep(_3,0,1){
LL&s=w[(_1<<2)|(_2<<1)|_3];
rep(i,1,n){
LL k=(X[i]*(_1?1:-1))+(Y[i]*(_2?1:-1))+(Z[i]*(_3?1:-1));
s=min(s,k);
}
}
LL l=0,r=3e18,ans=3e18;
while(l<=r){
const LL mid=l+r>>1;
if(check(mid))r=(ans=mid)-1;else l=mid+1;
}
check(ans);
cout<<sx<<' '<<sy<<' '<<sz<<'\n';
}
return 0;
}