洛谷题目页面传送门 & CodeForces题目页面传送门

题意见洛谷里的翻译。

这是一道毒瘤的div. 2 F,我是不可能比赛的时候做出来的。。。

(以下设两面都要煎\(n\)分钟,有\(m\)个可翻转时间区间,第\(i\)个为\([l_i,r_i]\))

废话不多说,这题可以考虑DP。数据范围告诉我们标算大概是\(\mathrm{O}(nm)\)的,不难想到可以把一个可翻转区间和与之相邻的不可翻转区间当作一个整体作为阶段。设\(dp_{i,j}\)表示当前考虑到时刻\(l_{i+1}\)(那么这个阶段需要考虑的时间段就是\([l_i,l_{i+1}]\),即可翻转区间\([l_i,r_i]\)加上不可翻转区间\([r_i,l_{i+1}]\),特殊地,\(l_0=0,r_0=-1,l_{m+1}=2n\)),最后一刻煎的那一面一共煎了\(j\)秒,所需要翻的最少次数。那么目标就是\(dp_{m,n}\)。很显然,边界是\(dp_{0,j}=\begin{cases}+\infty&j\ne l_1\\0&j=l_1\end{cases}\),因为前\(l_1\)秒是翻不了的。而转移的时候只需要考虑在\([l_i,l_{i+1}]\)里翻\(0,1,2\)次的情况即可,因为翻更多次都可以转化为翻\(1\)或\(2\)次(感性理解一下)。那么状态转移方程就出来了:

\[dp_{i,j}=\min\!\left(dp_{i-1,j-(l_{i+1}-l_i)},\min\limits_{k=l_i}^{r_i}\{dp_{i-1,l_i-(j-(l_{i+1}-k))}+1\},\min\limits_{k=l_i}^{r_i}\{dp_{i-1,j-(l_{i+1}-k)}+2\}\right)
\]

将上面那个式子去去括号变变形,得

\[dp_{i,j}=\min\!\left(dp_{i-1,j-l_{i+1}+l_i},\min\limits_{k=l_i-j+l_{i+1}-r_i}^{l_i-j+l_{i+1}-l_i}\{dp_{i-1,k}\}+1,\min\limits_{k=j-l_{i+1}+l_i}^{j-l_{i+1}+r_i}\{dp_{i-1,k}\}+2\right)
\]

不难发现,最外面的\(\min\)里有\(3\)部分,分别是翻\(0,1,2\)次的情况。翻\(0\)次的转移是\(\mathrm{O}(1)\)的,而另外\(2\)个是\(\mathrm{O}(n)\)的。朴素地转移总时间复杂度为\(\mathrm{O}\!\left(n^2m\right)\),爆炸不多说。不难发现,在同一个阶段里,随着\(j\)的增加,翻\(1\)次的\(\min\)的上下界同时减少,翻\(2\)次的则同时增加。这\(2\)个都可以用单调队列来优化到每个阶段均摊\(\mathrm{O}(n)\)(一个倒着单调队列,一个正着),于是总共\(\mathrm{O}(nm)\)。(如果你想不到单调队列,也可以在到达一个阶段的时候,把上一个阶段的DP值打个ST表,或者线段树维护,但那都是带\(\log\)的,过不掉hhhh,所以只能单调队列)

对了,我的代码里还用了滚动数组优化了一下空间。(其实根本不用,\(\mathrm{O}(nm)\)的空间在CodeForces上应该是可以过的,但保险起见)

下面贴AC代码:

#include<bits/stdc++.h>
using namespace std;
const int inf=0x3f3f3f3f;
const int N=100000,M=100;
int n/*每面要煎的秒数*/,m/*可翻转区间数*/;
int l[M+1],r[M+1];//每个区间的左右端点
int dp[2][2*N+1];//dp[i][j]表示当前考虑到时刻l[i+1],最后一刻煎的那一面一共煎了j秒,所需要翻的最少次数
int q[2*N],head,tail;//单调队列
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++)scanf("%d%d",l+i,r+i);
l[m+1]=2*n;//dp[m][j]应当考虑完整个2n秒的时间了
memset(dp[0],0x3f,sizeof(dp[0]));//边界
dp[0][l[1]]=0;//边界
for(int i=1;i<=m;i++){
int now=i&1,prv=!now;//滚动数组
memset(dp[now],0x3f,sizeof(dp[now]));//初始化为inf
for(int j=0;j<=2*n;j++)dp[now][j]=min(dp[now][j],j-l[i+1]+l[i]<0?inf:dp[prv][j-l[i+1]+l[i]]);//翻0次
head=tail=0;//清空单调队列
for(int j=max(0,l[i]-2*n+l[i+1]-r[i]);j<-2*n+l[i+1];j++){//翻1次,因为是倒着的,所以从2n开始
while(head<tail&&dp[prv][q[tail-1]]>=dp[prv][j])tail--;
q[tail++]=j;
}
for(int j=2*n;~j;j--){//翻1次,倒着单调队列
// cout<<j<<":\t+1=\t"<<l[i]-j+l[i+1]-r[i]<<"~"<<-j+l[i+1]<<"\n";
while(head<tail&&q[head]<l[i]-j+l[i+1]-r[i])head++;
if(-j+l[i+1]>=0){
while(head<tail&&dp[prv][q[tail-1]]>=dp[prv][-j+l[i+1]])tail--;
q[tail++]=-j+l[i+1];
}
dp[now][j]=min(dp[now][j],head==tail?inf:dp[prv][q[head]]+1);
}
head=tail=0;//清空单调队列
for(int j=max(0,-l[i+1]+l[i]);j<-l[i+1]+r[i];j++){//翻2次,因为是正着的,所以从0开始
while(head<tail&&dp[prv][q[tail-1]]>=dp[prv][j])tail--;
q[tail++]=j;
}
for(int j=0;j<=2*n;j++){//翻2次,正着单调队列
// cout<<j<<":\t+2=\t"<<j-l[i+1]+l[i]<<"~"<<j-l[i+1]+r[i]<<"\n";
while(head<tail&&q[head]<j-l[i+1]+l[i])head++;
if(j-l[i+1]+r[i]>=0){
while(head<tail&&dp[prv][q[tail-1]]>=dp[prv][j-l[i+1]+r[i]])tail--;
q[tail++]=j-l[i+1]+r[i];
}
dp[now][j]=min(dp[now][j],head==tail?inf:dp[prv][q[head]]+2);
}
// for(int j=0;j<=2*n;j++)printf("dp[%d][%d]=%d\n",i,j,dp[now][j]);
}
printf(dp[m&1][n]<inf?"Full\n%d\n":"Hungry",dp[m&1][n]);//目标是dp[m][n]
return 0;
}

