题目链接:

[UOJ455]雪灾与外卖

题目描述:有$n$个送餐员(坐标为$x_{i}$)及$m$个餐厅(坐标为$y_{i}$,权值为$w_{i}$),每个送餐员需要前往一个餐厅,每个餐厅只能容纳$c_{i}$个送餐员,一个送餐员去一个餐厅的代价为$|x_{i}-y_{j}|+w_{j}$,求最小代价。

首先这个题可以暴力建图跑费用流,具体做法就不说了。现在我们考虑模拟费用流的过程,也就是模拟贪心及匹配中反悔的过程。

我们对送餐员和餐厅分别开一个小根堆然后从左往右决策每个坐标位置的人或餐厅的选择:

对于送餐员,先强制让他与左面的餐厅匹配(如果没有则看作和无限远处匹配),为了使代价最小,我们选择左面$w-y$最小的餐厅与他匹配,因为他还可能与右边的餐厅匹配,所以我们往送餐员的堆中加入一个当前送餐员的反悔操作,权值为$-(x-y+w)-x$(因为这个反悔操作只会匹配右边的餐厅,所以送餐员之后的权值为$-x$),这样如果之后选择这个反悔操作,就会将之前选择的代价抵消掉,并让这个送餐员产生新的代价。这也就是说送餐员的堆中存的都是反悔的送餐员。

对于餐厅,只要当前餐厅的权值$w+y$与送餐员的堆顶的权值之和小于$0$就说明这个堆顶的送餐员匹配当前餐厅比之前的选择更优,那么我们就让他匹配当前餐厅。这时候有两种情况:1、餐厅反悔,它要匹配它右边的送餐员,那么我们在餐厅的堆中加入权值为$-(v+w+y)+w-y$的反悔操作(其中$v$表示送餐员堆顶的权值,因为这个反悔操作只会匹配右边的送餐员,所以餐厅的权值为$w-y$)。2、送餐员反悔,他要匹配更右边的餐厅,这时就要在送餐员的堆中加入权值为$-w-y$的反悔操作来使下一次选到这个操作时抵消掉这次匹配的代价。

总的来说这道题就是在所有正常匹配和反悔操作中贪心寻找最优解来进行匹配。

最后说一下时间复杂度:因为对于送餐员向左匹配时只会反悔一次所以送餐员的反悔操作进堆次数是线性的。对于餐厅的操作,因为一个餐厅匹配左面的送餐员时送餐员的反悔操作权值都是$-y-w$,所以只需要记录一下匹配数量,统一入堆即可。每个反悔操作在被匹配后都会删除,而除了送餐员向左匹配的反悔操作之外,只会在枚举到每个餐厅时将一个权值入堆,所以总共能被匹配的送餐员反悔操作的数量是线性的。

#include<set>
#include<map>
#include<queue>
#include<stack>
#include<cmath>
#include<cstdio>
#include<vector>
#include<bitset>
#include<cstring>
#include<iostream>
#include<algorithm>
#define ll long long
using namespace std;
struct miku
{
ll sum;
ll num;
miku(){}
miku(ll SUM,ll NUM){sum=SUM,num=NUM;}
};
bool operator <(miku a,miku b){return a.sum>b.sum;}
priority_queue<miku>A,B;
ll x[100010];
ll y[100010];
ll w[100010];
ll c[100010];
int n,m;
ll ans;
void ins1(ll x)
{
ll v=B.top().sum;
int c=B.top().num;
B.pop();
ans+=x+v;
A.push(miku(-(x+v)-x,1));
if(c>1)
{
B.push(miku(v,c-1));
}
}
void ins2(ll y,ll w,int c)
{
int k=0;
while(!A.empty()&&k<c&&A.top().sum+w+y<0)
{
ll v=A.top().sum;
int s=A.top().num;
A.pop();
int g=min(s,c-k);
s-=g,k+=g,ans+=1ll*g*(v+w+y);
if(s)
{
A.push(miku(v,s));
}
B.push(miku(-(v+w+y)+w-y,g));
}
if(k)
{
A.push(miku(-y-w,k));
}
if(c-k)
{
B.push(miku(w-y,c-k));
}
}
int main()
{
scanf("%d%d",&n,&m);
ll tot=0;
for(int i=1;i<=n;i++)
{
scanf("%lld",&x[i]);
}
for(int i=1;i<=m;i++)
{
scanf("%lld%lld%lld",&y[i],&w[i],&c[i]);
tot+=c[i];
}
if(tot<n)
{
printf("-1");
return 0;
}
y[0]=-1ll<<60,c[0]=1<<30;
int i=1,j=0;
while(i<=n&&j<=m)
{
if(x[i]<=y[j])
{
ins1(x[i]);
i++;
}
else
{
ins2(y[j],w[j],c[j]);
j++;
}
}
while(i<=n)
{
ins1(x[i]);
i++;
}
while(j<=m)
{
ins2(y[j],w[j],c[j]);
j++;
}
printf("%lld",ans);
}

