• 【题解】[CJOI2019Chebnear]


    【题解】[CJOI2019Chebnear]

    题目描述

    给定平面上有(n)个仇人,((x,y) ,x,y in R^+)(n)个人都是仇人关系,而有仇人关系的一对人的切比雪夫距离若(le k)则会发生“吵架”。可是,对于有些仇人(i)(j),先记为三元组(P(t,i,w)),他们的的仇人关系并不深,假设给全体(n)个人每人(ge w)的钱他们就变为朋友了。而朋友不会吵架,而且朋友的朋友也是你的朋友。

    现在问你,你最少给多少钱(w)可是让所有人不吵架?

    数据范围

    (nle100000,mle100000)

    说明

    切比雪夫距离:(d=max(|x_i-x_j|,|y_i-y_j|))

    (Solution)

    显然二分答案(w)。接下来的任务就是当给每个人(w)钱的时候,是否有人吵架了。

    然后(O(m))枚举那些朋友可以连接,直接用并查集维护朋友关系。

    考虑暴力。

    • (O(n^2))枚举每个点对,看他们是否吵架。这样显然超时。

    我们仔细思考一下,发现吵架只和以下两个因素有关。

    • (y)安全但(x)距离过近。
    • (x)安全但(y)距离过近。
    • 朋友

    朋友关系已经用并查集维护了,可以(O(alpha(n))=O(1))查询。接下来就是(x,y)的问题了。
    考虑把所有点按(x)排序。这样我们就可以快速确定一段区间内的人是否有可能(x)过近,然后对于这些点(O(n_?^2))枚举是否会吵架就好了。

    但是怎么缩小(n_?)呢?

    对于平面最近点对问题,可以证明(n_? le 6)。这里我们也可以类比,每次和最近点对一样,直接从中间分开,分治。我们的(n_?)一定比最近点对的(n_?)还要小,因为我们还有(k)的限制呀,帮助我们剪枝。

    接下来上代码了,今天的代码是不是码风很棒?

    #include<bits/stdc++.h>
    
    #define RP(t,a,b) for(register int (t)=(a),edd_=(b);t<=edd_;++t)
    #define DRP(t,a,b) for(register int (t)=(a),edd_=(b);t>=edd_;--t)
    #define ERP(t,a) for(int t=head[a];t;t=e[t].nx)
    #define pushup(x) seg[(x)]=seg[(x)<<1]+seg[(x)<<1|1]
    #define midd register int mid=(l+r)>>1
    #define TMP template<class ccf>
    #define rgt L,R,mid,r,pos<<1|1
    #define lef L,R,l,mid,pos<<1
    #define all 1,n,1
    
    using namespace std;typedef long long ll;
    TMP inline ccf Max(ccf a,ccf b){return a<b?b:a;}
    TMP inline ccf Min(ccf a,ccf b){return a<b?a:b;}
    TMP inline ccf Abs(ccf a){return a<0?-a:a;}
    TMP inline ccf qr(ccf k){
        char c=getchar();ccf x=0;int q=1;
        while(c<48||c>57)q=c==45?-1:q,c=getchar();
        while(c>=48&&c<=57)x=x*10+c-48,c=getchar();
        return q==-1?-x:x;}
    //-----------------template&IO------------------
    int n,m;double k;
    const int maxn=1e5+5;
    struct node{
        double x,y;int id;
        inline bool operator <(node a){return x<a.x;}
        inline double operator -(node a){return Max(Abs(x-a.x),Abs(y-a.y));}
    }data[maxn];
    struct E{
        int fr,to;double w;
        inline bool operator <(E a){return w<a.w;}
    }e[maxn<<1];
    int rr[maxn];
    inline int q(int x){register int t=x,temp,i=x;
        while(rr[t]!=t) t=rr[t];
        while(rr[i]!=i) temp=rr[i],rr[i]=t,i=temp;
        return t;
    }
    inline void j(int x,int y){rr[q(x)]=q(y);}
    inline bool in(int x,int y){return q(x)==q(y);}
    struct DFN{
        double pos;int id;
        inline bool operator <(DFN x){return pos<x.pos;}
    }dfn[maxn];
    
    bool divd(int lb,int rb){register int mid=(lb+rb)>>1;
        if(lb>=rb) return 1;
        if(!divd(lb,mid))   return 0;
        if(!divd(mid+1,rb)) return 0;
        register int L=mid,R=mid;
        while(data[mid].x-data[L-1].x<=k&&L>lb) --L;
        while(data[R+1].x-data[mid].x<=k&&R<rb) ++R;
        RP(t,L,R)RP(i,t+1,R)
    	if(!in(data[t].id,data[i].id)&&data[t]-data[i]<=k)
    	    return 0;
        return 1;
    }
    
    inline bool chek(double x){
        RP(t,1,n) rr[t]=t;
        RP(t,1,m) if(x>=e[t].w) j(e[t].fr,e[t].to);
        return divd(1,n);
    }
    
    int main(){
    #ifndef ONLINE_JUDGE
        freopen("chebnear.in","r",stdin);
        freopen("chebnear.out","w",stdout);
    #endif
        cin>>n>>m>>k;
        RP(t,1,n)
    	cin>>data[t].x>>data[t].y,data[t].id=t;
        RP(t,1,m)
    	cin>>e[t].fr>>e[t].to>>e[t].w;
        sort(data+1,data+n+1);
        sort(e+1,e+m+1);
        int l=1,r=m,ans=m;
        do{
    	midd;
    	if(chek(e[mid].w))
    	    r=mid-1,ans=Min(ans,mid);
    	else
    	    l=mid+1;
        }while(l<=r);
        if(chek(0)) ans=0;
        printf("%.3lf
    ",e[ans].w);
        return 0;
    }
    
    
    
  • 相关阅读:
    [转] 程序集和Dll的区别
    [转载] 节选自:2005年件我的第一次软件行业创业,烧掉30万、2年时间打水漂的惨痛教训总结
    [分享]屏幕取色工具
    LINQ学习笔记
    XP系统 mscorsvw.exe进程 占CPU资源 开机加载网络连接很慢 解决方法
    [原创] ASP.NET中事件执行顺序
    CHARINDEX, INSTR
    [转载]如何为自己的网站设置二级域名?
    [转载] System.Threading.Timer类的TimerCallback 委托
    [转载]ASP.NET 2.0 页面事件执行顺序
  • 原文地址:https://www.cnblogs.com/winlere/p/10359579.html
Copyright © 2020-2023  润新知