Mice and Holes 单调队列优化dp

n个老鼠,m个洞,告诉你他们的一维坐标和m个洞的容量限制,问最小总距离。1 ≤ n, m ≤ 5000。

​ 首先列出朴素的dp方程:\(f[i][j]=min(f[i-1][k]+s[j]-s[k])\),其中\(f[i][j]\)表示前i个洞,有j个老鼠进洞。s[j]-s[k]表示第k+1到j个老鼠进洞的路径和。然后我们发现,\(f[i][j]\)的值取决于最小的\(f[i-1][k]-s[k]\ (k<=j)\),同时,j-k必须小于等于第i个洞的容量。于是我们建一个单调队列,队列存储最优的k。然后如果\(j-q[head]\)大于第i个洞的容量,那么head++,然后如果\(f[i-1][j]\)大于队列末尾,那么就一直tail--。这样就可以把\(O(n^3)\)的时间复杂度优化成O(n^2)。

​ 对了,初始化的时候要注意,想清楚没有优化的时候是什么样的状态。其实不难的。

#include <cstdio>
#include <cstring>
#include <algorithm> typedef long long LL;
const LL maxn=5005, INF=1e18;
inline LL abs(LL x){ return x<0?-x:x; } struct Hole{
LL pos, cap;
void set(LL x, LL y){ pos=x; cap=y; }
}hole[maxn]; bool cmp(const Hole &a, const Hole &b){
return a.pos<b.pos; } //queue:当前第i个洞里面关于有几个老鼠的单调队列
LL n, m, head, tail, queue[maxn];
LL mice[maxn], pre[maxn];
LL fpre[maxn], fnow[maxn], s[maxn]; int main(){
scanf("%lld%lld", &n, &m);
for (LL i=1; i<=n; ++i)
scanf("%lld", &mice[i]);
std::sort(mice+1, mice+n+1);
for (LL i=1; i<=m; ++i)
scanf("%lld%lld", &hole[i].pos, &hole[i].cap);
std::sort(hole+1, hole+m+1, cmp);
//pre:洞最多可容纳老鼠的前缀和
pre[1]=hole[1].cap;
for (LL i=2; i<=m; ++i)
pre[i]=pre[i-1]+hole[i].cap;
if (pre[m]<n){
printf("-1\n");
return 0;
}
fpre[0]=fnow[0]=0;
for (int j=1; j<=n; ++j)
fpre[j]=fnow[j]=INF;
for (LL i=1; i<=m; ++i){
//si:前i个老鼠都放在此洞中的代价
s[0]=0;
for (LL j=1; j<=n; ++j)
s[j]=s[j-1]+abs(hole[i].pos-mice[j]);
head=0; tail=0;
for (LL j=0; j<=n; ++j){
//放不进去,那显然是直接跳过
if (j>pre[i]) break;
//不能让这个洞容纳更多老鼠
while (head<tail&&j-queue[head]>hole[i].cap) ++head;
//单调队列,不是min的通通吃掉
while (head<tail&&fpre[j]-s[j]<=
fpre[queue[tail-1]]-s[queue[tail-1]]) --tail;
queue[tail++]=j;
fnow[j]=fpre[queue[head]]+s[j]-s[queue[head]];
}
for (LL j=0; j<=n; ++j)
fpre[j]=fnow[j];
}
printf("%lld", fnow[n]);
}

