zoukankan      html  css  js  c++  java
  • 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=y+z-x).
    (2) 由于题目里要求所有坐标都是整数,新的坐标((x,y,z,w))必须满足(y-x,z-x)都是(2)的倍数。
    那么可以枚举(x,y,z,w)都是奇数或偶数的情况,分别求一下在(x,y,z)取值范围内(y+z-x)的最大最小值,然后和(w)的取值范围求交,调整一下即可求解。
    时间复杂度(O(nlog 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
    ",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
    ",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
    ",right);
    		check(right,true);
    	}
    	return 0;
    }
    
  • 相关阅读:
    诺基亚e71收不到彩信的解决办法
    calloc(), malloc(), realloc(), free(),alloca()
    win7下移动硬盘不能安全删除的解决方法
    C语言指针总结
    复制和剪切到底谁快?
    IC设计流程
    请用真正的原版电驴(eMule)!VeryCD是假电驴!
    [置顶] 图片检索,船,古代, 三桅, 三角帆船,侧滑浆
    [置顶] "在证书存储区中找不到清单签名证书"问题分析以及解决方案
    [置顶] sql2008 用户映射问题
  • 原文地址:https://www.cnblogs.com/suncongbo/p/12336943.html
Copyright © 2011-2022 走看看