20221104刷题记录

CF510D Fox And Jumping

给定 n n n 张卡,每张卡有 a i a_i ai 和费用 c i c_i ci,选一些卡让这些卡的 a i a_i ai gcd 为 1 1 1,求最小的费用。 n ≤ 300 , a i ≤ 1 0 9 n \leq 300,a_i \leq 10^9 n300,ai109

显然要 dp。设 f [ i ] [ j ] f[i][j] f[i][j] 表示考虑到第 i i i 张卡且 gcd 为 j j j 的最小费用。

f [ i ] [ j ] = min ⁡ k = 1 i − 1 { f [ i ] [ ( j , a i ) ] + c i } f[i][j]=\min_{k=1}^{i-1}\{f[i][(j,a_i)]+c_i\} f[i][j]=k=1mini1{f[i][(j,ai)]+ci}

时间复杂度 O ( n 2 V ) O(n^2V) O(n2V)。思考优化。

任何数的 gcd 都是这个数的因子。因此可以预处理出所有 a i a_i ai 的因子,然后做个映射。这样可以把空间降下来。还要滚动数组。

CF1294F Three Paths on a Tree

给定一棵 n n n 个结点的树,求三个点,使得这三个点路径的并集最大。 n ≤ 2 × 1 0 5 n \leq 2\times 10^5 n2×105

显然肯定要选直径的两个点的,问题在于第三个点怎么选。很简单:求出直径之后,把所有直径上的点扔到队列里 bfs,离直径最远的那个点就是第三个点。

注意特判整棵树是个链的情况。以及直径的长度不等于经过的点数,像我一样用 dfs 的需要注意处理。

CF852B Neural Network country

这个比较说不清,建议看原题(洛谷那个翻译很差)。

给定一个有向分层图,每层都有 n n n 个点,分 L L L 层;每条边有权值 a i a_i ai。层与层之间的边连接方式、权值排列方式均相同。求有多少条从 S S S T T T 的路径权值和为 m m m 的倍数。 L ≤ 1 0 5 , n ≤ 1 0 6 , m ≤ 200 L \leq 10^5,n\leq 10^6,m \leq 200 L105,n106,m200

w i w_i wi 表示两层间权值为 i i i 的数量。

考虑 dp。设 f [ i ] [ j ] f[i][j] f[i][j] 表示到了第 i i i 层时余数为 j j j 的方案数。那么有:

f [ i ] [ j ] = ∑ k = 0 m f [ i ] [ j − w k ] f[i][j]=\sum_{k=0}^{m}f[i][j-w_k] f[i][j]=k=0mf[i][jwk]

直接转移是 O ( n 2 m L ) O(n^2mL) O(n2mL) 的。但是你会发现,两层之间的转移是一模一样的。

f [ i + j ] = a [ i ] × b [ j ] f[i+j]=a[i]\times b[j] f[i+j]=a[i]×b[j]

也就是说这东西可以写成一个类似于卷的形式。能不能卷我不知道,不过反正这个是可以实现快速幂一样的转移了。

时间复杂度 O ( m log ⁡ L ) O(m \log L) O(mlogL)

dp 转移不一定要矩阵才能快速幂,如果两个阶段之间的转移一模一样,那可以考虑自己定义一种支持结合律的运算来快速幂。

P5355 [Ynoi2017] 由乃的玉米田

给定序列 a a a,每次询问给定一个符号 +-*/ 之一、一个区间 [ l , r ] [l,r] [l,r]和一个数 x x x,问 x x x 能不能用那个符号以及区间里的任意两个数运算得到。 n ≤ 1 0 5 , a i ≤ 1 0 5 n \leq 10^5,a_i \leq 10^5 n105,ai105

发现值域很小,不过线段树大概率是会 MLE 的。这里用莫队。思考每个操作怎么做:

  • 加:开两个 bitsetb1 保存 x x x 是否在区间内,b2 保存 V − x V-x Vx 是否在区间内。询问时返回 ((b1<<(maxv-x)&b2)).count() 即可。
  • 减:更简单,返回 ((b1<<x)&b1).count() 即可。
  • 乘:枚举 i ∈ [ 1 , V ] i \in [1,\sqrt V] i[1,V ],如果 x i \frac{x}{i} ixb1 里则返回 true。
  • 除:枚举 i ∈ [ 1 , V ] i \in [1,V] i[1,V],如果 i x ix ixb1 里则返回 true。

可以发现瓶颈在除法:单次操作是 O ( n ) O(n) O(n) 的。

考虑根号分治。对于除法操作, ≥ V \ge \sqrt V V 的询问复杂度是没问题的,所以把那些 x ≤ V x \leq \sqrt V xV 的单独分出来处理。

单次操作是 O ( V ) O(\sqrt V) O(V ) 的,总时间复杂度是 O ( n V ) O(n \sqrt V) O(nV )

那些单独分出来的怎么处理?可以枚举 x ∈ [ 1 , V ] x \in [1,\sqrt V] x[1,V ],然后扫描整个数列。维护一个 p r e [ i ] pre[i] pre[i] 表示数字 i i i 上一次出现的位置、以及一个指针 l l l,然后当 p r e [ a i v ] pre[a_iv] pre[aiv] p r e [ a i v ] pre[\frac{a_i}{v}] pre[vai] 能够更新 l l l 的时候,更新。之后就可以 O ( 1 ) O(1) O(1) 回答询问了。

总时间复杂度是 O ( n V ) O(n \sqrt V) O(nV )

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值