Mice and Holes 单调队列优化dp的更多相关文章

  1. 单调队列优化DP,多重背包

    单调队列优化DP:http://www.cnblogs.com/ka200812/archive/2012/07/11/2585950.html 单调队列优化多重背包:http://blog.csdn ...

  2. bzoj1855: [Scoi2010]股票交易--单调队列优化DP

    单调队列优化DP的模板题 不难列出DP方程: 对于买入的情况 由于dp[i][j]=max{dp[i-w-1][k]+k*Ap[i]-j*Ap[i]} AP[i]*j是固定的,在队列中维护dp[i-w ...

  3. hdu3401:单调队列优化dp

    第一个单调队列优化dp 写了半天,最后初始化搞错了还一直wa.. 题目大意: 炒股,总共 t 天,每天可以买入na[i]股,卖出nb[i]股,价钱分别为pa[i]和pb[i],最大同时拥有p股 且一次 ...

  4. Parade(单调队列优化dp)

    题目连接:http://acm.hdu.edu.cn/showproblem.php?pid=2490 Parade Time Limit: 4000/2000 MS (Java/Others)    ...

  5. BZOJ_3831_[Poi2014]Little Bird_单调队列优化DP

    BZOJ_3831_[Poi2014]Little Bird_单调队列优化DP Description 有一排n棵树,第i棵树的高度是Di. MHY要从第一棵树到第n棵树去找他的妹子玩. 如果MHY在 ...

  6. 【单调队列优化dp】 分组

    [单调队列优化dp] 分组 >>>>题目 [题目] 给定一行n个非负整数,现在你可以选择其中若干个数,但不能有连续k个数被选择.你的任务是使得选出的数字的和最大 [输入格式] ...

  7. [小明打联盟][斜率/单调队列 优化dp][背包]

    链接:https://ac.nowcoder.com/acm/problem/14553来源:牛客网 题目描述 小明很喜欢打游戏,现在已知一个新英雄即将推出,他同样拥有四个技能,其中三个小技能的释放时 ...

  8. 单调队列以及单调队列优化DP

    单调队列定义: 其实单调队列就是一种队列内的元素有单调性的队列,因为其单调性所以经常会被用来维护区间最值或者降低DP的维数已达到降维来减少空间及时间的目的. 单调队列的一般应用: 1.维护区间最值 2 ...

  9. BZOJ1791[Ioi2008]Island 岛屿 ——基环森林直径和+单调队列优化DP+树形DP

    题目描述 你将要游览一个有N个岛屿的公园.从每一个岛i出发,只建造一座桥.桥的长度以Li表示.公园内总共有N座桥.尽管每座桥由一个岛连到另一个岛,但每座桥均可以双向行走.同时,每一对这样的岛屿,都有一 ...

随机推荐

  1. tarjian求lca

    看了好多dalao的博客,就总结一下啦ovo tarjian算法很是神奇,它的作用是求lca.它是一种离线算法. 在线是指输入一个询问输出一个结果. 离线是将询问一次性输入,一起处理. tarjan它 ...

  2. Django来敲门~第一部分【4. 创建第一个模块应用】

    成若缺,其用不弊.大盈若冲,其用不穷.大直若屈.大巧若拙.大辩若讷.静胜躁,寒胜热.清静为天下正 ——老子<道德经> 本章内容 创建应用(app) 开发第一个视图(View) URL访问配 ...

  3. [转]两种高性能I/O设计模式(Reactor/Proactor)的比较

    [原文地址:http://www.cppblog.com/pansunyou/archive/2011/01/26/io_design_patterns.html] 综述 这篇文章探讨并比较两种用于T ...

  4. 自定义type为file型input控件+该控件具有本地图片预览功能

    最近的一个项目需求是写一个type为filex型的input控件,这个控件: 第一,要自定义样式: 第二,要能直接在本地预览上传的图片: 第三,要能检测图片的尺寸是否符合要求. 故综合网上的资源写了下 ...

  5. Django-进阶 分页,中间件

    知识预览 分页 中间件 回到顶部 分页 Django的分页器(paginator) view from django.shortcuts import render,HttpResponse # Cr ...

  6. Windows 7下Git SSH 创建Key的步骤

    1.首先你要安装Git工具 下载地址:https://git-scm.com/downloads 2.右键鼠标,选中 “Git Bash here”,当然你也可以在windows的 “开始”---&g ...

  7. 编译Python出现Tab,空格的问题

    我们编译python代码时, 经常出现各种因为tab和空格的问题, 例如: IndentationError: unindent does not match any outer indentatio ...

  8. windows7下c++11环境搭建

    1.安装codeblocks 13.12 2.下载安装tdm-gcc-4.8.1-3 3.配置coldblocks的编译器(settings->compiler->compiler set ...

  9. HDU1698(线段树入门题)

    Just a Hook Time Limit:2000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u Descrip ...

  10. fiddler 的AutoRespoder的使用(手动添加测试桩)

    ---恢复内容开始--- 1.首先我们抓取一个百度的请求,由于百度请求是https协议,需要手动添加证书(这个不写了,大佬们自己手动找下资料) 2.fiddler抓取的百度请求,其他的无关信息删除,便 ...