[UOJ455][UER #8]雪灾与外卖——堆+模拟费用流的更多相关文章

  1. BZOJ4977[Lydsy1708月赛]跳伞求生——贪心+堆+模拟费用流

    题目链接: 跳伞求生 可以将题目转化成数轴上有$n$个人和$m$个房子,坐标分别为$a_{i}$和$b_{i}$,每个人可以进一个他左边的房子,每个房子只能进一个人.每个房子有一个收益$c_{i}$, ...

  2. BZOJ4946[Noi2017]蔬菜——线段树+堆+模拟费用流

    题目链接: [Noi2017]蔬菜 题目大意:有$n$种蔬菜,每种蔬菜有$c_{i}$个,每种蔬菜每天有$x_{i}$个单位会坏掉(准确来说每天每种蔬菜坏掉的量是$x_{i}-$当天这种蔬菜卖出量), ...

  3. 模拟费用流 & 可撤销贪心

    1. CF730I Olympiad in Programming and Sports 大意: $n$个人, 第$i$个人编程能力$a_i$, 运动能力$b_i$, 要选出$p$个组成编程队, $s ...

  4. UOJ #455 [UER #8]雪灾与外卖 (贪心、模拟费用流)

    题目链接 http://uoj.ac/contest/47/problem/455 题解 模拟费用流,一个非常神奇的东西. 本题即为WC2019 laofu的讲课中的Problem 8,经典的老鼠进洞 ...

  5. 【bzoj1150】[CTSC2007]数据备份Backup 模拟费用流+链表+堆

    题目描述 你在一家 IT 公司为大型写字楼或办公楼(offices)的计算机数据做备份.然而数据备份的工作是枯燥乏味的,因此你想设计一个系统让不同的办公楼彼此之间互相备份,而你则坐在家中尽享计算机游戏 ...

  6. 【BZOJ3502/2288】PA2012 Tanie linie/【POJ Challenge】生日礼物 堆+链表(模拟费用流)

    [BZOJ3502]PA2012 Tanie linie Description n个数字,求不相交的总和最大的最多k个连续子序列. 1<= k<= N<= 1000000. Sam ...

  7. luogu P5470 [NOI2019]序列 dp 贪心 费用流 模拟费用流

    LINK:序列 考虑前20分 容易想到爆搜. 考虑dp 容易设\(f_{i,j,k,l}\)表示前i个位置 选了j对 且此时A选择了k个 B选择了l个的最大值.期望得分28. code //#incl ...

  8. 贪心(模拟费用流):NOIP2011 观光公交

    [问题描述] 风景迷人的小城Y 市,拥有n 个美丽的景点.由于慕名而来的游客越来越多,Y 市特意安排了一辆观光公交车,为游客提供更便捷的交通服务.观光公交车在第0 分钟出现在1号景点,随后依次前往2. ...

  9. BZOJ4849[Neerc2016]Mole Tunnels——模拟费用流+树形DP

    题目描述 鼹鼠们在底下开凿了n个洞,由n-1条隧道连接,对于任意的i>1,第i个洞都会和第i/2(取下整)个洞间有一条隧 道,第i个洞内还有ci个食物能供最多ci只鼹鼠吃.一共有m只鼹鼠,第i只 ...

随机推荐

  1. [LOJ#2386]. 「USACO 2018.01 Platinum」Cow at Large[点分治]

    题意 题目链接 分析 假设当前的根为 rt ,我们能够在奶牛到达 \(u\) 之时拦住它,当且仅当到叶子节点到 \(u\) 的最短距离 \(mn_u \le dis_u\) .容易发现,合法的区域是许 ...

  2. 一看就懂的Mybatis框架入门笔记

    本篇为初学Mybatis框架时的入门笔记,整理发出 Spring集成Mybatis https://www.cnblogs.com/yueshutong/p/9381590.html SpringBo ...

  3. HBase篇(1)-特性与应用场景

    [每日五分钟搞定大数据]系列,HBase第一篇 结束了Zookeeper篇, 接下来我们来说下Google三驾马车之一BigTable的开源实现:HBase,要讲的内容暂定如下: 这是第一篇我们先不聊 ...

  4. python-入门的第一个爬虫例子

    前言: 此文为大家入门爬虫来做一次简单的例子,让大家更直观的来了解爬虫. 本次我们利用 Requests 和正则表达式来抓取豆瓣电影的相关内容. 一.本次目标: 我们要提取出豆瓣电影-正在上映电影名称 ...

  5. [2018福大至诚软工助教]alpha阶段小结

    [2018福大至诚软工助教]alpha阶段小结 一.得分 1. 冲刺(7次 Scrum) 150分 1)第1篇(25分) 项目 评分标准 各个成员在 Alpha 阶段认领的任务 (6分)视详细程度给分 ...

  6. (Beta)团队贡献分

    Beta阶段团队每个成员都积极响应一起完成了开发, 所以最后我们一致决定各个成员的贡献分相同. 林珣玙 53 康家华 52 张启东 51 刘彦熙 49 马瑶华 48 仇栋民 47

  7. 将工程改造为SOA架构

    商城是基于soa的架构,表现层和服务层是不同的工程.所以要实现商品列表查询需要两个系统之间进行通信. 流动计算架构 当服务越来越多,容量的评估,小服务资源的浪费等问题逐渐显现,此时需增加一个调度中心基 ...

  8. AVAudioSesion和AVAudioPlayer的基本使用

    iOS基础篇-AVPLayer和AVAudioSession 2018.02.27 16:17 字数 215 阅读 1516评论 0喜欢 4 作用 AVPLayer:可以用来播放在线及本地音视频 AV ...

  9. Redis Sentinel 集群搭建常见注意事项

    我的配置: 1个master,1个slave,3个sentinel 搭建的过程网上已经有很多了,这里列几个重点关注: 修改sentinel.conf的protected-mode与redis.conf ...

  10. python模块详解

    什么是模块? 常见的场景:一个模块就是一个包含了python定义和声明的文件,文件名就是模块名字加上.py的后缀. 但其实import加载的模块分为四个通用类别: 1 使用python编写的代码(.p ...