【JZO5271】【GDOI2018模拟8.14】神奇的救火现场

来源:互联网 发布:淘宝比价插件哪个好 编辑:程序博客网 时间:2024/05/18 21:44

Description

这里写图片描述

Data Constraint

这里写图片描述

Solution

这和以前的jzoj上一道叫保持平衡的题很像啊。当然也有线性的做法,但我们这里只讲一下NlogN的做法。
我们维护两个小根堆分别为水栓和车的供给代价。每遇到一辆车,若水栓不为空,我们从水栓的堆中取出最小的代价x与其坐标相加后加入答案,并将坐标取反-代价加入车堆,若水栓为空,我们则将代价设为+∞重复刚才操作,表示以后若有水栓优先供应给这辆车。每遇到一个水栓,我们都在车里找一个最小答案,若最小答案小于0则加入答案并将坐标取反-代价加入水栓中。否则直接坐标取反加入即可。

Code

#include<iostream>#include<cmath>#include<cstring>#include<cstdio>#include<algorithm>#include<set>#define ll long longusing namespace std;const ll maxn=3e5+5,mo=0x7fffffff;multiset<ll>f,g;struct code{    ll x,bz;}a[maxn];ll n,m,i,t,j,k,l,x,y,z,ans;bool cmp(code x,code y){    return x.x<y.x;}int main(){    freopen("fire.in","r",stdin);freopen("fire.out","w",stdout);    scanf("%lld%lld",&m,&n);    for (i=1;i<=m;i++)scanf("%lld",&a[i].x);    for (i=1;i<=n;i++)scanf("%lld",&a[m+i].x),a[m+i].bz=1;    n+=m;    sort(a+1,a+n+1,cmp);    for (i=1;i<=n;i++)        if (a[i].bz){            if (!f.empty()){                x=*f.begin();                t=a[i].x+x;                ans+=t;                g.insert(-t-a[i].x);                f.erase(f.begin());            }else{                ans+=mo;                g.insert(-mo-a[i].x);            }        }else{            if (!g.empty()){                x=*g.begin();                if (x+a[i].x<0) g.erase(g.begin());                else x=-a[i].x;            }else x=-a[i].x;            t=a[i].x+x;            ans+=t;            f.insert(-t-a[i].x);        }    printf("%lld\n",ans);}
原创粉丝点击