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

来源:互联网 发布:json格式用什么打开 编辑:程序博客网 时间:2024/04/28 17:32

题意:给定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