Slastičarnica:非常好的区间 dp 题。

暴力

不难设计出暴力状态:\(dp_{q,i,j}\) 表示进行到第 \(q\) 次操作,剩下区间 \([i,j]\) 是否可行。

直到全部状态都为 \(0\) 的时候输出即可。

期望得分 \(19pts\)。

优化(假)

观察到每个 \(dp\) 状态都只有两个值 \(0,1\),那么我们可以考虑将状态中的某一维放进 \(dp\) 值里。

首先尝试把 \(q\) 换进去,状态设计为 \(dp_{i,j}\) 为剩余区间 \([i,j]\) 时进行的最大操作数为 \(q\)。

那么我们怎么转移?从大往小枚举区间,然后根据当前进行的操作,每次查询满足要求的前缀后缀,转移一下即可。

此时我们不难发现,\(q\) 的最大值只能是 \(n\),根本无法取到更大。这就是这题的诈骗点。

时间复杂度是 \(O(n^3)\) 的,而我们可以发现无法继续优化下去(四边形不等式等都用不了),就要换一种思路。

贪心

显然,对于一段区间而言,长度越长,自然是对答案更优。为什么?因为每次操作都可以留出更多的空间来操作。

于是我们考虑固定左端点,把右端点换出来。

正解

设计状态 \(dp_{q,i}\) 表示进行到了第 \(q\) 次操作,左端点为 \(i\) 时的最大右端点在哪。

每次操作可以选前缀、后缀,于是我们分两种转移。

前缀

\(dp_{q,i}\) 能转移当且仅当 \([i-d,i-1]\) 能被消掉,然后转移左端点在 \(i\) 前面的 \(j\) 的所有 \(dp_{q-1,j}\) 的值。

这个可以做一个很显然的前缀和优化,不再细说。

后缀

感觉这个比较难搞。

\(dp_{q,i}\) 能转移的条件是在 \([j,dp_{q-1,j}]\) 中有能消除的后缀,同时在这些后缀中取最大的左端点转移。

观察到 \(dp_{q-1,j}\) 也在 \([1,n]\) 之间,于是我们可以预处理出对于每一个点,在他左边的最大可消除后缀的左端点在哪,这个可以 \(O(n)\) 处理出。

然后每次转移一下即可。

总体时间复杂度 \(O(\min(n,q)n)\)。

细节

特判整个序列被删完的情况。只需要在删后缀里面加特判即可。因为要删完肯定是一次删全部,那么此时就没有前缀后缀之分了,算哪个都可以。

代码

#include <bits/stdc++.h>
#define fi first
#define se second
#define lc (p<<1)
#define rc ((p<<1)|1)
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pi;
int n,q,a[5005],mn[5005][5005],dp[5005][5005],rmx[5005];
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
cin>>n>>q;
for(int i=1;i<=n;i++)cin>>a[i];
memset(mn,0x3f,sizeof(mn));
for(int i=1;i<=n;i++)
{
mn[i][i]=a[i];
for(int j=i+1;j<=n;j++)mn[i][j]=min(mn[i][j-1],a[j]);
}
memset(dp,-1,sizeof(dp));
dp[0][1]=n;
for(int i=1;i<=min(n,q);i++)
{
bool ed=1;
int d,s,pre=-1,p=-1;
cin>>d>>s;
for(int j=1;j<=n;j++)
{
if(j-d>=1)pre=max(pre,dp[i-1][j-d]);
if(j-d>=1&&mn[j-d][j-1]>=s)dp[i][j]=max(dp[i][j],pre);
}
for(int j=1;j<=n;j++)
{
if(j-d+1>=1&&mn[j-d+1][j]>=s)p=max(p,j-d+1);
rmx[j]=p;
}
for(int j=1;j<=n;j++)
{
if(rmx[dp[i-1][j]]-1>=j)dp[i][j]=max(dp[i][j],rmx[dp[i-1][j]]-1);
if(dp[i][j]<j)dp[i][j]=-1;
if(rmx[dp[i-1][j]]==j)ed=0;
}
for(int j=1;j<=n;j++)if(dp[i][j]!=-1)ed=0;
if(ed)
{
cout<<i-1;
return 0;
}
}
cout<<q;
return 0;
}

