LeetCode-Day105(C++) 91. 解码方法

Vue3脚手架安装vue @/cli

  返回  

Namomo Summer Camp 2021 第一天专题讲解

2021/8/21 1:22:32 浏览:

Subset

题意:给出 n n n 个数,要求求出两个不相交的子集,使得他们的和一样。 n ≤ 1 × 1 0 5 n \leq 1\times 10^5 n1×105 a i ≤ 1 × 1 0 5 a_i \leq 1\times 10^5 ai1×105

解法:此题在 Atcoder 上出过一个类似题。考虑前 n n n 个元素构成的子集数目,有 2 n 2^n 2n 种子集,而前 n n n 个元素至多能构成的本质不同的数字只有 n max ⁡ { a i } ≤ n × 1 × 1 0 5 n\max\{a_i\} \leq n\times 1\times 10^5 nmax{ai}n×1×105,而实际构成的数目更是远远小于这个数字。不难发现,令 n = 22 n=22 n=22,则子集数目 2 22 = 4194304 > 1 × 1 0 5 × n = 2.2 × 1 0 6 2^{22}=4194304>1\times 10^5 \times n=2.2\times 10^6 222=4194304>1×105×n=2.2×106,由鸽巢原理知一定有和相同的不同子集。因而只需暴力枚举前 22 22 22 个元素构成的子集即可。

可以使用哈希表存储子集对应的和,对于和相同的两个不同子集,去掉两个集合的交集即可。

City Brain

来源:ICPC EC Final 2020 D

题意:给定点数为 n n n,边数为 m m m 的一个边权均为 1 1 1 的无向图。对于每条边,可以花费 x x x 元( x > 0 x>0 x>0),使得其边权变成 1 x + 1 \displaystyle \frac{1}{x+1} x+11。现在预先有 k k k 元,有两个人,分别从 s 1 , s 2 s_1,s_2 s1,s2 点走到 t 1 , t 2 t_1,t_2 t1,t2,问二人走过的边权和最小为多少。 n , m ≤ 5 × 1 0 3 n,m \leq 5\times 10^3 n,m5×103

解法:首先,无论怎么减,其边权均大于 0 0 0,而每条边边权均为 1 1 1,不难发现——无论在一条边上花费多少钱,都不如直接走最短路来的费用。因而只需要保留其最短路图即可。

再注意到一个事情——花费钱数是具有边际效应的,每多花一块钱其能减少的量单调递减(并且其递减速度非常快),因而一定是尽可能的更新那些没有减过或者花费钱数较少的边。注意:这里并不能保证每一个人走的路径段上每条边花费的钱数尽可能平均。

按照贪心的思路继续分析——二人会走公共段,并且如果有公共段必然是连续的一段。显然,如果存在多个公共段,例如 u 1 → v 1 u_1 \to v_1 u1v1,与 u 2 → v 2 u_2 \to v_2 u2v2,那么为什么二人不公共的走 v 1 → u 2 v_1 \to u_2 v1u2 呢?所以只会有一个公共段。但是公共段长度不一定最长,这里贪心无法成立。因而我们将边分成了个人段和公共段,在个人段和公共段上分别花费钱数平均。容易得到,对于长度为 l l l 的路径段,若修改次数为 x x x 次,则通过这一路径段的花费为 g ( x , l ) = x m o d    l ⌊ x l ⌋ + 2 + l − ( x m o d    l ) ⌊ x l ⌋ + 1 g(x,l)=\displaystyle \frac{x \mod l}{\lfloor \frac{x}{l} \rfloor +2}+\frac{l-(x \mod l)}{\lfloor \frac{x}{l} \rfloor+1} g(x,l)=lx+2xmodl+lx+1l(xmodl)

基于这一贪心,我们可以考虑枚举公共路径的长度。显然二人走的路径段数目恒定,因而确定了公共路径长度我们可以很快确定出二人剩下的单人路径长度,只需要 O ( n ) O(n) O(n) 的检查一下这样的公共路径段是否存在即可。此部分时间复杂度 O ( n 2 ) O(n^2) O(n2)。之后,我们需要均摊花的钱数。基于刚刚的贪心,不难发现其总的价值函数 f ( x ) = g ( x , l 1 ) + g ( k − x , l 2 ) f(x)=g(x,l_1)+g(k-x,l_2) f(x)=g(x,l1)+g(kx,l2) 为单峰函数,因而我们可以进行三分——三分出用于公共段与个人段分别用了多少钱,然后根据三分的转移即可。这样总复杂度仅 O ( n 2 + n log ⁡ k ) O(n^2+n \log k) O(n2+nlogk)

