#455. 【UER #8】雪灾与外卖

题目

先按左边排,考虑一个人/店不是匹配左边的(主动)就是让右边的匹配他(被动)

定义 v 为堆顶(小根堆),至于是人堆还是店堆按具体情况。

一个人匹配某家店

匹配左边: x+v,那么 v=wy。这里显然是店堆。

匹配右边:反悔,(x+v)x 插入人堆。具体为什么插入这个东西下面会提到。

店匹配人(也就是人匹配右边的店,假如花费大于0,那么一定不优于让人匹配左边)

匹配左边:w+y+v 的形式,那么实际上就是要 v=x ,至于 (x+v) 是为了撤销匹配左边的贡献。

匹配右边:(w+y+v)y+w 因为考虑人匹配左边的店是 x+v,那么撤销这次店的匹配就是 (w+y+v),实际上 x+v=xy+w

但假如是店2匹配店1所匹配的人呢? 即可能相邻2个店。我们考虑将店1当人看。

y1,w1,y2,w2,v

那么店1匹配的人就是 w1+y1+v,那假如让店2替代,还需要花费 (w2+y2+v)(w1+y1+v)=w1+y1w2y2,对照下店匹配人的式子,y+w+v,则v=y2w2,即往人堆插入 yw 即可。

#include <cstdio> #include <algorithm> #include <iostream> #include <cstring> #include <vector> #include <cmath> #include <queue> #include <map> #define ll long long using namespace std; int rd() { int f=1,sum=0; char ch=getchar(); while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();} while(isdigit(ch)) {sum=(sum<<3)+(sum<<1)+ch-'0';ch=getchar();} return sum*f; } ll lrd() { ll f=1,sum=0; char ch=getchar(); while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();} while(isdigit(ch)) {sum=(sum<<3)+(sum<<1)+ch-'0';ch=getchar();} return sum*f; } const int N=(int)(1e5+5); struct node { mutable ll v,tot; bool operator < (const node &x) const { return v>x.v; } bool operator > (const node &x) const { return v<x.v; } }; #define min(X,Y) (X>Y?Y:X) const ll inf=0x7fffffff; priority_queue<node>q1,q2; ll ans; int X[N],Y[N],W[N],C[N],n,m; void ins1(int id) { ll qwq=inf; if(!q2.empty()) { node x=q2.top(); qwq=X[id]+q2.top().v; if(!(--q2.top().tot)) q2.pop(); } ans+=qwq; q1.push((node){-qwq-X[id],1}); } void ins2(int id) { int tot=0; ll res=0; while(!q1.empty()&&tot<C[id]) { ll qwq=q1.top().v+W[id]+Y[id]; if(qwq>=0) break; int cnt=min(q1.top().tot,C[id]-tot); ans+=qwq*cnt; tot+=cnt; q2.push((node){-qwq-Y[id]+W[id],cnt}); if(!(q1.top().tot-=cnt)) q1.pop(); } if(tot) q1.push((node){-Y[id]-W[id],tot}); if(C[id]-tot) q2.push((node){-Y[id]+W[id],C[id]-tot}); } int main() { n=rd(); m=rd(); ll qwq=0; for(int i=1;i<=n;i++) X[i]=rd(); for(int i=1;i<=m;i++) Y[i]=rd(),W[i]=rd(),C[i]=rd(),qwq+=C[i]; if(qwq<n) { puts("-1"); return 0; } int j=1; for(int i=1;i<=m;i++) { while(j<=n&&X[j]<=Y[i]) ins1(j++); ins2(i); } while(j<=n) ins1(j++); printf("%lld",ans); return 0; }

 


__EOF__

本文作者F x o r G
本文链接https://www.cnblogs.com/xugangfan/p/15129852.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   FxorG  阅读(324)  评论(0编辑  收藏  举报
编辑推荐:
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
阅读排行:
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效
点击右上角即可分享
微信分享提示