• 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;
    }
    
  • 相关阅读:
    付出给人一种美好的感觉
    表连接查询 条件在On与Where后区别
    Json与实体类 转化
    算法的时间复杂度和空间复杂度详解
    真的理解同步和异步了吗?
    花生壳申请域名并进行内网穿透
    XML 反序列化
    .Net 发送邮件
    BootStrap DataTable 时间日期列排序
    SQL Server 动态SQL拼接
  • 原文地址:https://www.cnblogs.com/gmh77/p/13654861.html
Copyright © 2020-2023  润新知