题意简述

有一个正反面都为 \(0\) 的卡片,每过 \(1\) 分朝下那一面的数值就会增加 \(1\),你可以在几个区间的时间内翻转卡片,求经过 \(2n\) 秒后能否让这个卡片的正反面的数都为 \(n\),求最小翻转数。

暴力

为了简单起见,我们定义一面为正面,一面为反面,\(1\) 表示正面,\(0\) 表示反面。

一眼看出来 dp,\(dp_{i,j,1/0}\) 表示在第 \(i\) 个区间结束后,正面数字为 \(j\),\(1/0\) 面朝上的最小翻转数。

那么状态转移方程为:

\(dp_{i,j,1}=\min(dp_{i-1,j-p,1}+2,dp_{i-1,j-q,0}+1,dp_{i-1,j-g,1})\)

\(dp_{i,j,0}=\min(dp_{i-1,j-p,1}+1,dp_{i-1,j-q,0}+2,dp_{i-1,j,0})\)

其中满足:

区间间隔 \(\le p \le\) 两个区间右端点间隔。

区间长度 \(\le q \le\) 两个区间右端点间隔。

\(g\) 表示两个区间右端点间隔。

不难发现,这样的转移是 \(O(n)\) 的,再加上我们需要计算 \(nk\) 个 dp 值,这样做显然超时。需要考虑优化。

优化

不难发现,在计算一个区间完成后的值时,如果我们从 \(n\) 到 \(0\) 来计算,每次计算值所需要遍历区间的上限和下限都时逐渐减少的,那么我们就可以采取单调队列优化了。

这里用到一个小技巧:

如果一开始遍历区间的下限不为最低,那么我们可以令一个变量 \(idx\) 一开始指向第一个区间的下限,然后逐渐降低,分批入队。

这个单调队列可以滚动掉一维,只需要保留它记录 dp 值的 \(0/1\) 就行了。

Code

#include <bits/stdc++.h>

using namespace std;

const int N = 1e5 + 10, K = 110, INF = 0x3f3f3f3f;

int dp[K][N * 2][2];
int g[K], n, k, idx[2]; deque <int> q[2]; struct line {
int l, r;
bool operator < (const line& rhs) const {
return l < rhs.l;
}
}lines[K]; inline void q_push (int i, int j, int op) {
while (q[op].size() && dp[i][q[op].back()][op] >= dp[i][j][op]) q[op].pop_back();
q[op].push_back(j);
} inline void q_pop (int i, int j, int op) {
while (q[op].size() && j - q[op].front() < 0) q[op].pop_front();
} inline void init () {
q[1].clear(); q[0].clear();
idx[0] = idx[1] = 2 * n;
} int main () {
memset(dp, INF, sizeof(dp));
scanf("%d%d", &n, &k);
for (int i = 1;i <= k;i++) scanf("%d%d", &lines[i].l, &lines[i].r);
sort(lines + 1, lines + 1 + k);
g[1] = lines[1].l; g[k + 1] = 2 * n - lines[k].r;
for (int i = 2;i <= k;i++) g[i] = lines[i].l - lines[i - 1].r;
for (int j = lines[1].l;j <= lines[1].r;j++) {
dp[1][j][1] = 2;
dp[1][j][0] = 1;
}
dp[1][lines[1].r][1] = 0;
for (int i = 2;i <= k;i++) {
int l = lines[i].r - lines[i - 1].r, lg = lines[i].r - lines[i].l;
init();
for (int j = lines[i].r;j >= 0;j--) {
while (j - l <= idx[1] && idx[1] > 0) q_push(i - 1, idx[1]--, 1);
while (j - lg <= idx[0] && idx[0] > 0) q_push(i - 1, idx[0]--, 0);
q_pop(i - 1, j - g[i], 1); q_pop(i - 1, j, 0);
dp[i][j][1] = min(dp[i][j][1], (q[1].size() ? dp[i - 1][q[1].front()][1] + 2 : INF));
dp[i][j][1] = min(dp[i][j][1], (q[0].size() ? dp[i - 1][q[0].front()][0] + 1 : INF));
dp[i][j][1] = min(dp[i][j][1], (j - l >= 0 ? dp[i - 1][j - l][1] : INF));
// cout << i << " " << j << " 1: " << dp[i][j][1] << endl;
}
init();
for (int j = lines[i].r;j >= 0;j--) {
while (j - l <= idx[1] && idx[1] > 0) q_push(i - 1, idx[1]--, 1);
while (j - lg <= idx[0] && idx[0] > 0) q_push(i - 1, idx[0]--, 0);
q_pop(i - 1, j - g[i], 1); q_pop(i - 1, j, 0);
dp[i][j][0] = min(dp[i][j][0], (q[1].size() ? dp[i - 1][q[1].front()][1] + 1 : INF));
dp[i][j][0] = min(dp[i][j][0], (q[0].size() ? dp[i - 1][q[0].front()][0] + 2 : INF));
dp[i][j][0] = min(dp[i][j][0], dp[i - 1][j][0]);
// cout << i << " " << j << " 0: " << dp[i][j][0] << endl;
}
}
if (min(n - g[k + 1] >= 0 ? dp[k][n - g[k + 1]][1] : INF, dp[k][n][0]) < INF) printf("Full\n%d\n", min(n - g[k + 1] >= 0 ? dp[k][n - g[k + 1]][1] : INF, dp[k][n][0]));
else printf("Hungry\n");
return 0;
}