Mr. Panda and Typewriter

来源:CCPC Final 2019 C

题意:有一个打字机,有以下三个功能:

  1. x x x 的时间在文本最后打下一个字符。
  2. y y y 的时间复制一个连续子序列存入 buffer 中待粘贴。之前 buffer 中的子串会被清空。
  3. z z z 的时间将 buffer 中的子串粘贴到文本最后。此操作不会清空 buffer。

给定一篇长度为 n n n 的文章,问最短需要多长时间才能将其打完。 n ≤ 5 × 1 0 3 n \leq 5\times 10^3 n5×103

解法:显然,如果使用了 ctrl+C 操作,一定是要在之后 ctrl+V 的,否则就浪费了时间。

首先一个非常朴素的 DP 可以被设计出来—— f i , j , k f_{i,j,k} fi,j,k 表示打到第 i i i 个字符后,buffer 中存储了从 j j j 开始的长度为 k k k 的序列所需要的时间。但是数据范围明显不允许我们这么做。此时需大胆的删掉一个维度,变成 f i , j f_{i,j} fi,j 表示前 i i i 个字符,buffer 中存储了现在已经打出的字符串的最后 j j j 个字符,所需要的时间。可以发现这个也是可以成功转移的:

  1. 直接在字符串的末尾输入一个字符—— f i + 1 , k ← f i , j + x f_{i+1,k} \leftarrow f_{i,j}+x fi+1,kfi,j+x
  2. 使用粘贴—— f k , j ← f i , j + z + ( k − i − j ) x f_{k,j} \leftarrow f_{i,j}+z+(k-i-j)x fk,jfi,j+z+(kij)x k k k 为后面第一个完整包含 [ i − j + 1 , ⋯   , i ] [i-j+1,\cdots,i] [ij+1,,i] 字符串的区间右端点。中间的全部用操作 1 1 1 填满。
  3. f i + k , k ← f i , j f_{i+k,k} \leftarrow f_{i,j} fi+k,kfi,j [ i + 1 , ⋯   , i + k ] [i+1, \cdots ,i+k] [i+1,,i+k] 区间段是直接由之前的某个剪贴板状态剪贴而来。虽然这里可能会有损失(损失了剪贴板中的一些部分),但是我们取得是最小值,有重复是可以的。另一种写法是直接令 j = 0 j=0 j=0,这样显然也不会对答案有什么更劣的影响。

整体复杂度 O ( n 2 ) O(n^2) O(n2)

Bookcase Solidity United

题意:有 n n n 层书架,每层书架至多只能承受 a i a_i ai 的重量。现往每层书架上放 x x x 单个重量为 1 1 1 的物品, x x x 可以根据每一层的情况进行变化,如果超过其承受能力则该层书架被击碎, ⌊ x 2 ⌋ \displaystyle \lfloor \frac{x}{2} \rfloor 2x 个物品会掉落到地上,剩下的才会掉到下一个没有被击碎的书架。问击碎这 n n n 层书架至少需要放置多少个物品。 n ≤ 70 n \leq 70 n70 a i ≤ 150 a_i \leq 150 ai150

解法:看到这种 n n n 较小但是又不是那么小(无法进行状压 DP 的范围)时,可以考虑区间 DP。

首先显然贪心是不成立的——若在最高层与最底层中间存在有大量的 a i = 1 a_i=1 ai=1 的书架层,贪心的补满刚好需要击碎的重量就会导致中间大量的物品被浪费掉。这种情况应当提前击碎中间这些书架层,然后直接最高层和最底层对接。

f l , r , k f_{l,r,k} fl,r,k 表示击碎 [ l , r ] [l,r] [l,r] 的区间,最后还剩 k k k 个物品可以落下,最少需要几个物品。区间 DP 通常考察两种转移:

  1. 区间延申, f l , r , k → f l , r + 1 , max ⁡ ( k , a r + 1 ) 2 f_{l,r,k} \to f_{l,r+1,\frac{\max(k,a_{r+1})}{2}} fl,r,kfl,r+1,2max(k,ar+1):击碎了第 r r r 层直接击碎下一层。那么此时可以贪心的补足击碎下一层的球数。有递推 f [ i ] [ j ] [ max ⁡ ( k , a r + 1 ) 2 ] ← f [ i ] [ j ] [ k ] + max ⁡ ( 0 , a r + 1 − k ) f[i][j][\frac{\max(k,a_{r+1})}{2}] \leftarrow f[i][j][k]+\max(0,a_{r+1}-k) f[i][j][2max(k,ar+1)]f[i][j][k]+max(0,ar+1k)
  2. 区间合并:击碎了第 r r r 层,由于中间 [ r + 1 , p − 1 ] [r+1,p-1] [r+1,p1] 层全部已经被击碎,物品直接漏到第 p p p 层。那么转移为 f [ i ] [ j ] [ k + k 1 ] ← f [ i ] [ j ] [ k ] + f [ j ] [ p ] [ k 1 ] f[i][j][k+k_1] \leftarrow f[i][j][k]+f[j][p][k_1] f[i][j][k+k1]f[i][j][k]+f[j][p][k1]

