[关闭]
@xiaoziyao 2021-07-09T11:59:43.000000Z 字数 2881 阅读 835

CF685C Optimal Point解题报告

解题报告


CF685C Optimal Point解题报告:

更好的阅读体验

题意

给定 个立体三维坐标系的整点(坐标范围 ),求一个点使得其与所有点的曼哈顿距离最大值最小。(

分析

优美的胖题。

首先求最大值最小就可以知道要二分这个距离最大值。

考虑怎么 check 这个距离 ,发现这等价于解这个方程组的解(其中 为未知数):

发现这个绝对值很难拆,但由于 ,所以每个不等式可以等价为:

然后不难发现这个不等式可以化作:

为前四个式子的最大值, 为后四个式子的最小值,, ,那么等价于:

由于 ,且它们都是整数,所以还有

此时套路地枚举 的最后一个二进制位 再处理一下边界,那么模 相同的限制就没了,最后不难用调整法算出一个答案。

时间复杂度:

代码

  1. #include<stdio.h>
  2. #include<iostream>
  3. #define inf 6000000000000000000
  4. using namespace std;
  5. const int maxn=100005;
  6. int T,n;
  7. long long ansx,ansy,ansz;
  8. long long x[maxn],y[maxn],z[maxn];
  9. inline long long ceil(long long x){
  10. return x>=0? (x+1)/2ll:-((-x)/2ll);
  11. }
  12. inline long long floor(long long x){
  13. return x>=0? x/2ll:-((-x+1)/2ll);
  14. }
  15. int check(long long mid){
  16. long long al=-inf,bl=-inf,cl=-inf,dl=-inf,ar=inf,br=inf,cr=inf,dr=inf;
  17. //al<=a+b+c<=ar,bl<=a<=br,cl<=b<=cr,dl<=c<=dr
  18. for(int i=1;i<=n;i++){
  19. al=max(al,x[i]+y[i]+z[i]-mid),ar=min(ar,x[i]+y[i]+z[i]+mid);
  20. bl=max(bl,-x[i]+y[i]+z[i]-mid),br=min(br,-x[i]+y[i]+z[i]+mid);
  21. cl=max(cl,x[i]-y[i]+z[i]-mid),cr=min(cr,x[i]-y[i]+z[i]+mid);
  22. dl=max(dl,x[i]+y[i]-z[i]-mid),dr=min(dr,x[i]+y[i]-z[i]+mid);
  23. }
  24. for(int t=0;t<=1;t++){
  25. long long wl=ceil(al-3*t),wr=floor(ar-3*t);
  26. long long xl=ceil(bl-t),xr=floor(br-t);
  27. long long yl=ceil(cl-t),yr=floor(cr-t);
  28. long long zl=ceil(dl-t),zr=floor(dr-t);
  29. if(wl<=wr&&xl<=xr&&yl<=yr&&zl<=zr&&xl+yl+zl<=wr&&xr+yr+zr>=wl){
  30. long long x=xl,y=yl,z=zl,up=max(0ll,wl-xl-yl-zl);
  31. x+=min(up,xr-xl),up-=min(up,xr-xl);
  32. y+=min(up,yr-yl),up-=min(up,yr-yl);
  33. z+=min(up,zr-zl),up-=min(up,zr-zl);
  34. x=((x<<1)|t),y=((y<<1)|t),z=((z<<1)|t);
  35. ansx=(y+z)>>1,ansy=(x+z)>>1,ansz=(x+y)>>1;
  36. return 1;
  37. }
  38. }
  39. return 0;
  40. }
  41. int main(){
  42. scanf("%d",&T);
  43. while(T--){
  44. scanf("%d",&n);
  45. for(int i=1;i<=n;i++)
  46. scanf("%lld%lld%lld",&x[i],&y[i],&z[i]);
  47. long long L=-1,R=inf+1;
  48. while(L+1<R){
  49. long long mid=L+(R-L)/2ll;
  50. if(check(mid))
  51. R=mid;
  52. else L=mid;
  53. }
  54. check(R);
  55. printf("%lld %lld %lld\n",ansx,ansy,ansz);
  56. }
  57. return 0;
  58. }

整场比赛的题解

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注