题目链接:C. Optimal Point
题目大意:洛谷。
题解:最大值最小-->二分答案。
所以考虑距离一个点曼哈顿距离为(r)的所有点所构成的图形。
发现是两个四棱锥平起来,非常不可做。
所以考虑用不等式。
先根据曼哈顿距离的绝对值的取值列出(2^3=8)个不等式。
然后将不等式移项整理后只剩下 4 个,这 4 个不等式中的(x,y,z)分别换元,令(a=-x+y+z,b=x-y+z,c=x+y-z),然后再带回到原不等式中去。
发现还是不怎么可做。
然后考虑这个不等式的性质。
(a,b,c)的奇偶性相同,所以可以把两种情况都做一遍。
然后就做完了,时间复杂度(O(nlog v))。
下面是代码:
#include <cstdio>
template<typename Elem>
void read(Elem &a){
a=0;
char c=getchar();
int f=1;
while(c<'0'||c>'9'){
if(c=='-'){
f=-1;
}
c=getchar();
}
while(c>='0'&&c<='9'){
a=(a<<1)+(a<<3)+(c^48);
c=getchar();
}
if(f==-1){
a=-a;
}
}
template<typename Elem>
Elem max(Elem a,Elem b){
return a>b?a:b;
}
template<typename Elem>
Elem min(Elem a,Elem b){
return a<b?a:b;
}
typedef long long ll;
const int Maxn=100000;
const ll Inf=4e18;
int n;
struct Node{
ll x,y,z;
}a[Maxn+5];
ll X,Y,Z;
bool check(ll x){
ll maxn,max_x,max_y,max_z;
maxn=max_x=max_y=max_z=Inf;
ll minn,min_x,min_y,min_z;
minn=min_x=min_y=min_z=-Inf;
for(int i=1;i<=n;i++){
maxn=min(maxn,a[i].x+a[i].y+a[i].z+x);
max_x=min(max_x,-a[i].x+a[i].y+a[i].z+x);
max_y=min(max_y,a[i].x-a[i].y+a[i].z+x);
max_z=min(max_z,a[i].x+a[i].y-a[i].z+x);
minn=max(minn,a[i].x+a[i].y+a[i].z-x);
min_x=max(min_x,-a[i].x+a[i].y+a[i].z-x);
min_y=max(min_y,a[i].x-a[i].y+a[i].z-x);
min_z=max(min_z,a[i].x+a[i].y-a[i].z-x);
}
for(int i=0;i<2;i++){
ll l=minn+((minn&1)^i),r=maxn-((maxn&1)^i);
ll l_x=min_x+((min_x&1)^i),r_x=max_x-((max_x&1)^i);
ll l_y=min_y+((min_y&1)^i),r_y=max_y-((max_y&1)^i);
ll l_z=min_z+((min_z&1)^i),r_z=max_z-((max_z&1)^i);
if(l>r||l_x>r_x||l_y>r_y||l_z>r_z){
continue;
}
ll a=l_x,b=l_y,c=l_z;
if(a+b+c>r){
continue;
}
if(a+b+c<l){
a=r_x<l-b-c?r_x:l-b-c;
}
if(a+b+c<l){
b=r_y<l-a-c?r_y:l-a-c;
}
if(a+b+c<l){
c=r_z<l-a-b?r_z:l-a-b;
}
if(a+b+c<l){
continue;
}
X=(b+c)/2;
Y=(a+c)/2;
Z=(a+b)/2;
return 1;
}
return 0;
}
int main(){
int T;
read(T);
while(T--){
read(n);
for(int i=1;i<=n;i++){
read(a[i].x),read(a[i].y),read(a[i].z);
}
ll left=0,right=Inf;
while(left<right){
ll mid=(left>>1)+(right>>1);
if((left&1)&&(right&1)){
mid++;
}
if(check(mid)){
right=mid;
}
else{
left=mid+1;
}
}
check(left);
printf("%lld %lld %lld
",X,Y,Z);
}
return 0;
}
注:Inf 的取值一定要注意,太大太小都不可以。