BZOJ4071: [Apio2015]巴邻旁之桥

来源:互联网 发布:js json 添加元素 编辑:程序博客网 时间:2024/05/16 09:49

首先对于家和公司在同一侧的预处理掉,这样就只剩家和公司不在同一侧的情况了。
if(K==1)ans=∑abs(x-pos)+abs(y-pos);注意到与x,y是否在两侧无关,所以用经典的中位数处理思想sort一遍取中位数贪心即可。
else{
一个人要走的距离是abs(x-pos)+abs(y-pos),让它最短话句话说就是让中点距pos尽可能近,于是我们将所有区间按中点排序,枚举从哪个重中点分成两块,左面走左面的桥右面走右面的桥,平衡树或者权值线段树动态维护中位数即可。
}
好久不写splay,练习了一发…>_<…

#include<cstdio>#include<cstring>#include<iostream>#include<algorithm>#define ll long long//by:MirrorGrayusing namespace std;const int N=211111,inf=0x3f3f3f3f;struct node{    int x,y;    node(int a=0,int b=0){        x=a;y=b;    }    bool operator <(const node&b)const{        return x+y<b.x+b.y;    }}a[N];struct Splay{    int cnt,root;    struct splay{int l,r,fa,gs,size,d;ll sum;}sp[N];    void up(int tr){        sp[tr].size=sp[tr].gs;        sp[tr].sum=(ll)sp[tr].d*sp[tr].gs;        sp[tr].size+=sp[sp[tr].l].size+sp[sp[tr].r].size;        sp[tr].sum+=sp[sp[tr].l].sum+sp[sp[tr].r].sum;    }    Splay(){        cnt=2;root=1;        sp[1].d=-inf,sp[2].d=inf;        sp[1].r=2;sp[2].fa=1;        sp[1].gs=sp[2].gs=1;        up(2);up(1);    }    void zig(int tr){        int y=sp[tr].fa;        sp[y].l=sp[tr].r;        if(sp[tr].r)sp[sp[tr].r].fa=y;        sp[tr].fa=sp[y].fa;        if(sp[y].fa){            if(sp[sp[y].fa].l==y)sp[sp[y].fa].l=tr;            else sp[sp[y].fa].r=tr;        }        sp[y].fa=tr;sp[tr].r=y;        up(y);    }    void zag(int tr){        int y=sp[tr].fa;        sp[y].r=sp[tr].l;        if(sp[tr].l)sp[sp[tr].l].fa=y;        sp[tr].fa=sp[y].fa;        if(sp[y].fa){            if(sp[sp[y].fa].l==y)sp[sp[y].fa].l=tr;            else sp[sp[y].fa].r=tr;        }        sp[y].fa=tr;sp[tr].l=y;        up(y);    }    void splay(int tr,int aim){        while(sp[tr].fa!=aim){            int y=sp[tr].fa;            if(sp[y].fa==aim){                if(sp[y].l==tr)zig(tr);                else zag(tr);            }            else{                if(sp[sp[y].fa].l==y){                    if(sp[y].l==tr)zig(y),zig(tr);                    else zag(tr),zig(tr);                }                else{                    if(sp[y].l==tr)zig(tr),zag(tr);                    else zag(y),zag(tr);                }            }        }        up(tr);if(!aim)root=tr;    }    int pre(int tr,int d,int ret){        if(!tr)return ret;        if(sp[tr].d<d)return pre(sp[tr].r,d,tr);        else return pre(sp[tr].l,d,ret);    }    int nxt(int tr,int d,int ret){        if(!tr)return ret;        if(sp[tr].d>=d)return nxt(sp[tr].l,d,tr);        else return nxt(sp[tr].r,d,ret);    }    int kth(int tr,int k){        if(sp[sp[tr].l].size>=k)return kth(sp[tr].l,k);        if(sp[sp[tr].l].size+sp[tr].gs>=k)return tr;        return kth(sp[tr].r,k-(sp[sp[tr].l].size+sp[tr].gs));    }    void insert(int d){        int t1=pre(root,d,-1);splay(t1,0);        int t2=nxt(root,d,-1);splay(t2,t1);        if(sp[t2].d==d){            sp[t2].gs++;            up(t2);up(t1);            return ;        }        sp[t2].l=++cnt;        sp[cnt].d=d;sp[cnt].fa=t2;sp[cnt].gs=1;        up(cnt);up(t2);up(t1);    }    void del(int d){        int t1=pre(root,d,-1);splay(t1,0);        int t2=nxt(root,d+1,-1);splay(t2,t1);        int tr=sp[t2].l;        if(sp[tr].gs>1){            sp[tr].gs--;            up(tr);up(t2);up(t1);            return ;        }        sp[t2].l=0;        up(t2);up(t1);    }    ll Q(){        ll ret=0;        int tr=kth(root,sp[root].size>>1);        splay(tr,0);int l=sp[tr].l,r=sp[tr].r;//      cout<<"size : "<<sp[root].size<<" "<<sp[root].sum<<" "<<sp[root].d<<endl;//      cout<<sp[l].size<<" "<<sp[l].sum+inf<<endl;//      cout<<sp[r].size<<" "<<sp[r].sum-inf<<endl;        ret+=(ll)sp[l].size*sp[root].d-sp[l].sum;        ret+=sp[r].sum-(ll)sp[r].size*sp[root].d;        ret-=inf<<1;        return ret;    }}t1,t2;int main(){    int k,n;scanf("%d%d",&k,&n);    ll ans=0;int cnt=0;    for(int i=1;i<=n;i++){        char s1[2],s2[2];int b,c;        scanf("%s%d%s%d",s1,&b,s2,&c);        if(s1[0]==s2[0])ans+=abs(b-c);        else a[++cnt]=node(b,c),t2.insert(b),t2.insert(c);    }    ans+=cnt;    if(k==1)return printf("%lld\n",ans+t2.Q());    else{        sort(a+1,a+1+cnt);        ll tmp=t1.Q()+t2.Q();        for(int i=1;i<=cnt;i++){            t1.insert(a[i].x);t1.insert(a[i].y);            t2.del(a[i].x);t2.del(a[i].y);            tmp=min(tmp,t1.Q()+t2.Q());        }        printf("%lld\n",ans+tmp);    }    return 0;}
0 0