5
10
2016
0

[BZOJ2177] 曼哈顿最小生成树

模版题

每个点只向每个象限里最近的点连边

离散化后树状数组维护就好了

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
using namespace std;
 
const long long N=50005,LIMIT=1000000000,INF=210000000000000ll;
 
long long n,f[N],Fir[10*N],Sec[10*N],cnt,Line[10*N],Num[10*N],tot,ans;
 
struct Point{
long long x,y,id;
friend bool operator<(Point A,Point B){return (A.x<B.x)|(A.x==B.x && A.y<B.y);}
}poi[N];
 
struct Edge{
long long x,y,len;
Edge(){}
Edge(long long sa,long long sb,long long sc){x=sa;y=sb;len=sc;}
friend bool operator<(Edge A,Edge B){return A.len<B.len;}
}e[20*N];
 
long long Find(long long x){return f[x]==x?x:f[x]=Find(f[x]);}
void Union(long long x,long long y){if(x>y)f[x]=y;else f[y]=x;}
long long lowbit(long long x){return x&(-x);}
void AddBIT(long long x,long long y,long long z){while(x){if(Fir[x]>y){Fir[x]=y;Sec[x]=z;}x-=lowbit(x);}}
long long QueBIT(long long x){long long Mx=LIMIT*2,Ex=0;while(x<=n){if(Mx>Fir[x]){Mx=Fir[x];Ex=Sec[x];}x+=lowbit(x);}return Ex;}
long long Abs(long long x){return x>0?x:-x;}
long long Dist(Point A,Point B){return Abs(A.y-B.y)+Abs(A.x-B.x);}
 
int main(){
freopen("2177.in","r",stdin);
freopen("2177.out","w",stdout);
scanf("%lld",&n);
for(long long i=1;i<=n;i++){scanf("%lld %lld",&poi[i].x,&poi[i].y);poi[i].id=i;}
for(long long i=1;i<=4;i++){
    if(i==3)for(long long i=1;i<=n;i++)poi[i].x=LIMIT-poi[i].x;
    if(i==2 || i==4)for(long long i=1;i<=n;i++)swap(poi[i].x,poi[i].y);
    sort(poi+1,poi+n+1);
    for(long long i=1;i<=n;i++)Line[i]=poi[i].y-poi[i].x;
    sort(Line+1,Line+n+1);
    for(long long i=1;i<=n;i++)Num[i]=lower_bound(Line+1,Line+n+1,poi[i].y-poi[i].x)-Line;
    for(long long i=1;i<=n;i++)Fir[i]=INF;
    for(long long i=n;i>=1;i--){
        long long Set=QueBIT(Num[i]);
        if(Set)e[++cnt]=Edge(poi[i].id,poi[Set].id,Dist(poi[i],poi[Set]));
        AddBIT(Num[i],poi[i].y+poi[i].x,i);
    }
}
sort(e+1,e+cnt+1);
for(long long i=1;i<=n;i++)f[i]=i;
for(long long i=1;i<=cnt && tot<n-1;i++){
    if(Find(e[i].x)!=Find(e[i].y)){
        tot++;
        Union(Find(e[i].x),Find(e[i].y));
        ans+=1ll*e[i].len;
    }
}
printf("%lld\n",ans);
return 0;
}
Category: BZOJ | Tags: OI bzoj | Read Count: 504

登录 *


loading captcha image...
(输入验证码)
or Ctrl+Enter

Host by is-Programmer.com | Power by Chito 1.3.3 beta | Theme: Aeros 2.0 by TheBuckmaker.com