CF939F Cutlet (单调队列优化DP)
题目大意:要煎一块有两个面的肉,只能在一段k不相交的时间段$[l_{i},r_{i}]$内翻转,求$2*n$秒后,保证两个面煎的时间一样长时,需要最少的翻转次数,$n<=100000$,$k<=100$
神仙单调队列优化$DP$, [NOI2005]瑰丽华尔兹 也有类似的压时间段的套路,但这道题可比那道题难多了。
朴素$O(n^2)$的$DP$没什么好说的,我们要想办法把它优化成$O(nk)$的
定义$f[i][j]$表示第$i$个时间段内,朝上的面(现在没被煎的)被煎的时间是$j$
1.观察翻转的过程,貌似在一个连续的时间段内翻转2次以上就是没有意义的 ,因为可以翻过去再翻回来
2.貌似并不一定要在整数时间翻转,但这种情况只在翻转1次的情况下有意义,所以整体把时间*2
然后,分情况讨论$DP$转移
1.翻0次,朝上的面被煎的时间不变,$f[i][j]=f[i-1][j]$,无需任何优化
2.翻2次,朝上的面被至多额外煎$r_{i}+l_{i}$秒,枚举上一次当前面被煎的时间$k$,可得$f[i][j]=min(f[i][k])+2\;(k<=j)$
对于这种情况,正序枚举$j$,单调队列优化$DP$即可,$j-k>r_{i}+l_{i}$的弹出队列
3.翻1次,原来朝上的面被翻到了下面,设现在的上面是$a$面,下面是$b$面,则$a$面被煎了$j$秒,$b$面被煎了$r_{i}-j$秒
那么上一次$a$面被煎的时间是$k$,此时$a$面朝下,朝上的面是$b$面,被煎的时间是$r_{i-1}-k$,可得$f[i][j]=min(f[i-1][r_{i}-k])+1$
因为是$-k$,要倒序枚举$j$,同样用单调队列优化,$k-j>r_{i}+l_{i}$弹出队列即可
虽然空间能开下$O(nk)$,但用滚动数组跑得飞快
#include <cstdio>
#include <cstring>
#include <algorithm>
#define N 205
#define M 401000
#define dd double
#define inf 0x3f3f3f3f
#define rint register int
using namespace std; int n,K,cnt;
int l[N],r[N],t[N];
int f[][M],que[M]; int main()
{
scanf("%d%d",&n,&K);
for(int i=;i<=K;i++){
scanf("%d%d",&l[i],&r[i]);
t[++cnt]=l[i]<<,t[++cnt]=r[i]<<;
}
memset(f,0x3f,sizeof(f));
f[][]=;int now=,pst=;
n<<=;
for(int i=;i<=cnt;i++)
{
if(i&) continue;
int hd=,tl=;
for(rint j=;j<=t[i];j++)
f[now][j]=inf;
for(rint j=;j<=t[i];j++)
{
f[now][j]=min(f[now][j],f[pst][j]);
while(hd<=tl&&f[pst][j]<=f[pst][que[tl]])
tl--;
que[++tl]=j;
while(hd<=tl&&j-que[hd]>t[i]-t[i-])
hd++;
f[now][j]=min(f[now][j],f[pst][que[hd]]+);
}
hd=,tl=;
for(rint j=t[i];j>=;j--)
{
while(hd<=tl&&f[pst][t[i]-j]<=f[pst][t[i]-que[tl]])
tl--;
que[++tl]=j;
while(hd<=tl&&que[hd]-j>t[i]-t[i-])
hd++;
f[now][j]=min(f[now][j],f[pst][t[i]-que[hd]]+);
}
swap(now,pst);
}
if(f[pst][n]==inf) printf("Hungry\n");
else printf("Full\n%d\n",f[pst][n]);
return ;
}
CF939F Cutlet (单调队列优化DP)的更多相关文章
- 单调队列优化DP,多重背包
单调队列优化DP:http://www.cnblogs.com/ka200812/archive/2012/07/11/2585950.html 单调队列优化多重背包:http://blog.csdn ...
- 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 ...
- hdu3401:单调队列优化dp
第一个单调队列优化dp 写了半天,最后初始化搞错了还一直wa.. 题目大意: 炒股,总共 t 天,每天可以买入na[i]股,卖出nb[i]股,价钱分别为pa[i]和pb[i],最大同时拥有p股 且一次 ...
- Parade(单调队列优化dp)
题目连接:http://acm.hdu.edu.cn/showproblem.php?pid=2490 Parade Time Limit: 4000/2000 MS (Java/Others) ...
- BZOJ_3831_[Poi2014]Little Bird_单调队列优化DP
BZOJ_3831_[Poi2014]Little Bird_单调队列优化DP Description 有一排n棵树,第i棵树的高度是Di. MHY要从第一棵树到第n棵树去找他的妹子玩. 如果MHY在 ...
- 【单调队列优化dp】 分组
[单调队列优化dp] 分组 >>>>题目 [题目] 给定一行n个非负整数,现在你可以选择其中若干个数,但不能有连续k个数被选择.你的任务是使得选出的数字的和最大 [输入格式] ...
- [小明打联盟][斜率/单调队列 优化dp][背包]
链接:https://ac.nowcoder.com/acm/problem/14553来源:牛客网 题目描述 小明很喜欢打游戏,现在已知一个新英雄即将推出,他同样拥有四个技能,其中三个小技能的释放时 ...
- 单调队列以及单调队列优化DP
单调队列定义: 其实单调队列就是一种队列内的元素有单调性的队列,因为其单调性所以经常会被用来维护区间最值或者降低DP的维数已达到降维来减少空间及时间的目的. 单调队列的一般应用: 1.维护区间最值 2 ...
- BZOJ1791[Ioi2008]Island 岛屿 ——基环森林直径和+单调队列优化DP+树形DP
题目描述 你将要游览一个有N个岛屿的公园.从每一个岛i出发,只建造一座桥.桥的长度以Li表示.公园内总共有N座桥.尽管每座桥由一个岛连到另一个岛,但每座桥均可以双向行走.同时,每一对这样的岛屿,都有一 ...
随机推荐
- css——样式的优先级
样式的优先级 在p中有id,class,标签,行内样式,它们的优先级: 1.id 样式>class样式>标签样式 2.行内样式>内嵌样式>外部样式 强制优先级 比如我希望上面的 ...
- java的插入排序
import java.util.Scanner;public class test22 { public static void main(String[] args) { Scanner in= ...
- HDU 2078 选课时间( 水题 )
链接:传送门 思路:水题略 /************************************************************************* > File N ...
- 一个学习scrapy的网站
当然是scrapy中文网辣,从浅到深,例子报错几乎都有 http://www.scrapyd.cn/doc/
- js 对象的创建方式和对象的区别
js一个有三种方法创建对象,这里做一个总结. 1.对象直接量 所谓对象直接量,可以看做是一副映射表,这个方法也是最直接的一个方法,个人比较建议, 1 2 3 4 5 6 7 8 9 10 11 12 ...
- 【Codeforces Round #476 (Div. 2) [Thanks, Telegram!] B】Battleship
[链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] 暴力枚举船的左上角. 然后统计每个点被覆盖次数就好. [代码] #include <bits/stdc++.h> #de ...
- Java基础学习总结(59)——30 个java编程技巧
1.return 一个空的集合,而不是 null 如果一个程序返回一个没有任何值的集合,请确保一个空集合返回,而不是空元素.这样你就不用去写一大堆 "if else" 判断null ...
- linux内核(五)虚拟文件系统
虚拟文件系统(VFS)是linux内核和具体I/O设备之间的封装的一层共通访问接口,通过这层接口,linux内核可以以同一的方式访问各种I/O设备. 虚拟文件系统本身是linux内核的一部分,是纯软件 ...
- PatentTips - Object-oriented processor architecture and operating method
BACKGROUND OF THE INVENTION The present invention relates to processors and computer systems. More s ...
- fork同一时候创建多个子进程的方法
Fork同一时候创建多个子进程方法 第一种方法:验证通过 特点:同一时候创建多个子进程.每一个子进程能够运行不同的任务,程序 可读性较好,便于分析,易扩展为多个子进程 int main(void) { ...