此外还有一个贪心——显然不会“蓄能”,提前在一层放好多物品然后让它一口气落好多层,因为每过一层都会损失一半的物品,因而每次枚举的 k k k 的范围只有 [ 0 , a i ] [0,a_i] [0,ai]

Infimum of Paths

题意:有一个 n n n 个节点、 m m m 条边的带权有向图,边权 w w w 均为 [ 0 , 9 ] [0,9] [0,9],现在问能否从一个节点走到另一个节点,其权值为 ∑ i = 1 k 1 0 − i w e i \displaystyle \sum_{i=1}^{k} 10^{-i} w_{e_i} i=1k10iwei,其中 e i e_i ei 表示走过的第 i i i 段路径。问最小权值为多少。 n , m ≤ 5 × 1 0 3 n,m \leq 5\times 10^3 n,m5×103

解法:此题图中并没有说无环,因而环会成为一个极大的问题。并且容易注意到,某些环可能会影响到答案,使得路径长度变成无穷大——例如在某一个分岔口,走向终点的路径权值为 5 5 5,而顺着环上走的权值仅为 4 4 4。由于越靠近起点权值越大,并且后面走的权值不会影响前面的权值,而在换上每一轮走到这一岔口一定都是沿着环一直走下去,这样答案就变成了一个循环小数。

因而,考虑先处理无环的情况。先进行 n + 1 n+1 n+1 轮的 bfs 扩展,到着的每一个点记录从起点走到这个点的最小权值(题目中的权值)。这里可以采用基数排序,每一个点维护一个长度为 n n n 的到达序列。因而这里总的时空复杂度均为 O ( n 2 ) O(n^2) O(n2)

接下来考虑有环的情况。如果不在到终点的权值最小的路径上也不用管了,那么现在就是在最小权值的路径上出现了环。可以考虑 O ( n ) O(n) O(n) 的算出这个环上的路径带来的权值(仅算一圈即可),然后去比较一下不走完整环,直接去终点的权值,如果发现更小则从这个环开始无限循环下去。

Bytelandia States Union

题意:从坐标平面上 ( s 1 , t 1 ) (s_1,t_1) (s1,t1) 走到 ( s 2 , t 2 ) (s_2,t_2) (s2,t2),在 ( x , y ) (x,y) (x,y) 点,走到 ( x + 1 , y ) (x+1,y) (x+1,y) 的代价为 2 x y 2 + 2 y 2 + x 2 2xy^2+2y^2+x^2 2xy2+2y2+x2,走到 ( x − 1 , y ) (x-1,y) (x1,y) 的代价为 − 2 x y 2 + 2 y 2 + x 2 -2xy^2+2y^2+x^2 2xy2+2y2+x2,走到 ( x , y + 1 ) (x,y+1) (x,y+1) 的代价为 2 x 2 y + 2 x 2 + y 2 2x^2y+2x^2+y^2 2x2y+2x2+y2,走到 ( x , y − 1 ) (x,y-1) (x,y1) 的代价为 − 2 x 2 y + 2 x 2 + y 2 -2x^2y+2x^2+y^2 2x2y+2x2+y2。问其最小代价。

解法:通过配凑容易发现,以上四个式子可以合并为一个:若从 ( x s , y s ) (x_s,y_s) (xs,ys) 走到 ( x t , y t ) (x_t,y_t) (xt,yt),则代价为 x t 2 y t 2 − x s 2 y s 2 + x s 2 + y s 2 x_t^2y_t^2-x_s^2y_s^2+x_s^2+y_s^2 xt2yt2xs2ys2+xs2+ys2。那么从 ( s 1 , t 1 ) (s_1,t_1) (s1,t1) 走到 ( s 2 , t 2 ) (s_2,t_2) (s2,t2),其代价为 s 2 2 t 2 2 − s 1 2 t 1 2 + ∑ ( x 2 + y 2 ) s_2^2t_2^2-s_1^2t_1^2+\sum(x^2+y^2) s22t22s12t12+(x2+y2),即路径上每个点的横纵坐标的平方。

