【jzoj5043】【保持平衡】【数据结构】

来源:互联网 发布:淘宝直通车质量得分 编辑:程序博客网 时间:2024/06/04 19:56

题目大意

博爱路上种起了一棵棵的大树,但是有一些地方的树超过了负荷,有一些地方的树的数量又不够。

我们不妨把博爱路看做一条数轴,数轴有n个点,从1到n编号,第i个位置原来现在有ai棵树,这个位置的需求是bi棵树。ai,bi都是0到10的整数。由于你需要是这个位置的树的数量保持平衡,所以你需要移除或者搬一些树过来。

我们怎么使树的数量平衡呢?

首先,你可以从某个位置i移动一棵树到位置j,这时,你需要的运费是|i-j|*z元。

其次,你可以从商店买一棵树,需要支付x元,这时商店会把树配送到任意位置。

还有就是,你可以叫别人收购在任意位置一棵树,需要支付y元运费。

问使得树的数量平衡最小需要支付多少钱?

解题思路

考虑往右移移的情况,要运走的点,可以花y的费用运走,为了将来可以反悔,我们把-花费-i*z扔进noneed的小根堆。到了需求的点我们可以查询noneed看是否反悔,花费为最小值加i*z。

考虑左移的情况,只需在去最优值的时候相反地考虑即可。

code

#include<set>#include<cmath>#include<cstdio>#include<cstring>#include<algorithm>#define LF double#define LL long long#define min(a,b) ((a<b)?a:b)#define max(a,b) ((a>b)?a:b)#define fo(i,j,k) for(int i=j;i<=k;i++)#define fd(i,j,k) for(int i=j;i>=k;i--)#define fr(i,j) for(int i=begin[j];i;i=next[i])using namespace std;int const Mxn=2*1e5+9,Mxm=16*1e5+9,Inf=1e9;int n,x,y,z;multiset<LL>need,noneed;int main(){    freopen("balance.in","r",stdin);    freopen("balance.out","w",stdout);    scanf("%d%d%d%d",&n,&x,&y,&z);    int ai,bi;LL ans=0,tmp;    fo(i,1,n){        scanf("%d%d",&ai,&bi);        if(ai<bi){            ai=bi-ai;            fo(j,1,ai){                if(!noneed.empty()){                    tmp=(*noneed.begin())+z*i;                    if(tmp<x)noneed.erase(noneed.begin());                    else tmp=x;                }else tmp=x;                ans+=tmp;                need.insert(-i*z-tmp);            }        }        if(ai>bi){            ai-=bi;            fo(j,1,ai){                if(!need.empty()){                    tmp=(*need.begin())+z*i;                    if(tmp<y)need.erase(need.begin());                    else tmp=y;                }else tmp=y;                ans+=tmp;                noneed.insert(-i*z-tmp);            }        }    }    printf("%lld",ans);    return 0;}
0 0
原创粉丝点击