标签:oid 二分答案 def eof target blank 枚举 fast dig
考虑要最小化最大值,容易想到二分答案\(d\),那么就是要判断是否存在一个整点\((X,Y,Z)\)满足:
众所周知,\(|x|=\max\{x,-x\}\),所以\(|x|\le y\Leftrightarrow x\le y\wedge -x\le y\)。
也就是说,上面的式子可以被我们暴拆成八个式子,把\(X,Y,Z\)单独放一边,\(x_i,y_i,z_i\)和\(d\)放到另一边,就可以计算出\(X+Y+Z\),\(X+Y-Z\),\(X+Z-Y\),\(Y+Z-X\)四者的取值范围。
直接做仍旧是比较棘手的,发现\(X+Y+Z\)恰好等于后面三项之和,因此令\(A=X+Y-Z\),\(B=X+Z-Y\),\(C=Y+Z-X\),只要解出\(A,B,C\)的值就能还原出\(X=\frac{A+B}2\),\(Y=\frac{A+C}2\),\(Z=\frac{B+C}2\)。
但还要保证解得的\(X,Y,Z\)是整数,这充要于\(A,B,C\)奇偶性相同。
因此我们不妨枚举\(i=A\% 2\),则\(A=2A‘+i\),\(B=2B‘+i\),\(C=2C‘+i\),则我们可以通过原本的范围计算出\(A‘+B‘+C‘,A‘,B‘,C‘\)的范围。
再要判是否存在解就非常简单了,首先如果某一项的取值范围为空(左边界大于右边界)显然无解。
否则,\(A‘+B‘+C‘\)实际的取值范围应该是\(A‘,B‘,C‘\)最小值之和到最大值之和(中间的所有整值都能取到)。
故将\(A‘+B‘+C‘\)限制的取值范围与此比较,如果无交说明无解,否则有解。
而要构造一组解也是很简单的,先让\(A‘,B‘,C‘\)全取最小值,然后依次枚举每个数往大调整即可。
#include<bits/stdc++.h>
#define Tp template<typename Ty>
#define Ts template<typename Ty,typename... Ar>
#define Reg register
#define RI Reg int
#define Con const
#define CI Con int&
#define I inline
#define W while
#define N 100000
#define LL long long
#define INF (LL)4e18
using namespace std;
int n;LL x[N+5],y[N+5],z[N+5];
namespace FastIO
{
#define FS 100000
#define tc() (FA==FB&&(FB=(FA=FI)+fread(FI,1,FS,stdin),FA==FB)?EOF:*FA++)
#define D isdigit(oc=tc())
int ff;char oc,FI[FS],*FA=FI,*FB=FI;
Tp I void read(Ty& x) {x=0,ff=1;W(!D) ff=oc^‘-‘?1:-1;W(x=(x<<3)+(x<<1)+(oc&15),D);x*=ff;}
Ts I void read(Ty& x,Ar&... y) {read(x),read(y...);}
}using namespace FastIO;
I bool Check(Con LL& d,CI op=0)//验证
{
LL l=-INF,r=INF,la=-INF,ra=INF,lb=-INF,rb=INF,lc=-INF,rc=INF;
RI i;for(i=1;i<=n;++i)
l=max(l,x[i]+y[i]+z[i]-d),r=min(r,x[i]+y[i]+z[i]+d),//求X+Y+Z范围
la=max(la,x[i]+y[i]-z[i]-d),ra=min(ra,x[i]+y[i]-z[i]+d),//求X+Y-Z范围
lb=max(lb,x[i]+z[i]-y[i]-d),rb=min(rb,x[i]+z[i]-y[i]+d),//求X+Z-Y范围
lc=max(lc,y[i]+z[i]-x[i]-d),rc=min(rc,y[i]+z[i]-x[i]+d);//求Y+Z-X范围
LL A,B,C,L,R,LA,RA,LB,RB,LC,RC;for(i=0;i<=1;++i)//枚举A,B,C的奇偶性
{
L=l-3*i+1>>1,R=r-3*i>>1,LA=la-i+1>>1,RA=ra-i>>1,LB=lb-i+1>>1,RB=rb-i>>1,LC=lc-i+1>>1,RC=rc-i>>1;//求出新范围
if(L>R||LA>RA||LB>RB||LC>RC||LA+LB+LC>R||RA+RB+RC<L) continue;//如果存在值域为空或两值域区间无交则无解
(A=LA)+(B=LB)+(C=LC)<L&&(A+=min(RA-LA,R-A-B-C))+B+C<L&&A+(B+=min(RB-LB,R-A-B-C))+C<L&&(C+=min(RC-LC,R-A-B-C));//先全取最小值,依次往大调整
return op&&((A<<=1)|=i,(B<<=1)|=i,(C<<=1)|=i,printf("%lld %lld %lld\n",A+B>>1,A+C>>1,B+C>>1)),true;//还原A,B,C,输出构造方案
}return false;
}
int main()
{
RI Tt,i;LL l,r,mid;read(Tt);W(Tt--)
{
for(read(n),i=1;i<=n;++i) read(x[i],y[i],z[i]);
l=0,r=INF,mid;W(l^r) Check(mid=l+r-1>>1)?r=mid:l=mid+1;Check(r,1);//二分答案
}return 0;
}
标签:oid 二分答案 def eof target blank 枚举 fast dig
原文地址:https://www.cnblogs.com/chenxiaoran666/p/CF685C.html