2023 杭电多校(“钉耙编程”中国大学生算法设计超级联赛3)T9 题解

抢了个一血。不懂啊,这么傻逼的题居然没有人在 52 min ⁡ 52 \min 52min 内切(我如果小细节不写挂就十分钟切了)。

题目描述

给你若干个三元组 ( a i , b i , c i ) (a_i,b_i,c_i) (ai,bi,ci) ( a i ′ , b i ′ , c i ′ ) (a_i',b_i',c_i') (ai,bi,ci)

你可以从 ( a i , b i , c i ) (a_i,b_i,c_i) (ai,bi,ci) ( a i ′ , b i ′ , c i ′ ) (a_i',b_i',c_i') (ai,bi,ci) 中选择一个三元组作为第 i i i 个三元组( a i ′ ≥ a i , b i ′ ≥ b i , c i ′ ≥ c i a_i' \ge a_i,b_i' \ge b_i,c_i' \ge c_i aiai,bibi,cici)。

设你最后选择的三元组是 ( A i , B i , C i ) (A_i,B_i,C_i) (Ai,Bi,Ci)

那么这种方案的权值就是 max ⁡ ( max ⁡ A i − min ⁡ A i , max ⁡ B i − min ⁡ B i , max ⁡ C i − min ⁡ C i ) \max(\max A_i-\min A_i,\max B_i - \min B_i,\max C_i- \min C_i) max(maxAiminAi,maxBiminBi,maxCiminCi)

你需要找出一种方案,使得权值最小,并输出最小权值。

思路

看到最大值最小,直接二分。

考虑如何 c h e c k \rm check check

我们把 ( a i , b i , c i ) (a_i,b_i,c_i) (ai,bi,ci) ( a i ′ , b i ′ , c i ′ ) (a_i',b_i',c_i') (ai,bi,ci) 并成一个六元组 ( a i , b i , c i , a i ′ , b i ′ , c i ′ ) (a_i,b_i,c_i,a_i',b_i',c_i') (ai,bi,ci,ai,bi,ci),先钦定所有三元组都选 ( a i , b i , c i ) (a_i,b_i,c_i) (ai,bi,ci)

搞三个数组: x , y , z x,y,z x,y,z,分别表示这个六元组按 a i a_i ai 排序,按 b i b_i bi 排序,按 c i c_i ci 排序后的结果。

不难发现需要换成 ( a i ′ , b i ′ , c i ′ ) (a_i',b_i',c_i') (ai,bi,ci) 的三元组一定是 x , y , z x,y,z x,y,z 的一段前缀。

三个指针扫一遍即可。

注意需要判断前面三元组换了之后还是不满足条件的情况。

时间复杂度 O ( n log ⁡ n ) \mathcal O(n \log n) O(nlogn)

代码

//A tree without skin will surely die.
//A man without face is invincible.
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define sqr(x) ((x)*(x))
#define all(x) (x).begin(),(x).end()
#define Tim ((double)clock()/CLOCKS_PER_SEC)
#define mid ((l+r)>>1)
#define lowbit(x) (x&-x)
int const N=1e5+10;
int n,nwx,nwy,nwz,ix,iy,iz,qza,qzb,qzc;
struct node{int a,b,c,d,e,f;}a[N],b[N],c[N];
void push(node x){
    nwx=max(nwx,x.d),nwy=max(nwy,x.e),nwz=max(nwz,x.f);
    qza=min(qza,x.d),qzb=min(qzb,x.e),qzc=min(qzc,x.f);
}
bool check(int V){
    nwx=a[n].a,nwy=b[n].b,nwz=c[n].c,ix=1,iy=1,iz=1,qza=1e9,qzb=1e9,qzc=1e9;
    while (1){
        if (nwx-a[ix].a<=V && nwy-b[iy].b<=V && nwz-c[iz].c<=V && nwx-qza<=V && nwy-qzb<=V && nwz-qzc<=V) return 1;
        while (ix<=n && nwx-a[ix].a>V){push(a[ix]),++ix;if (nwx-qza>V || nwy-qzb>V || nwz-qzc>V) return 0;}
        while (iy<=n && nwy-b[iy].b>V){push(b[iy]),++iy;if (nwx-qza>V || nwy-qzb>V || nwz-qzc>V) return 0;}
        while (iz<=n && nwz-c[iz].c>V){push(c[iz]),++iz;if (nwx-qza>V || nwy-qzb>V || nwz-qzc>V) return 0;}
        if (nwx-qza>V || nwy-qzb>V || nwz-qzc>V) return 0;
    }
    return 1;
}
void solve(){
    cin>>n;
    for (int i=1;i<=n;++i) cin>>a[i].a>>a[i].b>>a[i].c>>a[i].d>>a[i].e>>a[i].f;
    for (int i=1;i<=n;++i) b[i]=a[i],c[i]=a[i];
    sort(a+1,a+n+1,[](node x,node y){return x.a<y.a;});
    sort(b+1,b+n+1,[](node x,node y){return x.b<y.b;});
    sort(c+1,c+n+1,[](node x,node y){return x.c<y.c;});
    int l=0,r=1e9;
    while (l<r)
        if (check(mid)) r=mid;
        else l=mid+1;
    cout<<l<<'\n';
}
signed main(){
    ios::sync_with_stdio(false);
    cin.tie(0),cout.tie(0);
    int t=1;
    cin>>t;
    while (t--) solve();
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值