CF685C. Optimal Point

题目大意

题解

类似二维,二分后变成一个六顶点八面体,维护四对面x+y+z,x+y-z,x-y+z,x-y-z的限制

要求对这个不等式组求解,想过一些做法感觉不可行

考虑换元,设A=-x+y=z,B=x-y+z,C=x+y-z,则x+y+z=A+B+C,变成关于A+B+C,A,B,C的限制,这个可以直接搞,就是把ABC都设为下界,之后A+B+C小于下界的话就把ABC增大

还原回去有x=(B+C)/2,y=(A+C)/2,z=(A+B)/2,可能不是整点所以把周围5^3个点都判一遍即可

code

#include <bits/stdc++.h>
#define fo(a,b,c) for (a=b; a<=c; a++)
#define fd(a,b,c) for (a=b; a>=c; a--)
#define inf 9223372036854775807ll
#define min(a,b) (a<b?a:b)
#define max(a,b) (a>b?a:b)
#define ll long long
//#define file
using namespace std;

ll x[100001],y[100001],z[100001],L,R,Mid,s[2][4],X,Y,Z,x2,y2,z2,xx,yy,zz,ans,S,A,B,C;
int T,n,i,j,k,l;
bool bz;

void swap(ll &x,ll &y) {ll z=x;x=y;y=z;}
bool pd(ll r)
{
	ll A,B,C;
	
	fo(i,0,3) s[0][i]=-inf,s[1][i]=inf;
	fo(i,1,n)
	{
		s[0][0]=max(s[0][0],x[i]+y[i]-r+z[i]),s[1][0]=min(s[1][0],x[i]+y[i]+r+z[i]);
		s[0][1]=max(s[0][1],x[i]+y[i]-r-z[i]),s[1][1]=min(s[1][1],x[i]+y[i]+r-z[i]);
		s[0][2]=max(s[0][2],x[i]-y[i]-r+z[i]),s[1][2]=min(s[1][2],x[i]-y[i]+r+z[i]);
		s[0][3]=max(s[0][3],x[i]-y[i]-r-z[i]),s[1][3]=min(s[1][3],x[i]-y[i]+r-z[i]);
	}
	swap(s[0][3],s[1][3]),s[0][3]=-s[0][3],s[1][3]=-s[1][3];
	return (s[0][0]<=s[1][0] && s[0][1]<=s[1][1] && s[0][2]<=s[1][2] && s[0][3]<=s[1][3]) && max(s[0][0],(double)s[0][1]+s[0][2]+s[0][3])<=min(s[1][0],(double)s[1][1]+s[1][2]+s[1][3]);
}
ll add(ll a,ll b)
{
	if (a&1) ++a,--b;
	a>>=1,b>>=1;
	return a+b;
}

ll js(ll X,ll Y,ll Z)
{
	ll s,ans=-9223372036854775807ll;
	int i;
	fo(i,1,n) s=abs(X-x[i])+abs(Y-y[i])+abs(Z-z[i]),ans=max(ans,s);
	return ans;
}

int main()
{
	#ifdef file
	freopen("CF685C.in","r",stdin);
	#endif
	
	scanf("%d",&T);
	for (;T;--T)
	{
		scanf("%d",&n);
		fo(i,1,n) scanf("%lld%lld%lld",&x[i],&y[i],&z[i]);
		
		L=0;R=6000000000000000000ll;
		while (L<R)
		{
			Mid=add(L,R);
			if (!pd(Mid))
			L=Mid+1; else R=Mid;
		}
		
		pd(L),bz=0;
		A=s[0][3],B=s[0][2],C=s[0][1];
		if ((double)A+B+C<s[0][0]) A+=min(s[1][3]-s[0][3],s[0][0]-(A+B+C));
		if ((double)A+B+C<s[0][0]) B+=min(s[1][2]-s[0][2],s[0][0]-(A+B+C));
		if ((double)A+B+C<s[0][0]) C+=min(s[1][1]-s[0][1],s[0][0]-(A+B+C));
		X=add(B,C),Y=add(A,C),Z=add(A,B);
		xx=X,yy=Y,zz=Z;
		
		ans=js(X,Y,Z);
		fo(x2,X-2,X+2)
		{
			fo(y2,Y-2,Y+2)
			{
				fo(z2,Z-2,Z+2)
				{
					S=js(x2,y2,z2);
					if (ans>S)
					ans=S,xx=x2,yy=y2,zz=z2;
				}
			}
		}
		printf("%lld %lld %lld
",xx,yy,zz);
	}
	
	fclose(stdin);
	fclose(stdout);
	return 0;
}
原文地址:https://www.cnblogs.com/gmh77/p/13654861.html