Codeforces 685C Optimal Point (二分、不同类型距离的相互转换)

题目链接

https://codeforces.com/contest/685/problem/C

题解

我怎么又还差最后一步的时候放弃了然后往别的方向上想了一小时才发现这个思路能做……

首先二分答案,转化为所有点半径为\(mid\)的曼哈顿距离区域内是否有交。
考虑二维问题,显然可以用曼哈顿转切比雪夫来做,把\((x,y)\)变成\((x+y,x-y)\)那么原来两点的曼哈顿距离就等于后来两点的切比雪夫距离。考虑一下这个做法的证明: \[|x_1-x_2|+|y_1-y_2|=\max(x_1-x_2+y_1-y_2,x_1-x_2-y_1+y_2,-x_1+x_2+y_1-y_2,-x_1+x_2-y_1+y_2)=\max(|(x_1+y_1)-(x_2+y_2)|,|(x_1-y_1)-(x_2-y_2)|)\]
三维的问题也可以用类似的思路。\[|x_1-x_2|+|y_1-y_2|+|z_1-z_2|=\max(|(x_1+y_1+z_1)-(x_2+y_2+z_2)|,|(x_1-y_1+z_1)-(x_2-y_2+z_2)|,|(x_1+y_1-z_1)-(x_2+y_2-z_2)|,|(x_1-y_1-z_1)-(x_2-y_2-z_2)|)\]于是我们可以把\((x,y,z)\)变成一个四维的坐标\((x+y+z,x-y+z,x+y-z,x-y-z)\), 曼哈顿距离就变成了切比雪夫距离,求一下区间交就行了。但是有以下两个附加限制:

(1) 新的坐标\((x,y,z,w)\)必须满足\(w=x+y-z\).

(2) 由于题目里要求所有坐标都是整数,新的坐标\((x,y,z,w)\)必须满足\(y-x,z-x\)都是\(2\)的倍数。
那么可以枚举\(x,y,z,w\)都是奇数或偶数的情况,分别求一下在\(x,y,z\)取值范围内\(y+z-x\)的最大最小值,然后和\(w\)的取值范围求交,调整一下即可求解。
时间复杂度\(O(n\log C)\), \(C\)为值域。

代码

#include<bits/stdc++.h>
#define llong long long
#define mkpr make_pair
#define riterator reverse_iterator
using namespace std;

inline int read()
{
    int x = 0,f = 1; char ch = getchar();
    for(;!isdigit(ch);ch=getchar()) {if(ch=='-') f = -1;}
    for(; isdigit(ch);ch=getchar()) {x = x*10+ch-48;}
    return x*f;
}

const int N = 1e5;
const llong INF = 6e18+1;
struct Point
{
    llong x,y,z,w;
} a[N+3];
int n;

llong fun(llong x,llong y,llong z) {return x&1?x+z:x+y;}

bool check(llong mid,bool typ=false)
{
    llong lx = -INF,ly = -INF,lz = -INF,lw = -INF,rx = INF,ry = INF,rz = INF,rw = INF;
    for(int i=1; i<=n; i++)
    {
        lx = max(lx,a[i].x-mid); rx = min(rx,a[i].x+mid);
        ly = max(ly,a[i].y-mid); ry = min(ry,a[i].y+mid);
        lz = max(lz,a[i].z-mid); rz = min(rz,a[i].z+mid);
        lw = max(lw,a[i].w-mid); rw = min(rw,a[i].w+mid);
    }
    if(lx>rx||ly>ry||lz>rz||lw>rw) return false;
    llong lx2 = fun(lx,0,1),ly2 = fun(ly,0,1),lz2 = fun(lz,0,1),lw2 = fun(lw,0,1),rx2 = fun(rx,0,-1),ry2 = fun(ry,0,-1),rz2 = fun(rz,0,-1),rw2 = fun(rw,0,-1);
    if(lx2<=rx2&&ly2<=ry2&&lz2<=rz2&&lw2<=rw2)
    {
        llong lw3 = ly2+lz2-rx2,rw3 = ry2+rz2-lx2;
        if(max(lw2,lw3)<=min(rw2,rw3))
        {
            llong w = max(lw2,lw3),x = rx2,y = ly2,z = lz2;
            if(typ)
            {
                if(y+z-x<w) {y += min(ry2-ly2,w-(y+z-x));}
                if(y+z-x<w) {z += min(rz2-lz2,w-(y+z-x));}
                if(y+z-x<w) {x -= min(rx2-lx2,w-(y+z-x));}
                llong xx = (y+z)/2ll,yy = (x-y)/2ll,zz = (x-z)/2ll;
                printf("%I64d %I64d %I64d\n",xx,yy,zz);
            }
            return true;
        }
    }
    lx2 = fun(lx,1,0),ly2 = fun(ly,1,0),lz2 = fun(lz,1,0),lw2 = fun(lw,1,0),rx2 = fun(rx,-1,0),ry2 = fun(ry,-1,0),rz2 = fun(rz,-1,0),rw2 = fun(rw,-1,0);
    if(lx2<=rx2&&ly2<=ry2&&lz2<=rz2&&lw2<=rw2)
    {
        llong lw3 = ly2+lz2-rx2,rw3 = ry2+rz2-lx2;
        if(max(lw2,lw3)<=min(rw2,rw3))
        {
            if(typ)
            {
                llong w = max(lw2,lw3),x = rx2,y = ly2,z = lz2;
                if(y+z-x<w) {y += min(ry2-ly2,w-(y+z-x));}
                if(y+z-x<w) {z += min(rz2-lz2,w-(y+z-x));}
                if(y+z-x<w) {x -= min(rx2-lx2,w-(y+z-x));}
                llong xx = (y+z)/2ll,yy = (x-y)/2ll,zz = (x-z)/2ll;
                printf("%I64d %I64d %I64d\n",xx,yy,zz);
            }
            return true;
        }
    }
    return false;
}

