[ 杂题 ] Codeforces685C Optimal Point

二分答案,对于每个点求出满足的区域,求出这些区域的交。一个区域可以表示成:

...x+y+z... . . . ≤ x + y + z ≤ . . .

...x+yz... . . . ≤ x + y − z ≤ . . .

...xy+z... . . . ≤ x − y + z ≤ . . .

...x+y+z... . . . ≤ − x + y + z ≤ . . .

a=x+yz,b=xy+z,c=x+y+z a = x + y − z , b = x − y + z , c = − x + y + z ,则
a+b+c=x+y+z a + b + c = x + y + z

x=a+b2 x = a + b 2

y=a+c2 y = a + c 2

z=b+c2 z = b + c 2

所以 a,b,c a , b , c 的奇偶性必须相同。然后将 a,b,c a , b , c 增大,使其满足第一个条件就好了。

#include<bits/stdc++.h>
using namespace std;
inline char nc(){
    static char buf[1000000],*p1=buf,*p2=buf;
    return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
}
inline void Read(int& x){
    char c=nc(),b=1;
    for(;c<'0'||c>'9';c=nc())if(c=='-')b=-1;
    for(x=0;c>='0'&&c<='9';x=(x<<3)+(x<<1)+c-48,c=nc());x*=b;
}
typedef long long ll;
inline void Read(ll& x){
    char c=nc(),b=1;
    for(;c<'0'||c>'9';c=nc())if(c=='-')b=-1;
    for(x=0;c>='0'&&c<='9';x=(x<<3)+(x<<1)+c-48,c=nc());x*=b;
}
const int N=100010;
int T;
int k,n,m;
ll a[N],b[N],c[N];
ll Ans1,Ans2,Ans3;
ll L[4],R[4];
inline bool Check(ll x){
    for(int i=0;i<4;i++)L[i]=-9e18,R[i]=9e18;
    for(int i=1;i<=n;i++){
        ll A=a[i],B=b[i],C=c[i];
        L[0]=max(L[0],A+B+C-x);R[0]=min(R[0],A+B+C+x);
        L[1]=max(L[1],A+B-C-x);R[1]=min(R[1],A+B-C+x);
        L[2]=max(L[2],A-B+C-x);R[2]=min(R[2],A-B+C+x);
        L[3]=max(L[3],-A+B+C-x);R[3]=min(R[3],-A+B+C+x);
    }
    for(int d=0;d<2;d++){
        ll a=L[1],b=L[2],c=L[3],e=L[0],A=R[1],B=R[2],C=R[3],E=R[0];
        if((a&1)!=d)a++;if((A&1)!=d)A--;
        if((b&1)!=d)b++;if((B&1)!=d)B--;
        if((c&1)!=d)c++;if((C&1)!=d)C--;
        if((e&1)!=d)e++;if((E&1)!=d)E--;
        if(a>A||b>B||c>C||e>E||a+b+c>E||A+B+C<e)continue;
        ll cur=max(e-a-b-c,0ll),t;
        t=min(cur,A-a);
        a+=t;cur-=t;
        t=min(cur,B-b);
        b+=t;cur-=t;
        t=min(cur,C-c);
        c+=t;cur-=t;
        if(cur)continue;
        Ans1=(a+b)/2;Ans2=(a+c)/2;Ans3=(b+c)/2;
        return 1;
    }
    return 0;
}
int main(){
    Read(T);
    while(T--){
        Read(n);
        for(int i=1;i<=n;i++)Read(a[i]),Read(b[i]),Read(c[i]);
        ll l=0,r=3e18;
        while(l<=r){
            ll Mid=l+r>>1;
            if(Check(Mid))r=Mid-1;else l=Mid+1;
        }
        printf("%I64d %I64d %I64d\n",Ans1,Ans2,Ans3);
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值