Codeforces Round #359 (Div. 2)E. Optimal Point ★ ★ ★

题意:给定t组数据,每组给n个点(x,y,z)。求一个点(X,Y,Z)使得max(|xi-X|+|yi-Y|+|zi-Z|)最小。

题解:

首先二分答案 \deltaδ。假设最优的点是 (X, Y, Z)(X,Y,Z)
那么对于任意的点 ii 有|x_i - X| + |y_i - Y| + |z_i - Z| \leq \deltaxiX+yiY+ziZδ

因为 
|x_i - X| = \max\{x_i - X, X - x_i\},xiX=max{xiX,Xxi},|y_i - Y| = \max\{y_i - Y, Y - y_i\},yiY=max{yiY,Yyi},|z_i - Z| = \max\{z_i - Z, Z - z_i\}.ziZ=max{ziZ,Zzi}.所以
|x_i - X| + |y_i - Y| + |z_i - Z| = \max\{(x_i + y_i + z_i) - (X + Y + Z), \ldots\} \leq \delta.xiX+yiY+ziZ=max{(xi+yi+zi)(X+Y+Z),}δ.

总之,
\max\{x_i + y_i + z_i\} - \delta \leq X + Y + Z \leq \min\{x_i + y_i + z_i\} + \delta,max{xi+yi+zi}δX+Y+Zmin{xi+yi+zi}+δ,\max\{-x_i + y_i + z_i\} - \delta \leq -X + Y + Z \leq \min\{-x_i + y_i + z_i\} + \delta,max{xi+yi+zi}δX+Y+Zmin{xi+yi+zi}+δ,\max\{x_i + y_i - z_i\} - \delta \leq X + Y - Z \leq \min\{x_i + y_i - z_i\} + \delta,max{xi+yizi}δX+YZmin{xi+yizi}+δ,\max\{-x_i + y_i - z_i\} - \delta \leq -X + Y - Z \leq \min\{-x_i + y_i - z_i\} + \delta.max{xi+yizi}δX+YZmin{xi+yizi}+δ.

为了解不等式组,令 S = Y + ZS=Y+Z,我们知道
\max\{x_i + y_i + z_i\} - \delta -X \leq S \leq \min\{x_i + y_i + z_i\} + \delta - X,max{xi+yi+zi}δXSmin{xi+yi+zi}+δX,\max\{-x_i + y_i + z_i\} - \delta +X \leq S \leq \min\{-x_i + y_i + z_i\} + \delta + X.max{xi+yi+zi}δ+XSmin{xi+yi+zi}+δ+X.即区间
[\max\{x_i + y_i + z_i\} - \delta -X, \min\{x_i + y_i + z_i\} + \delta - X][max{xi+yi+zi}δX,min{xi+yi+zi}+δX]和区间
[\max\{-x_i + y_i + z_i\} - \delta +X, \min\{-x_i + y_i + z_i\} + \delta + X][max{xi+yi+zi}δ+X,min{xi+yi+zi}+δ+X]有交,解出 XX 的范围。

同理,令 D = Y - ZD=YZ,也可以解出 XX 的范围。如果 XX 的解集不空,任意选一个 X = X_0X=X0,得到 SS 和 DD 的范围。
如果范围内存在一组 (S, D)(S,D) 同奇偶,那么 (Y, Z)(Y,Z) 也有解。
如果奇偶性出现问题,需要再取一组 X = X_1X=X1.

具体实现时,中间运算的结果可能会超过 64 位整数。 我的代码小心地避免了溢出。

