BZOJ 2177 最小曼哈顿生成树

来源:互联网 发布:java中常用io流类 编辑:程序博客网 时间:2024/05/01 01:34

留板。

#include <bits/stdc++.h>using namespace std;typedef pair<int,int> pii;const int maxn=100005;const long long inf=0x3f3f3f3f3f3f3f3f;int n,pos[maxn],f[maxn];long long bit[maxn],res,x,y;struct edge {    int u,v;    long long w;    edge(){}    edge(int u,int v,int w):u(u),v(v),w(w){}    bool operator<(const edge &rhs)const{        return w<rhs.w;    }};vector<edge> v;vector<long long> ID;inline void init() {    for (int i=0;i<n;++i)        f[i]=i;}int F(int x) {    return x==f[x]?x:f[x]=F(f[x]);}inline void U(int x,int y) {    f[F(x)]=F(y);}inline void update(int x,long long v,int p) {    while (x) {        if (bit[x]>v) {            bit[x]=v;            pos[x]=p;        }        x-=x&-x;    }}inline int query(int x) {    long long val=inf;    int ret=-1;    while (x<=n) {        if (bit[x]<val) {            val=bit[x];            ret=pos[x];        }        x+=x&-x;    }    return ret;}struct P {    long long x,y;    int id;    P(){}    P(long long x,long long y,int id):x(x),y(y),id(id){}    bool operator<(const P &rhs)const{        return x==rhs.x?y<rhs.y:x<rhs.x;    }} p[maxn];inline long long manh(int i,int j) {    return abs(p[i].x-p[j].x)+abs(p[i].y-p[j].y);}inline void discrete() {    ID.clear();    for (int i=0;i<n;++i)        ID.push_back(p[i].y-p[i].x);    sort(ID.begin(),ID.end());    ID.erase(unique(ID.begin(),ID.end()),ID.end());}inline int id(int x) {    return lower_bound(ID.begin(),ID.end(),x)-ID.begin()+1;}inline void solve() {    sort(p,p+n);    discrete();    memset(bit,0x3f,sizeof bit);    memset(pos,-1,sizeof pos);    for (int i=n-1;i>=0;--i) {        int o=id(p[i].y-p[i].x);        int t=query(o);        if (t!=-1)            v.push_back(edge(p[i].id,p[t].id,manh(i,t)));        update(o,p[i].x+p[i].y,i);    }}inline void build() {    for (int i=0;i<4;++i) {        if (i==1||i==3)            for (int j=0;j<n;++j)                swap(p[j].x,p[j].y);        if (i==2)            for (int j=0;j<n;++j)                p[j].x=-p[j].x;        solve();    }}inline void kruskal() {    init();    sort(v.begin(),v.end());    res=0;    for (int i=0;i<(int)v.size();++i)        if (F(v[i].u)!=F(v[i].v)) {            U(v[i].u,v[i].v);            res+=v[i].w;        }    cout<<res<<endl;}int main(){    scanf("%d",&n);    for (int i=0;i<n;++i) {        cin>>x>>y;        p[i]=P(x,y,i);    }    build();    kruskal();    return 0;}

原创粉丝点击