Problem

\(\mathrm{UOJ~455}\)

题意概要:一根数轴上有 \(n\) 只老鼠与 \(m\) 个洞,每个洞有费用与容量限制,要求每只老鼠要进一个洞且每个洞的老鼠不超过自身的容量限制,定义一种方案的费用为所有老鼠移动距离之和加上所有老鼠进的洞费用之和(若一个洞进了 \(k\) 只老鼠,则费用需要计算 \(k\) 次)

\(n,m\leq 10^5\)

Solution

冬令营时掉线了,只记得这题被大家把好评刷上去了

这题是所谓模拟费用流问题。我理解的模拟费用流其实等价于处理“反悔”也即反向弧,因为费用流问题是使用 最短路(贪心) 加 反向弧(反悔) 解决的,所以利用该种思想,在平时题目中,若贪心有瑕疵,可以考虑维护后悔操作。相似的题有bzoj4977跳伞逃生

将所有老鼠和洞按照坐标排序先

bzoj4977相当于这题中老鼠只能往左走,即只能往前匹配,这样可以从左往右维护一个堆解决贪心。

而这题中老鼠和洞都可能往右匹配,但是依照上述“贪心+后悔”的思想,考虑先让老鼠和洞往左匹配。

维护老鼠和洞两个堆,分别设为 \(A,B\);明确老鼠进洞的代价是两个坐标中靠右的减去靠左的。

下面开始讨论:

若当前为老鼠,且其坐标为 \(x\),若从 \(B\) 中取得的最优解为 \(v\),则对答案贡献 \(x+v\)。这样的话只考虑了向左的匹配,但实际有可能向右匹配(反悔),考虑将这次匹配的贡献消除,且将此点设定为左端,则需向 \(A\) 中加入 \(-(v+x)-x\)(前者将当前贡献消除,后者假定当前为左端点需减去)

若当前为餐厅,且其坐标为 \(y\),费用为 \(w\),若从 \(A\) 中取得的最优解为 \(v\),对答案贡献 \(w+y+v\),与上头类似,为了维护反悔操作需在 \(B\) 中加入 \(-(w+y+v)-y\)

打完后发现样例中有俩过不去,问了大神们才知道我少考虑了一种情况:若当前顺序为 鼠、洞、洞,我的方法一旦匹配了第一个洞和鼠后,不能考虑鼠反悔去匹配第二个洞的情况

那么就再加入一种反悔操作:往 \(A\) 中加入 \(-w-y\) 即可。具体地说,假设鼠价值 \(v\),两个洞的费用与坐标分别为 \(w_1,w_2,y_1,y_2\),那从第一种情况反悔到第二种情况的贡献为 \((w_2+y_2+v)-(w_1+y_1+v)=w_2+y_2-w_1-y_1\),由于 \(w_2+y_2\) 会在后面统计到,所以只需往堆中加入 \(-w_1-y_1\) 即可。至于为什么不需要对 洞、鼠、鼠 的情况做反悔,因为所有老鼠都是一样的,不可能存在舍近求远的情况

还有一点,由于所有老鼠都要求进洞,若最左侧的老鼠在最左侧的洞的左边,则这只老鼠有可能不会进洞,所以可以在最最最左侧加入一个费用无穷大的洞,这样左侧的老鼠匹配它后立马就会被替换掉,进而所有老鼠都会被匹配(在有解的情况下)

至于如何考虑每个洞的容量限制,可以将每个洞作为一个整体放进堆里,记录下剩余使用次数,作为反悔可以每次分裂一个出来

虽然思想比较简单,但是由于用到多次反悔操作(甚至有反悔后的反悔),所以代码难以调试,建议静态差错,最好一遍过

Code

代码中 \(P\) 表示老鼠,\(R\) 表示洞

//uoj-455
#include <bits/stdc++.h>
using namespace std;
typedef long long ll; typedef pair <ll,int> pr;
#define mp make_pair template <typename _tp> inline void read(_tp&x){
char c11=getchar(),ob=0;x=0;
while(c11!='-'&&!isdigit(c11))c11=getchar();if(c11=='-')ob=1,c11=getchar();
while(isdigit(c11))x=x*10+c11-'0',c11=getchar();if(ob)x=-x;
} const int N = 401000;
const ll Inf = 2e17;
int x[N],n,m; struct node{
int y,w,c;
inline void in(){read(y),read(w),read(c);}
friend inline bool operator < (const node&A,const node&B) {return A.y < B.y;}
}p[N]; struct Heap{
pr h[N]; int tp;
inline bool empty() {return !tp;}
inline pr top() {return h[1];}
inline void push(pr x) {h[++tp] = x; push_heap(h+1,h+tp+1,greater <pr> ());}
inline void pop() {pop_heap(h+1,h+tp+1,greater <pr> ()); --tp;}
}R,P; int main(){
read(n),read(m);
ll tot = 0;
for(int i=1;i<=n;++i) read(x[i]); sort(x+1,x+n+1);
for(int i=1;i<=m;++i) p[i].in(), tot += p[i].c; sort(p+1,p+m+1); if(tot < n) {puts("-1"); return 0;} R.push(mp(Inf,2e8));
x[n+1] = 2e9; ll Ans = 0ll;
for(int i=1,j=1;i<=n or j<=m;) {
while(p[j].y <= x[i] and j <= m){
int usc = 0;
while(!P.empty() and p[j].c){
pr nw = P.top();
ll val = p[j].w + p[j].y + nw.first;
if(val > 0) break; P.pop();
int ct = min(nw.second, p[j].c);
Ans += (ll)ct * val;
R.push(mp(-nw.first - 2*p[j].y, ct));
p[j].c -= ct, usc += ct, nw.second -= ct;
if(nw.second) P.push(nw);
}
if(usc) P.push(mp(-p[j].w - p[j].y, usc));
if(p[j].c) R.push(mp(p[j].w - p[j].y, p[j].c));
++j;
}
if(i > n) continue;
pr nw = R.top(); R.pop();
Ans += nw.first + x[i];
P.push(mp(-(nw.first + x[i]) - x[i], 1));
--nw.second; if(nw.second) R.push(nw);
++i;
}
printf("%lld\n",Ans);
return 0;
}