可以证明:从 ( x 1 , y 1 ) (x_1,y_1) (x1,y1) 走到 ( x 2 , y 2 ) (x_2,y_2) (x2,y2),一定是走最短路径。不失一般性的,考虑从 ( x 1 , y ) (x_1,y) (x1,y) 走到 ( x 2 , y ) (x_2,y) (x2,y) x 1 < x 2 x_1<x_2 x1<x2 y > 0 y>0 y>0。直接走的答案即是 ∑ i = x 1 x 2 i 2 + y 2 ( x 2 − x 1 ) \displaystyle \sum_{i=x_1}^{x_2} i^2+y^2(x_2-x_1) i=x1x2i2+y2(x2x1),如果为了贪图更小的 y y y,而在第一步向下走,最后一步向上走,容易发现其变化量为 ( − 2 y + 1 ) ( x 2 − x 1 ) + x 1 2 + x 2 2 + 2 y 2 (-2y+1)(x_2-x_1)+x_1^2+x_2^2+2y^2 (2y+1)(x2x1)+x12+x22+2y2,一定是得不偿失。所以直接走最短路径。

此外,继续考虑贪心。如果 x 1 < x 2 x_1<x_2 x1<x2 y 1 < y 2 y_1<y_2 y1<y2,一个简单的贪心想法是每次只挑横纵坐标小的走。当 x < y x<y x<y 时,变化 x x x 比变化 y y y 好,反之亦然。若 x 1 > x 2 x_1>x_2 x1>x2 y 1 < y 2 y_1<y_2 y1<y2,则是先将 y y y 减小再移动 x x x

Mr.Panda and Cactus

来源:CCPC Final 2018 E

题意:给定一颗 n n n 个节点 m m m 条带边权的仙人掌,现在对其上的 n n n 个点进行染色,要求使用恰好 k k k 种颜色,最后统计两端点颜色不同边的边权和,求边权和的最小值。 k ≤ 1 × 1 0 3 k\leq 1\times 10^3 k1×103 n , m ≤ 1 × 1 0 5 n,m \leq 1\times 10^5 n,m1×105

解法:由于仙人掌的性质,每条边至多只会出现在一个环上。先用跑 tarjan 跑出仙人掌的环,将边区分树边和非树边。

注意到本题并没有询问究竟是如何染色的,因而不应该考虑染色方案,而应该直接考虑统计答案。出于贪心,一定是让一个连通块内全部染上同一个颜色,尽可能的增加同一颜色边数目,因而本题染色的实质是将原图划分为 k k k 个联通块。

考虑如何统计答案。记 f i , j f_{i,j} fi,j 为遍历了前 i i i 条边,将原图划分为了 j j j 个联通块其最小边权和。这里的边可以按任意顺序去遍历,同时要分树边和非树边去考虑。对于非树边,砍断 k k k 个非树边连通块数目增加 k − 1 k-1 k1,而树边则是增加 k k k 个。因而可以实现转移。

整体复杂度 O ( n k ) O(nk) O(nk)

Query on a Tree

题意:给定一棵 n n n 个点的树,树上有点权 a i a_i ai,初始点权均为 0 0 0,有以下一些操作:

  1. x x x 的点权增加 1 1 1
  2. 查询整棵树上 min ⁡ 1 ≤ j ≤ n ∑ i = 1 n a i d i s ( i , j ) \displaystyle \min_{1 \leq j \leq n} \sum_{i=1}^n a_i {\rm dis}(i,j) 1jnmini=1naidis(i,j),其中 d i s ( i , j ) {\rm dis}(i,j) dis(i,j) 表示 i i i j j j 的最短距离。若存在多个 j j j 满足条件,要求输出离 1 1 1 号节点更近的答案。

解法:不难发现,操作二的答案就是带权重树的重心。

显然可以有一个结论——带权树重心的祖先的子树权重和一定严格大于整棵树权重总和的一半。这里可以由树的重心的定义快速得到。

由于最后是要求离 1 1 1 号节点更近,因而不妨以 1 1 1 号节点作为根节点,对树进行一个 dfs。得到这个树的 dfs 序后,可以按照这样的方式得到一个序列——按照 dfs 序的先后,将 i i i 这一数字连续写 a i a_i ai 次。因而最后的答案就是这个序列的最中间的数字。因而可以根据 dfs 序搭建一个线段树(即树链剖分),其中第 i i i 个位置放置其对应的出现次数,然后查询的时候根据出现次数二分出最中间的数字是多少。

