【题解】P9749 [CSP-J 2023] 公路
\(Meaning\)

\(Solution\)
这道题我来讲一个不一样的解法:\(dp\)
在写 \(dp\) 之前,我们需要明确以下几个东西:状态的表示,状态转移方程,边界条件和答案的表示。
状态的表示
\(dp[i]\) 表示到达第 \(i\) 个站点所需要的最少钱数, \(w[i]\) 表示在使用最少钱数到达第 \(i\) 个站点时多余的路程。
状态转移方程
dp[i]=dp[i-1]+\bigg\lceil\frac{v[i-1]-w[i-1]}{d}\bigg\rceil\times pre\_min(i-1)
\]
w[i]=\bigg\lceil\frac{v[i-1]-w[i-1]}{d}\bigg\rceil-v[i-1]+w[i-1]
\]
其中 \(pre\_min(i)\) 表示前 \(i\) 个站点中最小的油价。
边界条件
dp[i]=0,w[i]=0
\]
答案的表示
dp[n]
\]
问题
在状态转移方程中,怎样在 \(O(1)\) 的时间复杂度下完成 \(pre\_min\) 函数呢?
这就涉及到了一个算法:
\(ST\) 表
在算法和数据结构中,ST表(Sparse Table)是一种用于解决区间查询问题的数据结构。它可以有效地回答各种形式的查询,例如最小值、最大值、区间和等。
简介
ST表的主要思想是通过预处理来加速区间查询。它使用倍增 DP 的思想将一个数组分割成多个子区间,并在每个子区间上计算出某种操作的结果。然后,根据这些预先计算好的结果,我们可以根据需要合并区间来回答各种查询。
具体的实现过程如下:
- 初始化ST表,ST表是一个二维数组。
- 将输入的原始数组填充到ST表的第一行。
- 使用递推关系填充ST表的其他行,直到得到完整的ST表。
- 根据查询的起始位置和区间长度,在ST表中找到对应区间的值,结合适当的操作得出最终结果。
查询操作
对于任何查询操作,我们可以使用以下步骤来回答:
计算出查询区间的长度len。
找到大于等于len的最大值j,使得2^j <= len。
使用预处理的结果和递推关系,在ST表中找到对应的值,并结合适当的操作得到查询结果。
这种方法的时间复杂度为O(1),因为我们只需进行几次常数级别的操作即可回答查询。
应用场景
ST表在解决各种区间查询问题时非常有用。以下是一些常见的应用场景:
- 查询最小值/最大值:通过选择适当的查询操作,在O(1)的时间复杂度内回答每个查询。
- 区间和查询:可以通过使用累积和来实现区间和查询。
- 区间gcd查询:可以通过预处理和递推关系计算区间内的最大公约数。
总结
ST表是一种高效解决区间查询问题的数据结构。通过预先计算和递推关系,我们可以在O(1)的时间复杂度内回答各种形式的查询。它的实现相对简单且灵活,适用于多种应用场景。
模板
初始化(时间复杂度 \(O(\log_2n)\) )
for(int i=1;i<=n;i++) {
st[i][0]=a[i];
}
for(int j=1;(1<<j)<=n;j++) {
for(int i=1;i+(1<<j)-1<=n;i++) {
st[i][j]=min(st[i][j-1],st[i+(1<<(j-1))][j-1]);
}
}
查询(时间复杂度 \(O(1)\) )
l=1,r=i-1,len=log2(r-l+1);
pm=min(st[l][len],st[r-(1<<len)+1][len]);
解决问题
有了ST表,我们就可以在O(1)的时间复杂度中查询最值了,那我们程序的最终问题:TLE也解决了。程序整体时间复杂度为O(n),可以通过此题。
AC代码如下。
\(Accept\ Code\)
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll N=1e5+5;
ll v[N],a[N],w[N],dp[N],st[N][20];
ll n,d,l,r,len,pm;
int main() {
cin>>n>>d;
for(int i=1;i<n;i++) {
cin>>v[i];
}
for(int i=1;i<=n;i++) {
cin>>a[i];
}
for(int i=1;i<=n;i++) {
st[i][0]=a[i];
}
for(int j=1;(1<<j)<=n;j++) {
for(int i=1;i+(1<<j)-1<=n;i++) {
st[i][j]=min(st[i][j-1],st[i+(1<<(j-1))][j-1]);
}
}
for(int i=2;i<=n;i++) {
l=1,r=i-1,len=log2(r-l+1);
pm=min(st[l][len],st[r-(1<<len)+1][len]);
dp[i]=dp[i-1]+ceil(1.0*(v[i-1]-w[i-1])/d)*pm;
w[i]=ceil(1.0*(v[i-1]-w[i-1])/d)*d-(v[i-1]-w[i-1]);
}
cout<<dp[n];
return 0;
}
【题解】P9749 [CSP-J 2023] 公路的更多相关文章
- CSP J/S 初赛总结
CSP J/S 初赛总结 2021/9/19 19:29 用官方答案估计 J 涂卡的时候唯一的一支 2B 铅笔坏了,只能用笔芯一个个涂 选择 \(-6\ pts\) 判断 \(-3\ pts\) 回答 ...
- 2019 CSP J/S第2轮 视频与题解
CSP入门组和提高组第二轮题解 转自网络
- 【游记】CSP J/S 2019 游记
J 组 \(2:30\)开始, \(2:13\)还在酒店的我看了看手表...飞奔考场. T1 数字游戏 秒切. 下午某中学某大佬说可用线性基(%) T2 公交换乘 用单调队列思想,秒切. T3 纪念品 ...
- CSP J/S 2019受虐记
一枚蒟蒻的游记~ 提高组DAY1 不是说每场考试都有一道签到题吗 那我tm读了三遍题硬是没找到一道水题是怎么回事(是我太弱了吗) 没办法,硬着头皮做T1 暴力写法...期望得分30pts 于是...在 ...
- 【题解】 [HNOI/AHOI2018]道路 (动态规划)
懒得复制,戳我戳我 Solution: \(dp[i][j][k]\)以\(i\)为子树根节点,到根节点中有\(j\)条公路没修,\(k\)条铁路没修,存子树不便利和 \(dp[i][j][k]=mi ...
- 【codeforces】【比赛题解】#855 Codefest 17
神秘比赛,以<哈利波特>为主题……有点难. C题我熬夜切终于是写出来了,可惜比赛结束了,气啊. 比赛链接:点我. [A]汤姆·里德尔的日记 题意: 哈利波特正在摧毁神秘人的分灵体(魂器). ...
- [游记]2020/CSP - S总结
2020 / C S P − S 总 结 2020/CSP - S总结 2020/CSP−S总结 这年的 C S P CSP CSP考的不是很理想,本来稳进的 C S P − J CSP-J CSP− ...
- Atcoder 2159 連結 / Connectivity(并查集+map乱搞)
問題文N 個の都市があり.K 本の道路と L 本の鉄道が都市の間に伸びています. i 番目の道路は pi 番目と qi 番目の都市を双方向に結び. i 番目の鉄道は ri 番目と si 番目の都市を双 ...
- 洛谷 P1373 小a和uim之大逃离 Label:dp 不会
题目背景 小a和uim来到雨林中探险.突然一阵北风吹来,一片乌云从北部天边急涌过来,还伴着一道道闪电,一阵阵雷声.刹那间,狂风大作,乌云布满了天空,紧接着豆大的雨点从天空中打落下来,只见前方出现了一个 ...
- 【CodeForces 261B】Maxim and Restaurant(DP,期望)
题目链接 第一种解法是$O(n^3*p)$的:f[i][j][k]表示前i个人进j个人长度为k有几种方案(排列固定为123..n时).$f[i][j][k]=f[i-1][j][k]+f[i-1][j ...
随机推荐
- scroll-view横向滚动的问题
最近在做一个小程序的项目,在写demo的时候,需要用到scroll-view来实现横向滚动的效果: 按照官方文档来写简直坑到家了,正确的写法如下: <scroll-view scroll-x=& ...
- 什么是全同态加密(FHE)中的自举(Bootstrapping)?
PrimiHub一款由密码学专家团队打造的开源隐私计算平台,专注于分享数据安全.密码学.联邦学习.同态加密等隐私计算领域的技术和内容. 全同态加密(Fully Homomorphic Encrypti ...
- vscode报错Already included file name ‘xxx‘ differs from file name ‘xxx‘ only in casing的解决方法:
场景:我们创建了一个文件是小写开头的,又改成大写开头的. 比如: relationDemo.vue 改成 RelationDemo.vue 原因:缓存的判重逻辑是不区分大小写导致的.在这种情况下,vs ...
- freeswitch的gateway实现出中继的主备方案
概述 freeswitch是一款简单好用的VOIP开源软交换平台. 某些呼叫场景中,我们有2条出中继线路可选,2条出中继需要按照主备模式来配置,优先使用主中继呼叫,当主中继出现问题时,呼叫自动转移到备 ...
- Java求一个集合的所有子集
转载请注明出处: 求一个集合的所有子集表示从一个集合当中,任取任意项或不取,所能得到的所有结果,比如有一个集合{a,b,c,d},那么{a,b}, {b, d}等都是它的子集,空集也是它的子集, 一个 ...
- 让vs自动提示没有using的类
默认情况下,没有using的类,敲代码时没有智能提示,需要在[工具]->[选项]中开启
- [转帖]OutOfMemory JVM参数一览
https://www.cnblogs.com/kuroro/p/11707951.html JVM提供了有用的参数来处理OutOfMemoryError.在本文中,我们要强调那些JVM参数.在对Ou ...
- [转帖]ESXi主机RAID卡_HBA卡_网卡 型号_固件_驱动查询
https://www.cnblogs.com/vincenshen/p/12332142.html 一.RAID卡/HBA卡 型号_固件_驱动查询 1. 查询所有SCSI设备列表 # esxcfg- ...
- vim工具极简总结
vim工具总结 背景 很多操作记不住. 想着总结当笔记使用. 备忘 基本总结 vim somefile 打开/新建文件 i/a/insert按键 进入插入模式 insert 连续两次 进入替换模式 e ...
- [转帖]jdbc连接mysql设置session variables 参数变量
目录 两种方式 连接串设置[^1] 执行语句中设置 两种方式 url连接串中设置 执行语句中设置 连接串设置1 sessionVariables jdbc.url=jdbc:mysql://xxxx. ...