2021年第44周总结

2021年第44周总结

11.1

判断线段相交问题

解决计算几何中判断两个直线相交问题,通过矢量叉乘判断向量的相对位置,叉乘也可判断凸包等。

博客

LeetCode 335

CF 751

Problem D

此题属于BFS中边数较多的情况,尝试采用删点的方法降低时间复杂度,删除后某些点将不会被搜索到。

可以使用Set维护待搜索的点集合。

思路&难点:Set优化的BFS。

LC No.265

Probelm D

编辑距离超级加强版。

一开始考虑 d p [ i ] [ j ] dp[i][j] dp[i][j]为布尔型是否匹配,后来发现其具有后效性,因此该方法不行,DP在设计状态的时候首先考虑是否有无后效性。

新的DP方法,通过前推少量状态而不是枚举状态减少常数。

定义 d p [ i ] [ j ] dp[i][j] dp[i][j]为匹配到 s 1 [ i ] s1[i] s1[i] s 2 [ j ] s2[j] s2[j]的不产生冲突可能的剩余差值(由通配符产生)。

通过枚举 d p [ i ] [ j ] dp[i][j] dp[i][j]的状态去推出后继的状态。

其分为两种情况:

  • 追加差值
  • 匹配差值

分类讨论即可。

思路:二维DP。
难点:选择合适的DP状态解决后效性。

11.2

CF 751

Problem E

可以看做是模板题。给定两个数组, a a a的相对位置不变, b b b以任意顺序插入到 a a a中,求最小逆序对。

首先需要证明两个结论:

  1. b b b一定以从小到大的相对顺序进行插入,证明显然。
  2. b i b_i bi的插入的最优性互相独立互不影响。

第二点的证明,假设 b i b_i bi a j a_j aj的前面插入对逆序对的贡献是最少的,那么我们知道, a j > b i a_j>b_i aj>bi b i b_i bi插在 a j a_j aj后面,则会多产生一个逆序对,并且小于 b i b_i bi b b b也不会产生更大的贡献。

首先的一个思路从寻找 b 1 b_1 b1的最优插入位置 p 1 p_1 p1,这需要 O ( n ) O(n) O(n)的时间,在 p 1 p_1 p1之后查找 p 2 p_2 p2的位置,这需要 O ( n ) O(n) O(n)时间,总共需要 O ( n m ) O(nm) O(nm)的时间。如果我们使用分治,每次查找 b m i d b_{mid} bmid的最优位置,每一层需要 O ( n ) O(n) O(n)的时间,总共需要 O ( n log ⁡ m ) O(n\log m) O(nlogm)

最后树状数组统计逆序对的个数,然后统计即可,时间复杂度 O ( ( n + m ) log ⁡ ( n + m ) ) O((n+m)\log (n + m)) O((n+m)log(n+m))

思路:贪心证明+分治。
难点:分成子问题优先考虑分治。

CF 752

Problem E

结论题 + 贡献转移。

考虑简化这个过程,能够得到一些有用的结论,即若 a i + 1 < a i a_{i+1}<a_i ai+1<ai,那么最终 a i = ⌊ a ⌈ a i a i + 1 ⌉ ⌋ a_i=\lfloor \frac{a}{\lceil \frac{a_i}{a_i + 1} \rceil} \rfloor ai=ai+1aia,并且需要 ⌈ a i a i + 1 ⌉ − 1 \lceil \frac{a_i}{a_i + 1} \rceil - 1 ai+1ai1次拆解。

那么我们可以枚举以 x x x结尾,前驱为 a i + 1 a_i + 1 ai+1 ⌈ a i a i + 1 ⌉ − 1 \lceil \frac{a_i}{a_i + 1} \rceil - 1 ai+1ai1贡献。设 d p [ i ] [ x ] dp[i][x] dp[i][x]表示为子数组 a [ i : j ] a[i:j] a[i:j]最终以 x x x结尾的子数组的数量,那么前面有 i i i个开头的子数组会得到这个贡献。即为 i ∗ d p [ i ] [ x ] ∗ ( ⌈ a i x ⌉ − 1 ) i * dp[i][x] * (\lceil \frac{a_i}{x} \rceil - 1) idp[i][x](xai1)

