题解 CF685C 【Optimal Point】
CF685C Optimal Point
这个题,我看到的第一眼以为是个三分。因为
然后我们看一眼题意,它是要求距离的最大值最小,而最大值最小又可以提示我们这个题可能需要二分,那么我们就可以很显然地去二分这个最大距离
我们会发现这是个很不好处理的不等式关系组,因为有一堆变量,还套个绝对值。我们考虑拆绝对值,根据正负关系,应该会得到
看起来是组很恐怖的式子。考虑移项合并,则有:
其中
这里的
我们考虑换元,令
我们还会发现另外一点,就是
这样我们再带回第二个不等式组,则有:
那么问题就在于如何求解这个不等式组了。其实也不要想得太复杂,因为我们只要求出一组解,所以可以考虑我们平时做数学题的策略:令
若不满足条件,而且
最后的时间复杂度应该是
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <cctype>
#include <queue>
#include <vector>
using namespace std;
inline long long read()
{
long long x=0,f=1;char ch=getchar();
while (!isdigit(ch)){if (ch=='-') f=-1;ch=getchar();}
while (isdigit(ch)){x=x*10+ch-48;ch=getchar();}
return x*f;
}
int n;
long long x[100050],y[100050],z[100050],xans,yans,zans;
inline void Init()
{
for (int i=1;i<=n;i++)
x[i]=y[i]=z[i]=0;
//memset(x,0,sizeof(x));
//memset(y,0,sizeof(y));
//memset(z,0,sizeof(z));
xans=yans=zans=0;
}
inline bool check(long long mid)
{
long long r1=4e18,r2=4e18,r3=4e18,r4=4e18;
long long l1=-4e18,l2=-4e18,l3=-4e18,l4=-4e18;
for (int i=1;i<=n;i++)
{
r1=min(r1,mid+x[i]+y[i]+z[i]);
r2=min(r2,mid-x[i]+y[i]+z[i]);
r3=min(r3,mid+x[i]-y[i]+z[i]);
r4=min(r4,mid+x[i]+y[i]-z[i]);
l1=max(l1,-mid+x[i]+y[i]+z[i]);
l2=max(l2,-mid-x[i]+y[i]+z[i]);
l3=max(l3,-mid+x[i]-y[i]+z[i]);
l4=max(l4,-mid+x[i]+y[i]-z[i]);
}
for (int i=0;i<=1;i++)
{
long long l11=l1+((l1&1)^i);
long long r11=r1-((r1&1)^i);
long long l21=l2+((l2&1)^i);
long long r21=r2-((r2&1)^i);
long long l31=l3+((l3&1)^i);
long long r31=r3-((r3&1)^i);
long long l41=l4+((l4&1)^i);
long long r41=r4-((r4&1)^i);
if (l11<=r11 && l21<=r21 && l31<=r31 && l41<=r41)
{
long long a=l21;
long long b=l31;
long long c=l41;
if (a+b+c<=r11)
{
if (a+b+c<l11)
{
if (r21<l11-b-c)
a=r21;
else
a=l11-b-c;
}
if (a+b+c<l11)
{
if (r31<l11-a-c)
b=r31;
else
b=l11-a-c;
}
if (a+b+c<l11)
{
if (r41<l11-a-b)
c=r41;
else
c=l11-a-b;
}
if (a+b+c>=l11)
{
xans=(b+c)>>1;
yans=(a+c)>>1;
zans=(a+b)>>1;
return 1;
}
}
}
}
return 0;
}
int main()
{
int T=read();
while (T--)
{
n=read();
Init();
for (int i=1;i<=n;i++)
{
x[i]=read();
y[i]=read();
z[i]=read();
}
if (n==1)
{
cout << x[1] << " " << y[1] << " " << z[1] << endl;
continue;
}
long long left=0,right=4e18;
while (left<=right)
{
long long mid=(left+right)>>1;
if (check(mid))
right=mid-1;
else
left=mid+1;
}
cout << xans << " " << yans << " " << zans << endl;
}
return 0;
}