Luogu P11230 CSP-J 2024 接龙 题解 [ 线性 dp ] [ 前缀和 ]
接龙:一个前缀和优化 dp 或者单调队列优化 dp 的题目。
怎么周围的人都秒了 T3 不会 T4 啊,只有我觉得 T4 很套路,T3 比较难写吗。
暴力 dp
为了避免多维的状态定义,我们把每个人的子序列化为长度最多为 \(2\times 10^5\) 的一维序列,并记录下每一张牌对应的人是谁。记这个一维序列的长度为 \(tot\),显然 \(tot=\sum_{i=1}^{n} l_i\)。
我们定义状态 \(dp_{i,j}\) 表示当前进行到第 \(i\) 轮,且该轮以一维序列中的第 \(j\) 张牌结尾是否可行。
有一个显然的转移,我们遍历第 \(j\) 张牌的前面 \(k-1\) 张牌(必须要是同一个人的),假设某张前面的牌所写的数字为 \(x\),那么我们可以遍历 \(r-1\) 层中不是同一个人的且值为 \(x\) 的人的牌转移过来,只要这些牌中有一个的结果为 \(1\),那么第 \(j\) 张牌的值就是 \(1\)。
时间复杂度 \(O(rn^2k)\)。
第一步优化
注意到我们的限制有一个是“不能从同一个人那里转移过来”,考虑一个和前几年提高组假期计划那题很像的想法。
原题中是记录前 \(3\) 大的值,目的是避免走到重复的景点。而这题我们可以借鉴它的思路,记录两个属于不同人的且可以转移过来牌。只要这两张牌中,有一张和我现在的牌所属的人不同,就是可以转移过来的。
这个可以通过在每一轮结束之后预处理一遍得到。
时间复杂度 \(O(rnk)\)。
第二步优化
到这里我们就快做完这题了。观察到一个数的结果为 \(1\),当且仅当前 \(k-1\) 位的预处理值中有一个可以转移。熟悉 dp 的人肯定能一下就想到单调队列优化,进行转移,时间复杂度就被降到了 \(O(rn)\)。
但这是普及组,不能考单调队列。于是我们换一种普及组思路。因为这题可以预处理,而查询操作是查询 \(l\) 到 \(r\) 之间有没有元素 \(1\),因此我们预处理之后前缀和一下就能做到 \(O(1)\) 查询有没有元素 \(1\) 了。
时间复杂度 \(O(rn)\)。
代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
int t,n,k,q,f[105][200005][2],a[200005],bl[200005],tot,can[200005];
bitset<200005>dp[105];
void init()
{
memset(f,-1,sizeof(f));
for(int r=1;r<=100;r++)
{
//count can
if(r==1)
{
for(int i=1;i<=tot;i++)can[i]=can[i-1]+(a[i]==1);
}
else
{
for(int i=1;i<=tot;i++)can[i]=can[i-1]+((f[r-1][a[i]][0]!=-1&&f[r-1][a[i]][0]!=bl[i])||(f[r-1][a[i]][1]!=-1&&f[r-1][a[i]][1]!=bl[i]));
}
//count dp
int pre=0;
for(int i=1;i<=tot;i++)
{
if(bl[i]!=bl[i-1])pre=i;
int rn=i-1;
int ln=max(pre,i-k+1);
dp[r][i]=((can[rn]-can[ln-1])>0);
}
//count f
for(int i=1;i<=tot;i++)
{
if(dp[r][i]==0)continue;
if(f[r][a[i]][0]==-1)f[r][a[i]][0]=bl[i];
else if(f[r][a[i]][1]==-1&&f[r][a[i]][0]!=bl[i])f[r][a[i]][1]=bl[i];
}
// for(int i=1;i<=tot;i++)
// {
// cout<<"can["<<r<<"]["<<i<<"]="<<can[i]<<endl;
// }
// for(int i=1;i<=tot;i++)
// {
// cout<<"f["<<r<<"]["<<i<<"][0]="<<f[r][i][0]<<endl;
// cout<<"f["<<r<<"]["<<i<<"][0]="<<f[r][i][1]<<endl;
// }
}
}
void solve()
{
scanf("%d%d%d",&n,&k,&q);
tot=0;
for(int i=1;i<=n;i++)
{
int l;
scanf("%d",&l);
for(int j=1;j<=l;j++)
{
tot++;
scanf("%d",&a[tot]);
bl[tot]=i;
}
}
init();
while(q--)
{
int r,c;
scanf("%d%d",&r,&c);
printf("%d\n",(f[r][c][0]!=-1||f[r][c][1]!=-1));
}
}
int main()
{
freopen("chain.in","r",stdin);
freopen("chain.out","w",stdout);
scanf("%d",&t);
while(t--)solve();
return 0;
}
Luogu P11230 CSP-J 2024 接龙 题解 [ 线性 dp ] [ 前缀和 ]的更多相关文章
- CF10D-LCIS题解--线性DP+打印方案
题目链接: https://www.luogu.org/problemnew/show/CF10D 方法一 分析 \(LCS\)和\(LIS\)已经成烂大街的知识了,可是当这两个合并起来成为\(LCI ...
- 上午小测3 T1 括号序列 && luogu P5658 [CSP/S 2019 D1T2] 括号树 题解
前 言: 一直很想写这道括号树..毕竟是在去年折磨了我4个小时的题.... 上午小测3 T1 括号序列 前言: 原来这题是个dp啊...这几天出了好几道dp,我都没看出来,我竟然折磨菜. 考试的时候先 ...
- luogu P1549 棋盘问题(2) 题解
luogu P1549 棋盘问题(2) 题解 题目描述 在\(N * N\)的棋盘上\((1≤N≤10)\),填入\(1,2,-,N^2\)共\(N^2\)个数,使得任意两个相邻的数之和为素数. 例如 ...
- CSP J/S 初赛总结
CSP J/S 初赛总结 2021/9/19 19:29 用官方答案估计 J 涂卡的时候唯一的一支 2B 铅笔坏了,只能用笔芯一个个涂 选择 \(-6\ pts\) 判断 \(-3\ pts\) 回答 ...
- luogu2657-Windy数题解--数位DP
题目链接 https://www.luogu.org/problemnew/show/P2657 分析 第一道数位DP题,发现有点意思 DP求\([L,R]\)区间内的XXX个数,很套路地想到前缀和, ...
- Blocks题解(区间dp)
Blocks题解 区间dp 阅读体验...https://zybuluo.com/Junlier/note/1289712 很好的一道区间dp的题目(别问我怎么想到的) dp状态 其实这个题最难的地方 ...
- 模拟赛 提米树 题解 (DP+思维)
题意: 有一棵棵提米树,满足这样的性质: 每个点上长了一定数量的Temmie 薄片,薄片数量记为这个点的权值,这些点被标记为 1 到 n 的整数,其 中 1 号点是树的根,没有孩子的点是树上的叶子. ...
- 洛谷P2507 [SCOI2008]配对 题解(dp+贪心)
洛谷P2507 [SCOI2008]配对 题解(dp+贪心) 标签:题解 阅读体验:https://zybuluo.com/Junlier/note/1299251 链接题目地址:洛谷P2507 [S ...
- 方格取数(number) 题解(dp)
题目链接 题目大意 给你n*m个方格,每个格子有对应的值 你从(1,1)出发到(n,m)每次只能往下往上往右,走过的点则不能走 求一条路线使得走过的路径的权值和最大 题目思路 如果只是简单的往下和往右 ...
- 2019 CSP J/S第2轮 视频与题解
CSP入门组和提高组第二轮题解 转自网络
随机推荐
- uni-app项目button组件去不掉的灰色边框爬坑
前情 uni-app是我比较喜欢的跨平台框架,它能开发小程序/H5/APP(安卓/iOS),重要的是对前端开发友好,自带的IDE让开发体验非常棒,公司项目就是主推uni-app. 坑位 最近在开发个人 ...
- 为了改一行代码,我花了10多天时间,让性能提升了40多倍---Pascal架构GPU在vllm下的模型推理优化
ChatGPT生成的文章摘要 这篇博客记录了作者在家中使用Pascal显卡运行大型模型时遇到的挑战和解决方案.随着本地大型模型性能的提升,作者选择使用vllm库进行推理.然而,作者遇到了多个技术难题, ...
- 在 Ubuntu GUI 中以 root 身份登录
参考:https://zhuanlan.zhihu.com/p/610049537?utm_id=0 有一些桌面用户想以 root 身份登录.这不是什么明智之举,但肯定是可以做到的. 默认情况下,Ub ...
- JAVA中的时区设置
JAVA中的时区设置 第一种方式.通过代码指定. final TimeZone timeZone = TimeZone.getTimeZone("GTM+8"); Time ...
- Solon v3.0.5 发布!(Spring 生态可以退休了吗?)
Solon 框架! 新一代,面向全场景的 Java 应用开发框架.从零开始构建(非 java-ee 架构),有灵活的接口规范与开放生态. 追求: 更快.更小.更简单 提倡: 克制.高效.开放.生态 有 ...
- Qt血的教训/细数Qt开发的各种坑/又爱又恨/欢迎围观留言评论
一.吐槽总结 搞Qt开发十几年了,最初从Qt4.6开始,一直追新到现在的6.7版本,中间经历过无数的血的教训,简直是又爱又恨.其实Qt挺好的,但是还是要忍不住吐槽一下,本人还是希望Qt发展的越来越好, ...
- Qt/C++编写精美输入法(历时十年迭代/可换肤/支持Qt4/5/6/win/linux/mac/嵌入式等)
一.前言 大概是从2012年就开始研究用Qt写输入法,因为项目需要,嵌入式板子上,没有对应的输入法,当初使用过很多NVR,里面也是鼠标按下弹出输入法面板进行输入,可以切换数字和字母及中文,于是借鉴着操 ...
- Qt编写视频监控系统75-计算实时码率并显示
一.前言 做监控摄像头的实时视频显示,一般还会要求统计实时码率显示在通道画面上,一个是为了测试下整个软件的性能,同时也看下当前到底是主码流还是子码流,设备到底是不是真的按照设定的码流大小来传输视频数据 ...
- golang自带的死锁检测并非银弹
网上总是能看到有人说go自带了死锁检测,只要有死锁发生runtime就能检测到并及时报错退出,因此go不会被死锁问题困扰. 这说明了口口相传知识的有效性是日常值得怀疑的,同时也再一次证明了没有银弹这句 ...
- Linux服务器环境安装mysql
背景 1.安装环境:kvm虚拟机 2.运行环境:linux 3.架构:x86 4.安装mysql版本:mysql-5.7 1.安装准备 # Mysql官网 https://downloads.mysq ...