int main()
{
    int T; scanf("%d",&T);
    while(T--)
    {
        scanf("%d",&n);
        for(int i=1; i<=n; i++)
        {
            llong x,y,z; scanf("%I64d%I64d%I64d",&x,&y,&z);
            a[i].x = x+y+z,a[i].y = x-y+z,a[i].z = x+y-z,a[i].w = x-y-z;
        }
        llong left = 0ll,right = 3e18;
        while(left<right)
        {
            llong mid = left+(right-left>>1);
            if(check(mid)) {right = mid;}
            else {left = mid+1;}
        }
//      printf("ans=%I64d\n",right);
        check(right,true);
    }
    return 0;
}

原文地址:https://www.cnblogs.com/suncongbo/p/12336943.html

时间: 2025-01-06 13:31:15

Codeforces 685C Optimal Point (二分、不同类型距离的相互转换)的相关文章

POJ 2112 Optimal Milking 二分答案+最大流

首先二分最长的边,然后删去所有比当前枚举的值长的边,算最大流,看是否能满足所有的牛都能找到挤奶的地方 #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> #include <climits> #include <string> #include <iostream> #include <map> #include

java Data、String、Long三种日期类型之间的相互转换

java Data.String.Long三种日期类型之间的相互转换 // date类型转换为String类型 // formatType格式为yyyy-MM-dd HH:mm:ss//yyyy年MM月dd日 HH时mm分ss秒 // data Date类型的时间 public static String dateToString(Date data, String formatType) { return new SimpleDateFormat(formatType).format(data

Codeforces Round #425 (Div. 2) Problem C (Codeforces 832C) Strange Radiation - 二分答案 - 数论

n people are standing on a coordinate axis in points with positive integer coordinates strictly less than 106. For each person we know in which direction (left or right) he is facing, and his maximum speed. You can put a bomb in some point with non-n

codeforces 343C Read Time 二分 + 贪心

http://codeforces.com/problemset/problem/343/C 题意: 有一些磁头,给出了起始的位置,给出了一些磁盘中需要访问的地点.求这些磁头移动的最小的次数. 思路: 二分找出满足要求的最小的时间,对于当前尝试的时间进行贪心判断是否可用.对于贪心,因为每一个磁头都需要读到还没有人读过的最左边的地方.如果这个都不能满足,那么这个时间是不可以的. 在这基础上,对于同样的这么多时间,尽可能的让这个磁头读到能读到的最右边,这样就可以将还没有读过的地方尽可能的往右推. 如

Codeforces 772A Voltage Keepsake - 二分答案

You have n devices that you want to use simultaneously. The i-th device uses ai units of power per second. This usage is continuous. That is, in λ seconds, the device will use λ·ai units of power. The i-th device currently has bi units of power store

POJ 2112 Optimal Milking (二分 + 最大流)

题目大意: 在一个农场里面,有k个挤奶机,编号分别是 1..k,有c头奶牛,编号分别是k+1 .. k+c,每个挤奶机一天最让可以挤m头奶牛的奶,奶牛和挤奶机之间用邻接矩阵给出距离.求让所有奶牛都挤到 奶的情况下,走的最远的那头奶牛走的距离最小是多少. 数据保证有解. 算法讨论: 首先可以想到是二分,然后在选择流网络的时候,一开始选择的最小费用最大流,让二分的边权充当最小费用,但是这样跑发现每次二分的是我们要跑的答案,不可行.所以就改用最大流. 最大流肯定是在二分的情况下判定最大流是否等于c,即

【模拟】Codeforces 710B Optimal Point on a Line

题目链接: http://codeforces.com/problemset/problem/710/B 题目大意: 给N个点的坐标,在X轴上找到最靠左的点使得这个点到N个点距离之和最小. 题目思路: [模拟] 先将N个点坐标排序,找夹在i中间的坐标即为答案.(中间2个数选左边的) 从点坐标是X的点往左移到X+1,代价是X右边的坐标数-左边的坐标数.当X不是给定的坐标时答案是不会变得. 所以最终寻找的这个点一定是N个点中个某个点.并且就在正中中间的位置.如果正中间有两个数,那么这两个数之间的任何

Codeforces gym 100517(二分,同方向判断)

题意:给了一个凸包,按顺时针顺序给点,点数不超过10万,再给了两个不同点,点严格在凸包内,凸包保证没有三点共线,问凸包上有多少对点(pi, pj),满足pi和pj的线段 与 两个点的线段严格相交,线段间严格相交意思是交点不在端点. 链接:http://codeforces.com/gym/100517 (K题) 解法:设凸包有n个点,将凸包点集p扩大一倍,变为2n个点.枚举前n个点,每次枚举到 i ,在[i+1, i+n-1]内进行二分,找到两个点p1,p2,满足p1和p2是"最靠近"

Educational Codeforces Round 21 Problem F (Codeforces 808F) - 最小割 - 二分答案

Digital collectible card games have become very popular recently. So Vova decided to try one of these. Vova has n cards in his collection. Each of these cards is characterised by its power pi, magic number ci and level li. Vova wants to build a deck