题解-UOJ 455雪灾与外卖的更多相关文章

  1. [UOJ455][UER #8]雪灾与外卖——堆+模拟费用流

    题目链接: [UOJ455]雪灾与外卖 题目描述:有$n$个送餐员(坐标为$x_{i}$)及$m$个餐厅(坐标为$y_{i}$,权值为$w_{i}$),每个送餐员需要前往一个餐厅,每个餐厅只能容纳$c ...

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

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

  3. uoj455 【UER #8】雪灾与外卖

    http://uoj.ac/problem/455 题解: https://blog.csdn.net/litble/article/details/88410435 https://www.mina ...

  4. 【胡策篇】题解 (UOJ 192 + CF938G + SPOJ DIVCNT2)

    和泉纱雾与烟花大会 题目来源: UOJ 192 最强跳蚤 (只改了数据范围) 官方题解: 在这里哦~(说的很详细了 我都没啥好说的了) 题目大意: 求树上各边权乘积是完全平方数的路径数量. 这种从\( ...

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

    题解: 这个东西的模型是个费用流 但是直接跑费用流能拿到5分的高分 $(nm)*(nm)*log{nm}$ 考虑优化一下建图 我们可以不用对每个店和人都连边 而是对人和店都连一条链 然后对每个人连店刚 ...

  6. UOJ 12 猜数 数学题

    [UER #1]猜数 这一天,小Y.小D.小C正在愉快地玩耍. 小Y是个数学家,他一拍脑袋冒出了一个神奇的完全平方数 n. 小D是个机灵鬼,很快从小Y嘴里套出了 n 的值.然后在脑内把 n 写成了 a ...

  7. 【UTR #2】[UOJ#278]题目排列顺序 [UOJ#279]题目交流通道 [UOJ#280]题目难度提升

    [UOJ#278][UTR #2]题目排列顺序 试题描述 “又要出题了.” 宇宙出题中心主任 —— 吉米多出题斯基,坐在办公桌前策划即将到来的 UOI. 这场比赛有 n 道题,吉米多出题斯基需要决定这 ...

  8. NOIWC2019 冬眠记

    冬眠 由于THUWC考太差了没啥心情做事…… Day -1 报到日前一天晚上去看了看宿舍表,发现周围全是集训队,隔壁就是栋爷.高队和lca,再隔壁是zzq和wxh……吓傻了(本校buff这么好吗) D ...

  9. ZOJ - 3469 Food Delivery (区间dp)

    When we are focusing on solving problems, we usually prefer to stay in front of computers rather tha ...

随机推荐

  1. 正则化(Regularization)本质

    参考: http://www.cnblogs.com/maybe2030/p/9231231.html https://blog.csdn.net/wsj998689aa/article/detail ...

  2. Mobile CI/CD 101

    This is a guest post by Slava Chernikoff, Principal Engineer at Binwell. Mobile DevOps falls under t ...

  3. rk3128 手动挂载 U 盘

    2019-04-16 关键字: RK . 挂载.U盘 笔者手里有一块非常原生的运行 Android 4.4 操作系统的 RK3128 开发板.原生到各种功能模块都不能用的地步.今天就遇到一个不按常理出 ...

  4. MySQL——修改用户密码 | 移除权限

    修改用户密码 '; 移除权限 REVOKE Delete, Drop ON *.* FROM `root`@`localhost`; 权限列表

  5. windows无法完成安装,若要在此计算机上安装,请重新启动安装

    当出现如上提示的时候,不要重启,按下shift+f10 会打开命令窗口,先输入cd oobe 进入到C:\windows\system32\oobe文件夹,输入msoobe回车然后输入msoobe即可 ...

  6. bzoj1444[Jsoi2009]有趣的游戏[AC自动机]

    题面 bzoj 我要向师父学习善待每一只数据结构 考虑成环,那么高斯消元 然鹅这道题太小了 所以直接转移矩阵自乘就好啦 终点不向外连边 有一条向自己的,概率为一的自环来作为结尾 对于其他店 若有边\( ...

  7. Promise的源码实现(完美符合Promise/A+规范)

    Promise是前端面试中的高频问题,我作为面试官的时候,问Promise的概率超过90%,据我所知,大多数公司,都会问一些关于Promise的问题.如果你能根据PromiseA+的规范,写出符合规范 ...

  8. redisson整合spring

    转: redisson整合spring 转: 原文:http://blog.csdn.net/wang_keng/article/details/73549274 首先讲下什么是Redisson:Re ...

  9. OS + CentOS cmake

    s Linux编译安装cmake最新版本 https://blog.51cto.com/sadoc/1910753 https://cmake.org/download/ https://github ...

  10. input表单强制大小写

    如题,在HTML页面中常常有遇到强制表单大小写的场景. 在css中设置,HTML页面元素引用就可以了 强制大写: .toUp{ text-transform:uppercase; } 强制小写: .t ...