#include<map>
#include<set>
#include<cmath>
#include<queue>
#include<bitset>
#include<math.h>
#include<cstdio>
#include<vector>
#include<string>
#include<cstring>
#include<iostream>
#include<algorithm>
#pragma comment(linker, "/STACK:102400000,102400000")
using namespace std;
const int N=100010;
const int MAX=1000000100;
const int mod=100000000;
const int MOD1=1000000007;
const int MOD2=1000000009;
const double EPS=0.00000001;
typedef long long ll;
const ll MOD=998244353;
const int INF=1000000010;
const double pi=acos(-1.0);
typedef double db;
typedef unsigned long long ull;
ll mx[5],mi[5];
ll X[5][2],f[7],MX=1e18;
ll get(ll x,ll y) {//防爆longlong
    if ((x<0&&y<0)||(x>0&&y>0)) {
        ll bo=0;
        if (x%2&&y%2) bo=1;
        if (x<0&&y<0) return x/2+y/2-bo;
        else return x/2+y/2+bo;
    } else return (x+y)/2;
}
int pd(ll x) {
    f[3]=max(X[1][0]-x,X[2][0]+x);f[4]=min(X[1][1]-x,X[2][1]+x);
    f[5]=max(X[3][0]-x,X[4][0]+x);f[6]=min(X[3][1]-x,X[4][1]+x);
    if (f[3]>f[4]||f[5]>f[6]) return 0;
    if (f[4]>f[3]||f[6]>f[5]) return 1;
    if ((f[3]%2+2)%2==(f[5]%2+2)%2) return 1;
    return 0;
}
int check(ll x) {
    int i;
    for (i=1;i<5;i++) {
        X[i][0]=mx[i]-x;X[i][1]=mi[i]+x;
        if (X[i][0]>X[i][1]) return 0;
    }
    f[1]=get(X[1][0],-X[2][1]);f[2]=get(X[1][1],-X[2][0]);//[x1,x2]
    f[3]=get(X[3][0],-X[4][1]);f[4]=get(X[3][1],-X[4][0]);//[x3,x4]
    f[1]=max(f[1],max(f[3],-MX));f[2]=min(f[2],min(f[4],MX));//[x1,x2]&[x3,x4],防爆longlong
    if (f[1]>f[2]) return 0;
    for (ll j=f[1];j<=f[2];j++)
    if (pd(j)) return 1;
    return 0;
}
int main()
{
    int i,n,t;
    ll x,y,z,mxx=3*1e18;
    scanf("%d", &t);
    while (t--) {
        scanf("%d", &n);
        for (i=1;i<5;i++) {
            mi[i]=mxx;mx[i]=-mxx;
        }
        for (i=1;i<=n;i++) {
            scanf("%I64d%I64d%I64d", &x, &y, &z);
            mi[1]=min(mi[1],x+y+z);mx[1]=max(mx[1],x+y+z);
            mi[2]=min(mi[2],-x+y+z);mx[2]=max(mx[2],-x+y+z);
            mi[3]=min(mi[3],x+y-z);mx[3]=max(mx[3],x+y-z);
            mi[4]=min(mi[4],-x+y-z);mx[4]=max(mx[4],-x+y-z);
        }
        ll l=-1,r=mxx,mid=(l+r)>>1;
        while (l+1<r)
        if (check(mid)) { r=mid;mid=(l+r)>>1; }
        else { l=mid;mid=(l+r)>>1; }
        check(r);
        for (ll j=f[1];j<=f[2];j++)
        if (pd(j)) {
            x=j;
            if (f[3]==f[4]||f[5]==f[6]) {
                if (f[3]==f[4]) {
                    y=f[3];
                    if ((f[5]%2+2)%2==(f[3]%2+2)%2) z=f[5];
                    else z=f[5]+1;
                } else {
                    z=f[5];
                    if ((f[5]%2+2)%2==(f[3]%2+2)%2) y=f[3];
                    else y=f[3]+1;
                }
            } else {
                y=f[3];
                if ((f[5]%2+2)%2==(f[3]%2+2)%2) z=f[5];
                else z=f[5]+1;
            }
            break ;
        }
        printf("%I64d %I64d %I64d\n", x, get(y,z), get(y,-z));
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
资源包主要包含以下内容: ASP项目源码:每个资源包中都包含完整的ASP项目源码,这些源码采用了经典的ASP技术开发,结构清晰、注释详细,帮助用户轻松理解整个项目的逻辑和实现方式。通过这些源码,用户可以学习到ASP的基本语法、服务器端脚本编写方法、数据库操作、用户权限管理等关键技术。 数据库设计文件:为了方便用户更好地理解系统的后台逻辑,每个项目中都附带了完整的数据库设计文件。这些文件通常包括数据库结构图、数据表设计文档,以及示例数据SQL脚本。用户可以通过这些文件快速搭建项目所需的数据库环境,并了解各个数据表之间的关系和作用。 详细的开发文档:每个资源包都附有详细的开发文档,文档内容包括项目背景介绍、功能模块说明、系统流程图、用户界面设计以及关键代码解析等。这些文档为用户提供了深入的学习材料,使得即便是从零开始的开发者也能逐步掌握项目开发的全过程。 项目演示与使用指南:为帮助用户更好地理解和使用这些ASP项目,每个资源包中都包含项目的演示文件和使用指南。演示文件通常以视频或图文形式展示项目的主要功能和操作流程,使用指南则详细说明了如何配置开发环境、部署项目以及常见问题的解决方法。 毕业设计参考:对于正在准备毕业设计的学生来说,这些资源包是绝佳的参考材料。每个项目不仅功能完善、结构清晰,还符合常见的毕业设计要求和标准。通过这些项目,学生可以学习到如何从零开始构建一个完整的Web系统,并积累丰富的项目经验。
资源包主要包含以下内容: ASP项目源码:每个资源包中都包含完整的ASP项目源码,这些源码采用了经典的ASP技术开发,结构清晰、注释详细,帮助用户轻松理解整个项目的逻辑和实现方式。通过这些源码,用户可以学习到ASP的基本语法、服务器端脚本编写方法、数据库操作、用户权限管理等关键技术。 数据库设计文件:为了方便用户更好地理解系统的后台逻辑,每个项目中都附带了完整的数据库设计文件。这些文件通常包括数据库结构图、数据表设计文档,以及示例数据SQL脚本。用户可以通过这些文件快速搭建项目所需的数据库环境,并了解各个数据表之间的关系和作用。 详细的开发文档:每个资源包都附有详细的开发文档,文档内容包括项目背景介绍、功能模块说明、系统流程图、用户界面设计以及关键代码解析等。这些文档为用户提供了深入的学习材料,使得即便是从零开始的开发者也能逐步掌握项目开发的全过程。 项目演示与使用指南:为帮助用户更好地理解和使用这些ASP项目,每个资源包中都包含项目的演示文件和使用指南。演示文件通常以视频或图文形式展示项目的主要功能和操作流程,使用指南则详细说明了如何配置开发环境、部署项目以及常见问题的解决方法。 毕业设计参考:对于正在准备毕业设计的学生来说,这些资源包是绝佳的参考材料。每个项目不仅功能完善、结构清晰,还符合常见的毕业设计要求和标准。通过这些项目,学生可以学习到如何从零开始构建一个完整的Web系统,并积累丰富的项目经验。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值