CF939F Cutlet 题解的更多相关文章

  1. CF939F Cutlet (单调队列优化DP)

    题目大意:要煎一块有两个面的肉,只能在一段k不相交的时间段$[l_{i},r_{i}]$内翻转,求$2*n$秒后,保证两个面煎的时间一样长时,需要最少的翻转次数,$n<=100000$,$k&l ...

  2. 2016 华南师大ACM校赛 SCNUCPC 非官方题解

    我要举报本次校赛出题人的消极出题!!! 官方题解请戳:http://3.scnuacm2015.sinaapp.com/?p=89(其实就是一堆代码没有题解) A. 树链剖分数据结构板题 题目大意:我 ...

  3. noip2016十连测题解

    以下代码为了阅读方便,省去以下头文件: #include <iostream> #include <stdio.h> #include <math.h> #incl ...

  4. BZOJ-2561-最小生成树 题解(最小割)

    2561: 最小生成树(题解) Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1628  Solved: 786 传送门:http://www.lyd ...

  5. Codeforces Round #353 (Div. 2) ABCDE 题解 python

    Problems     # Name     A Infinite Sequence standard input/output 1 s, 256 MB    x3509 B Restoring P ...

  6. 哈尔滨理工大学ACM全国邀请赛(网络同步赛)题解

    题目链接 提交连接:http://acm-software.hrbust.edu.cn/problemset.php?page=5 1470-1482 只做出来四道比较水的题目,还需要加强中等题的训练 ...

  7. 2016ACM青岛区域赛题解

    A.Relic Discovery_hdu5982 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Jav ...

  8. poj1399 hoj1037 Direct Visibility 题解 (宽搜)

    http://poj.org/problem?id=1399 http://acm.hit.edu.cn/hoj/problem/view?id=1037 题意: 在一个最多200*200的minec ...

  9. 网络流n题 题解

    学会了网络流,就经常闲的没事儿刷网络流--于是乎来一发题解. 1. COGS2093 花园的守护之神 题意:给定一个带权无向图,问至少删除多少条边才能使得s-t最短路的长度变长. 用Dijkstra或 ...

  10. CF100965C题解..

    求方程 \[ \begin{array}\\ \sum_{i=1}^n x_i & \equiv & a_1 \pmod{p} \\ \sum_{i=1}^n x_i^2 & ...

随机推荐

  1. 2022-04-20:小团去参加军训,军训快要结束了, 长官想要把大家一排n个人分成m组,然后让每组分别去参加阅兵仪式, 只能选择相邻的人一组,不能随意改变队伍中人的位置, 阅兵仪式上会进行打分,其中

    2022-04-20:小团去参加军训,军训快要结束了, 长官想要把大家一排n个人分成m组,然后让每组分别去参加阅兵仪式, 只能选择相邻的人一组,不能随意改变队伍中人的位置, 阅兵仪式上会进行打分,其中 ...

  2. 2021-04-07:给定一个非负数组arr,长度为N,那么有N-1种方案可以把arr切成左右两部分,每一种方案都有,min{左部分累加和,右部分累加和},求这么多方案中,min{左部分累加和,右部分累加和}的最大值是多少? 整个过程要求时间复杂度O(N)。

    2021-04-07:给定一个非负数组arr,长度为N,那么有N-1种方案可以把arr切成左右两部分,每一种方案都有,min{左部分累加和,右部分累加和},求这么多方案中,min{左部分累加和,右部分 ...

  3. vue全家桶进阶之路40:Vue3父件传值给子件

    在Vue3中,可以通过props将父组件的数据传递给子组件.具体步骤如下: 在父组件中定义要传递给子组件的数据,可以是data属性中的数据或者是计算属性computed中的数据. 在子组件中通过pro ...

  4. SQL Server 2014 英文版安装教程

    安装过程如下 1. 点击setup开始安装. 2. 选择如下的全新安装. 3. 自动生成产品密钥,然后点击下一步. 4. 勾选接受条款,然后点击下一步. 5. 自动更新根据实际情况进行选择,点击下一步 ...

  5. Metabase可视化BI系统部署安装及简单使用

    Metabase 是国外开源的一个可视化系统,语言使用了Clojure + TypeScript. Clojure(/ˈkloʊʒər/)是Lisp程式語言在Java平台上的現代.動態及函數式方言.来 ...

  6. Win10安装cuda11.0+cudnn8.0(这是配套的)

    首先你要知道你的电脑显卡能支持的cuda最大版本: 如下下图所示,支持最大版本为cuda11.0.228版本! 一.下载 Win10 64 位 下载cudnn8.0 链接:https://pan.ba ...

  7. 翻车了,被读者找出 BUG

    大家好呀,我是小楼. 本文是上篇文章<使用增强版 singleflight 合并事件推送,效果炸裂!>的续集,没看过前文必须要先看完才能看本文,实在不想看,拉到文章末尾,给我点个赞再退出吧 ...

  8. Java Websocket 01: 原生模式 Websocket 基础通信

    目录 Java Websocket 01: 原生模式 Websocket 基础通信 Java Websocket 02: 原生模式通过 Websocket 传输文件 Websocket 原生模式 原生 ...

  9. redis集群报错:MISCONF Redis is configured to save RDB snapshots, but it is currently not able to persist on disk.

    之前在x86架构的服务器部署redis集群,未遇到题中问题:然而在ARM架构的服务器部署redis集群,第一次遇到如此问题.虽然问题已经解决,但不清楚问题的具体原因,在此做个记录. 性能测试过程中,通 ...

  10. maven报错:不再支持源选项 5。请使用 6 或更高版本

    问题描述 在执行命令 mvn compile 发生错误 D:\Github_NOTES\JavaWeb_Learning\02Java\JavaWeb\Code\Maven1>mvn clean ...