P2209 [USACO13OPEN]燃油经济性Fuel Economy

题面

sol:(思想):开一个大根堆和一个小根堆,每次计算到下了一个加油站用掉的油时尽量用小根堆中的元素,且同时删去大根堆中的相应位置的元素,当前加油站如果足够便宜,就可以把大根堆中的元素替换掉;

(实现):显然不可以开两个堆,因为删除是瓶颈,就可以用一下双端队列,右小左大,用油是从右边弹出,更新时从左边开始弹出

#include <queue>
#include <cstdio>
#include <algorithm>
using namespace std;
const long long N=50005;
long long n,G,B,D;
struct node{long long x,y;}a[N];
inline bool cmp(node a,node b){return a.x!=b.x?a.x<b.x:a.y<b.y;}
struct oll{long long num,w;};
deque<oll>q;
signed main()
{
    long long i,ny,np,re=0LL; oll tmp;
    scanf("%lld%lld%lld%lld",&n,&G,&B,&D);
    for(i=1;i<=n;i++)
    {
        scanf("%lld%lld",&a[i].x,&a[i].y);
    }sort(a+1,a+n+1,cmp);
    if(a[1].x>B||D-a[n].x>G)return 0*printf("-1\n");
    for(i=2;i<=n;i++)if(a[i].x-a[i-1].x>G)return 0*printf("-1\n");
    if(B>=D)return 0*printf("0\n"); if(a[n].x==D)a[n].y=0; else a[++n].x=D;
    a[n].y=0; ny=B; q.push_back((oll){B,0});
    for(i=1;i<=n;i++)
    {
        long long dd=a[i].x-a[i-1].x;
        while(!q.empty()&&dd>0)
        {
            tmp=q.front(); q.pop_front();
            if(tmp.num>dd)
            {
                ny-=dd; q.push_front((oll){tmp.num-dd,tmp.w}); break;
            }dd-=tmp.num; ny-=tmp.num;
        }
        if(i==n)
        {
            while(!q.empty())
            {
                re=re-1LL*q.front().num*q.front().w; q.pop_front();
            }break;
        }
        while(!q.empty()&&q.back().w>a[i].y)
        {
            re-=q.back().num*q.back().w; ny-=q.back().num; q.pop_back();
        }q.push_back((oll){G-ny,a[i].y}); re=(long long)re+1LL*(G-ny)*a[i].y; ny=G;
    }printf("%lld\n",re);
}

猜你喜欢

转载自www.cnblogs.com/gaojunonly1/p/9692997.html