整体复杂度 O ( q log ⁡ 2 n ) O(q \log^2n) O(qlog2n)

Beautiful Sequence Unraveling

题意:定义一个长度为 n n n 的序列为美的序列—— ∀ i ∈ [ 1 , n ) \forall i \in [1,n) i[1,n) min ⁡ 1 ≤ j ≤ i { a j } ≠ max ⁡ i + 1 ≤ j ≤ n { a j } \displaystyle \min_{1 \leq j \leq i} \{ a_j\} \neq \max_{i+1 \leq j \leq n} \{a_j\} 1jimin{aj}=i+1jnmax{aj}。问长度为 n n n,每个数字均在 [ 1 , k ] [1,k] [1,k] 范围中的美的序列有多少个。 n ≤ 400 n \leq 400 n400 k ≤ 1 × 1 0 8 k \leq 1\times 10^8 k1×108

解法:考虑最朴素的求解。定义 DP 状态 f x , y f_{x,y} fx,y 为长度为 x x x 的序列,包含 [ 1 , y ] [1,y] [1,y] 的美的序列数目,满足 y ≤ x y \leq x yx。显然直接求美的序列是非常复杂的,因而考虑反选——答案即为 y x y^x yx 减去 ∃ i ∈ [ 1 , n ) \exist i \in [1,n) i[1,n) min ⁡ 1 ≤ j ≤ i { a j } = max ⁡ i + 1 ≤ j ≤ x { a j } \displaystyle \min_{1 \leq j \leq i} \{a_j\}=\max_{i+1 \leq j \leq x} \{a_j\} 1jimin{aj}=i+1jxmax{aj} 的序列数目。

t t t 为最大的满足上述条件的 i i i,则容易得到, t t t 右侧的一定是一个美丽序列,否则不满足最大条件。并且, t t t 右侧的元素统统大于左侧的元素。枚举 t t t,记左侧元素的最大值为 m m m,则有 f x , y ← ( f x − t , y − m + 1 − f x − t , y − m ) ( m t − ( m − 1 ) t ) f_{x,y}\leftarrow (f_{x-t,y-m+1}-f_{x-t,y-m})(m^t-(m-1)^t) fx,y(fxt,ym+1fxt,ym)(mt(m1)t)。其含义为, t t t 右侧的方案数即为 f x − t , y − m + 1 − f x − t , y − m f_{x-t,y-m+1}-f_{x-t,y-m} fxt,ym+1fxt,ym,因为必须取到最小的值 m m m;左侧可以任选,但是必须要求最大值为 m m m,所以方案为 m t − ( m − 1 ) t m^{t}-(m-1)^t mt(m1)t

考虑优化这一式子。 f x , y = ∑ t = 1 x ∑ m = 1 i ( f x − t , y − m + 1 − f x − t , y − m ) ( m t − ( m − 1 ) t ) \displaystyle f_{x,y}=\sum_{t=1}^{x} \sum_{m=1}^i (f_{x-t,y-m+1}-f_{x-t,y-m})(m^t-(m-1)^t) fx,y=t=1xm=1i(fxt,ym+1fxt,ym)(mt(m1)t)。单独考虑 ( f x − t , y − m + 1 − f x − t , y − m ) m t = m x f x − t , y − m + 1 − f x − t , y − m m x − t \displaystyle (f_{x-t,y-m+1}-f_{x-t,y-m}) m^t=m^{x}\frac{f_{x-t,y-m+1}-f_{x-t,y-m}}{m^{x-t}} (fxt,ym+1fxt,ym)mt=mxmxtfxt,ym+1fxt,ym,容易发现在 x x x 固定的情况下, x − t x-t xt 被天然绑定了,因而可以考虑前缀和优化,拿出固定的 m x m^x mx,优化掉一维。因而这个 O ( n 4 ) O(n^4) O(n4) 的 DP 就被我们优化到了 O ( n 3 ) O(n^3) O(n3)

注意我们 DP 数组的真正含义——恰好使用 y y y 个数字,构成长度为 n n n 的美的序列的个数,因而最后再使用组合数公式,答案即为 ∑ i = 1 n ( k i ) f n , i \displaystyle \sum_{i=1}^n \dbinom{k}{i} f_{n,i} i=1n(ik)fn,i

联系我们

如果您对我们的服务有兴趣,请及时和我们联系!

服务热线:18288888888
座机:18288888888
传真:
邮箱:888888@qq.com
地址:郑州市文化路红专路93号