CodeForces 939F Cutlet的更多相关文章

  1. codeforces 939F 单调队列优化dp

    F. Cutlet time limit per test 4 seconds memory limit per test 256 megabytes input standard input out ...

  2. Codeforces Round #464 F. Cutlet

    Description 题面 有\(2*n\)的时间,去煎一块肉,肉有两面,你需要在特定的时间内翻转,使得每一面都恰好煎了\(n\)分钟,你有\(k\)次翻转的机会,每一次表示为一段时间 \([L_i ...

  3. python爬虫学习(5) —— 扒一下codeforces题面

    上一次我们拿学校的URP做了个小小的demo.... 其实我们还可以把每个学生的证件照爬下来做成一个证件照校花校草评比 另外也可以写一个物理实验自动选课... 但是出于多种原因,,还是绕开这些敏感话题 ...

  4. 【Codeforces 738D】Sea Battle(贪心)

    http://codeforces.com/contest/738/problem/D Galya is playing one-dimensional Sea Battle on a 1 × n g ...

  5. 【Codeforces 738C】Road to Cinema

    http://codeforces.com/contest/738/problem/C Vasya is currently at a car rental service, and he wants ...

  6. 【Codeforces 738A】Interview with Oleg

    http://codeforces.com/contest/738/problem/A Polycarp has interviewed Oleg and has written the interv ...

  7. CodeForces - 662A Gambling Nim

    http://codeforces.com/problemset/problem/662/A 题目大意: 给定n(n <= 500000)张卡片,每张卡片的两个面都写有数字,每个面都有0.5的概 ...

  8. CodeForces - 274B Zero Tree

    http://codeforces.com/problemset/problem/274/B 题目大意: 给定你一颗树,每个点上有权值. 现在你每次取出这颗树的一颗子树(即点集和边集均是原图的子集的连 ...

  9. CodeForces - 261B Maxim and Restaurant

    http://codeforces.com/problemset/problem/261/B 题目大意:给定n个数a1-an(n<=50,ai<=50),随机打乱后,记Si=a1+a2+a ...

随机推荐

  1. Minimum Spanning Tree

    前言 说到最小生成树(Minimum Spanning Tree),首先要对以下的图论概念有所了解. 图 图(Graph)是表示物件与物件之间的关系的数学对象,是图论的基本研究对象.图的定义方式有两种 ...

  2. 洛谷p1216 IOI1994 Day1T1

    洛谷p1216 IOI1994 Day1T1 洛谷原题 题目描述 观察下面的数字金字塔. 写一个程序来查找从最高点到底部任意处结束的路径,使路径经过数字的和最大.每一步可以走到左下方的点也可以到达右下 ...

  3. idea中向pom.xml添加依赖时显示”not found dependency“

    总结: 起因:再输入hibernate-core的version时,开始写的是对的,就是 5.0.11.Final(这个也是跟着教程来的),直接就报错了,左等右等没用,也点过maven的reimpor ...

  4. LaTeX大全

    1.指数和下标可以用^和_后加相应字符来实现.比如: 2.平方根(square root)的输入命令为:\sqrt,n 次方根相应地为: \sqrt[n].方根符号的大小由LATEX自动加以调整.也可 ...

  5. C语言入门3-C语言概述及数据类型

    一.          计算机程序设计语言 (计算机语言的发展历史) 1.       机器语言 机器语言 二进制代码语言,由  0和1组成的. 特点是:计算机可以直接识别,不需要进行任何的翻译. 2 ...

  6. 简单web网页与SSM后台交互

    简单web网页与SSM后台交互 情况说明 如今,已经搭建好SSM后台开发环境,并且可以经由postman工具测试成功.现在尝试写出web前端网页,通过实现简单的提交.注册.查询功能来加深对前后端数据传 ...

  7. C#中使用split分割字符串的方法小结

    string s=abcdeabcdeabcde; string[] sArray=s.Split(c) ; foreach(string i in sArray) Console.WriteLine ...

  8. 《VR入门系列教程》之16---第一个OculusVR应用

    第一个VR应用    之前我们已经将Oculus的开发包导入到空工程中了,现在我们来构建第一个桌面VR的示例.开发包中已经有一个示例场景,只需要几步就可以让这个场景运行起来.我们将要构建的这个Demo ...

  9. Servlet和JSP知识总结

    1.Servlet接口有哪些方法及Servlet生命周期 Servlet接口定义了5个方法,前三个方法与Servlet生命周期有关: void init() void service() void d ...

  10. WGAN的改进点和实操

    包含三部分:1.WGAN改进点  2.代码修改  3.训练心得 一.WGAN的改进部分: 判别器最后一层去掉sigmoid    (相当于最后一层做了一个y = x的激活) 生成器和判别器的loss不 ...