思路:推结论+贡献转移。
难点:推出结论+ DP状态设计 + 贡献转移技巧。

11.3

LC 407

优先队列的优化的BFS搜索题。

我们假设一个小人在 ( r , c ) (r,c) (r,c)向四周倒水,优先队列中有三元组 ( r , c , h e i ) (r,c,hei) (r,c,hei),表示小人在 ( r , c ) (r,c) (r,c)向四周倒水的最大高度为 h e i hei hei

首先我们可以确定一开始小人应该站在边界处,故将所有的边界加入到队列中。

每次队列取出 h e i hei hei最小的,向四周倒水,如果 ( d r , d c ) (dr,dc) (dr,dc)的高度低于 h e i hei hei,那么肯定是可以倒水的高度为 h e i hei hei的,因为 ( d r , d c ) (dr,dc) (dr,dc)的短板一定是 ( r , c ) (r,c) (r,c)。然后 ( d r , d c ) (dr,dc) (dr,dc) h e i hei hei就可以确定,即 max ⁡ ( h e i , h e i g h t [ d r ] [ d c ] ) \max(hei,height[dr][dc]) max(hei,height[dr][dc]),将其加入优先队列中。

思路&难点:优先队列维护的BFS。

11.5

21 CCPC for Female

Problem C

一开始ych告诉我将分公司的数量为 1 1 1和大于 1 1 1进行分类,为 1 1 1的就不要赋予状态。

正解为传递闭包优化DAG上的DP。

考虑带中间节点的路径 i → j i \to j ij,那么若有边 ( i , j ) (i,j) (i,j)存在,那么以这条边转移的DP一定是不优的,所以可以删掉这个边。

为了维护节点 i j ij ij之间是否有带中间节点的路径,需要求一次DAG的传递闭包。

这样操作之后,可以证明带有 n n n个节点的DAG图最多有 n − 1 n-1 n1个边。即 1 → n 1 \to n 1n的一条链。

这样时间复杂度就从 O ( n 2 ) O(n^2) O(n2)的完全图优化为 O ( n ) O(n) O(n)的链图。

思路:DAG上的DP。
难点:用传递闭包优化DAG的DP。

Problem B

倍增,一个很显然的思路,在字符串 s s s上查询,从 s [ 0 ] s[0] s[0] s [ k 1 ] s[k_1] s[k1]正好凑齐一组字母表,从 s [ k 1 + 1 ] s[k_1 + 1] s[k1+1] s [ k 2 ] s[k_2] s[k2]正好凑齐一组字母表,结果正好能最多凑齐 p p p个字母表,那么关于 s s s的答案即为 p + 1 p+1 p+1

考虑 d p [ i ] [ k ] dp[i][k] dp[i][k]为从起点 i i i 2 k 2^k 2k次的中点。首先通过一次二分计算出 d p [ i ] [ 0 ] dp[i][0] dp[i][0],然后进行倍增求出所有的 d p [ i ] [ k ] dp[i][k] dp[i][k]即可。

单次查询时的时间复杂度为 O ( log ⁡ n ) O(\log n) O(logn)

思路&难点:二分+倍增DP。

11.6

21 CCPC for Female

Problem F

POJ 2185的增强版本 广义KMP&二维KMP的模板题,只不过需要一次Hash来优化字符串的判断相等。

思路&难点:二维KMP+Hash优化。

11.8

ABC 226

Problem F

一道分拆数估计+DFS枚举分拆+第一类斯特林数+划分模型的一道综合计数题。

首先根据 P 50 < 1 e 6 P_{50} < 1e6 P50<1e6,确定DFS枚举分拆可行。

然后DFS枚举分拆,在可能的答案中对分拆组转换为划分组,最后根据公式 S ( n , 1 ) = ( n − 1 ) ! S(n,1) = (n - 1)! S(n,1)=(n1)!对其进行计数。

思路:组合数学。
难点:计算公式的确定。

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值