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); }
河田は河田、赤木は赤木……。
私は誰ですか。教えてください、私は誰ですか。
そうだ、俺はあきらめない男、三井寿だ!