Luogu P9180 [COCI2022-2023#5] Slastičarnica 题解 [ 蓝 ] [ 区间 dp ] [ dp 状态优化 ] [ 前缀和优化 ]的更多相关文章

  1. luogu P1549 棋盘问题(2) 题解

    luogu P1549 棋盘问题(2) 题解 题目描述 在\(N * N\)的棋盘上\((1≤N≤10)\),填入\(1,2,-,N^2\)共\(N^2\)个数,使得任意两个相邻的数之和为素数. 例如 ...

  2. 【luogu P1314 聪明的质监员】 题解

    题目链接:https://www.luogu.org/problemnew/show/P1314 二分答案 但是计算区间贡献的时候 直接暴力会挂 前缀和加速 #include <cstdio&g ...

  3. BZOJ 2023 [Usaco2005 Nov]Ant Counting 数蚂蚁:dp【前缀和优化】

    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2023 题意: 有n个家族,共m只蚂蚁(n <= 1000, m <= 1000 ...

  4. 题解——洛谷P2734 游戏A Game 题解(区间DP)

    题面 题目背景 有如下一个双人游戏:N(2 <= N <= 100)个正整数的序列放在一个游戏平台上,游戏由玩家1开始,两人轮流从序列的任意一端取一个数,取数后该数字被去掉并累加到本玩家的 ...

  5. 【题解】POJ1934 Trip (DP+记录方案)

    [题解]POJ1934 Trip (DP+记录方案) 题意: 传送门 刚开始我是这么设状态的(谁叫我DP没学好) \(dp(i,j)\)表示钦定选择\(i\)和\(j\)的LCS,然而你会发现这样钦定 ...

  6. 【题解】剪纸条(dp)

    [题解]剪纸条(dp) HRBUST - 1828 网上搜不到题解?那我就来写一篇吧哈哈哈 最优化问题先考虑\(dp\),设\(dp(i)\)表示将前\(i\)个字符(包括\(i\))分割成不相交的回 ...

  7. 【题解】ARC101F Robots and Exits(DP转格路+树状数组优化DP)

    [题解]ARC101F Robots and Exits(DP转格路+树状数组优化DP) 先删去所有只能进入一个洞的机器人,这对答案没有贡献 考虑一个机器人只能进入两个洞,且真正的限制条件是操作的前缀 ...

  8. 【题解】地精部落(DP)

    [题解]地精部落(DP) 设\(f_i\)表示强制第一个是谷的合法方案数 转移枚举一个排列的最大值在哪里,就把序列分成了互不相干的两个部分,把其中\(i-1\choose j-1\)的数字分配给前面部 ...

  9. 【luogu P2279 [HNOI2003]消防局的设立】 题解

    题目链接:https://www.luogu.org/problemnew/show/P2279 想怎么贪怎么贪 #include <queue> #include <cstdio& ...

  10. 【luogu P2762 太空飞行计划问题】 题解

    题目链接:https://www.luogu.org/problemnew/show/P2762 算是拍照那个题的加强下. 输入真的很毒瘤.(都这么说但好像我的过了?) #include <qu ...

随机推荐

  1. Node.js Express 框架(1)

    1.Express介绍 Express 是一个简洁而灵活的 node.js Web应用框架, 提供了一系列强大特性帮助你创建各种 Web 应用,和丰富的 HTTP 工具. Express的特点: 实现 ...

  2. 出现警告信息 Please enter a commit message to explain why this merge is necessary,

    Please enter a commit message to explain why this merge is necessary, # especially if it merges an u ...

  3. R数据分析:临床研究样本量计算、结果解读与实操

    很久之前给大家写过一篇文章详细介绍了样本量计算的底层逻辑,不过那篇文章原理是依照卡方比较来写的,可以拓展到均值比较,但视角还是比较小,今天从整个临床研究的角度结合具体的例子谈谈大家遇到的样本量的计算方 ...

  4. 基于.NET WinForm开发的一款硬件及协议通讯工具

    前言 今天大姚给大家分享一款基于.NET WinForm开发的一款硬件及协议通讯工具:PLC-CommunTools. 项目介绍 PLC-CommunTools是一款基于.NET WinForm开发的 ...

  5. 【C#】【报错解决】找不到请求的Net Framework Data ProVider。可能没有安装。

    如题报错截图如上,解决方法如下 第一步:找到[引用]中的MySql.Data中的版本号 第二步,在Web.config中添加如下配置 <system.data> <DbProvide ...

  6. 【Java高级编程】Java多线程学习笔记

    Java 多线程 目录 Java 多线程 1.多线程创建 方法1:通过 继承 thread 类 方法2:通过 实现 Runnable 接口 2.线程中的相关方法 (1)设置优先级 setPrlorty ...

  7. git clone 指定 ssh-key 文件

    环境 & 软件 mac OS 问题 git clone 不是默认 ssh-key,无法克隆 解决方法 用ssh-add命令将对应的私钥加入到缓存 // ssh-add 自定义名称 // 例子 ...

  8. .NET Core 类型系统(Types System)底层原理浅谈

    C#类型系统 C# 是一种强类型语言. 每个变量和常量都有一个类型,每个求值的表达式也是如此. 每个方法声明都为每个输入参数和返回值指定名称.类型和种类(值.引用或输出). .NET 类库定义了内置数 ...

  9. Qt开发经验小技巧146-150

    Qt中自带的很多控件,其实都是由一堆基础控件(QLabel.QPushButton等)组成的,比如日历面板 QCalendarWidget 就是 QToolButton+QSpinBox+QTable ...

  10. 23种设计模式实战:重学Java设计模式

    23种设计模式实战PDF: 链接:https://pan.baidu.com/s/1XfjkBt19G7jZQfwk5wAV3w 提取码:1234