2023 3 月 HL 集训总结

犹豫了一下,还是把对应题目的总结放到对应的天数里面,到时候比较好找

3.5 晚自习

上 luogu 测了一下春测分数,100+85+100+15=300,不太好,暴力分应该是 100+100+100+40=340 的说,高分应该在 380 左右。

自己仔细想了想 T2,在自己算法的基础上用聪明一点的爆搜过掉了,挺可惜的。

然后想了较久的 T4,还是没有头绪,二分答案之后不会判定

把之前大致搞懂,但没有写代码的 CF1340F Nastya and CB 搞了

预习了一下明天的题目,思考了部分题,感觉都很有难度。

  • CF1340F Nastya and CBS:考虑一个区间如若被消成存在 {) 那么无论外面怎么搞都不合法。那么一个子区间应该可以被处理成 )))]]}})(((({[[[[ 这类形式。于是一个做法是分块维护 左边的右括号 和 右边的左括号 的 hash 值,每次匹配一下。更优秀的做法是利用 楼房重建线段树 的思想,在递归过程中,计算出左区间对右区间的影响,然后进一步递归右区间即可。

没有 QQ/oh,没有 QQ 音乐(没带耳机)/fn/fn/fn/fn

3.6 sqy 杂题 + 广附杂题1

早上 6:50 被闹钟叫起来了,起来的时候比较精神,但是觉得还有点早,然后继续睡,睡得很浅。酒店到机房的路上感觉人很清醒,到了机房就感觉有点小困。

sqy 讲得比较详细,但是越听越困,感觉这些题都听得迷迷糊糊的,感觉 sqy 的声音需要费力才能辨认出到底在说什么,感觉是自己没有脑子。

原来大家都很困,那么可能的原因是教师没有开窗。

下午不小心睡过头了/xia,过程和早上差不多,2:00 左右起来,觉得还可以睡,然后 G

晚上的题都比较清新,比较可做,体验比较好。

  • Parmigiana With Seafood[solved]:高级博弈题。菊花是简单的,考虑链的情况。A 首先意图争抢最大值,假设最大值初始不是叶子,那么对于 A,B 而言,设最大值在 i,那么 i - 1 和 i + 1 都是不敢走的点,那么二者必然先把剩下的 n - 3 个点取完,讨论奇偶性可以知道 A 在 n 是偶数的时候可以取到 n;假如 n 是奇数,讨论一下 n - 1 的位置,设在 j,发现问题等价于将 [i, j] 缩成一个点,然后 A 是否可以取到这个大点。结论是,对于链的情况,n 是偶数,ans = n;奇数,ans = max i, s.t. dis(i, n) 是奇数。这个结论可以推广到树上。发现 WA,一看发现找到的 ans 小了,漏掉的情况是:“我们定义 (x, y, z) 是一个 Bad Tuple,当且仅当存在 w 使得:1. d(x,w) ≡ d(y,w) ≡ d(z,w) ≡ 0 (mod 2)。2. 删去 w 后 x, y, z 两两不联通。” 更科学的分析出这些条件的方式是,把点分成两类,一类是 A 如果想要去一定可以取到的,一类是 B 可以阻止的(实际上,也就是对于 B 而言一定可以取到的点),然后分析奇偶性,发现对于链上的情况而言,关注的是 到第一个叶子距离 + 到最后一个叶子的距离 是奇数的情况,那么此时只能是一奇一偶;但是对于树上,可以是 奇+奇+奇。不用考虑 奇+奇+奇+偶,一个理解方式是可以被拆分成上面两种情况。

  • Graph Problem With Small n^2[solved]:优良的状态优化题。首先有简单 \(f_i[s]\) n32n 做法,每次枚举 x\in f_i[s],枚举 x 的出边 v,更新 f[s|v] |= (1<<v)。发现上述更新柿子与 x 无关,预处理 To[s] 表示 s 集合的出边集合,可以 n22n。复杂度瓶颈在于需要枚举起点,发现起点唯一的作用是提供一个初值,每次重跑是非常浪费的行为,考虑从 x->y 的哈密顿路,可以拆分成 x->1->y 的哈密顿路,那么不妨只以 1 为起点,跑出一个 f[s],由于是无向图,那么可以知道对于 i\in s,f[all ^ s] 中的点均是合法的点,枚举 s 即可处理出所有的 ans。总复杂度 n2^n

  • Least Annoying Constructive Problem[solved]:神笔构造题。第一个结论:对于一个 2n 阶的完全图,可以拆成 2n - 1 个完美匹配,有构造性证明:对于第 i 个匹配,将 i - j i + 1 + j 匹配在一起,把图画成一个圆的形式容易发现这样的正确性。第二个发现:如若把两个完美匹配拼在一起,那么一定会形成若干个环。那么这里的想法就是,让以结论中构造出的相邻完美匹配拼起来,讨论讨论发现是正确的。

  • Wonderland Chase[solved]:博弈。考虑如果本来就在环上,那么 A 赢麻了;如果 A 初始在叶子上,那么是非常危险的,A 会希求走到一个环上。如是可以定义 SAFE 点:存在一个 >=3 的环,使得包含这个点。可以证明,对于 A 在一个 UNSAFE 点 x,如果想要走到一个 SAFE 点 i,当且仅当 dis(x,i) < dis(B,i),如若存在,那么 A 赢了;否则,A 一定会选择走向 dis(A, i) < dis(B, i) 且 dis(B,i) 最大的点硬拖。

  • Mana Collection[solved]:容易想到转化成求解最少浪费的量,设 \(f[s][i]\) 表示已经确定了 s 集合最后一次到达的时间,当前在点 i,浪费的最少能量,转移直接 \(f[s][i] + dis[i][j] \times \sum_{x\in s}w_x \to f[s|j][j]\) ,一个担心是 dis(i, j) 会不会再次经过 s 集合中的点,但是可以发现的是,这种情况必然会被另外一个 DP 过程算到,且必然不优于那个方案。此时,对于一个询问 (e, tim),等价于 \(\max_s \{sum[s] \times tim - f[s][e]\}\),显然可以理解成给定一堆直线求某一个点的最大值, 维护下凸包/李超线段树即可。

  • SurroundingGame[understood]:经典 文理分科/小M的作物

  • Hungry Cow[understood]:线段树分治+线段树上二分的线段树爽题

  • Watching Cowflix[understood]:神仙题。直接对着原题目 DP,有 \(f[i][0/1]\) 表示覆盖了所有 i 子树内部的特殊点,i 选没选,对每一个 k 做一次,复杂度 O(n^2);然后,这个选择了一个连通块,然后附加一个贡献,实际上很像 wqs 二分的过程,考虑某种意义上逆向进行 wqs 二分的过程,即考虑计算出 g[i] 表示假装 k = 0 时,恰好使用 i 个块的最小代价,那么实际上,此时计算的是最小点数,知道答案可以表述为 k \times 连通块数量 + 总点数(对应到 wqs 二分上表述为 kx + b,实质上是算出了凸包上每一个点),可以求出答案。计算 g 是树上背包,由于容量是 k,复杂度是 O(nk) 的,复杂度证明可以考虑类似树形背包的证明,树形背包是两个点会在 lca 处合并一次,而这里还额外增加了距离不超过 k 的限制。同时,注意到答案不会超过 2n(全部放在一个连通块),所以当 k \(>\) sqrt 的时候,连通块数 \(< \sqrt n\),于是得到一个根号做法,即对于 \(k\le\sqrt n\),做 O(n) 一次的 f,对于 \(k > \sqrt n\),利用 O(n\sqrt n) 的 g 把这样的 k 对应的答案求出来。一个常数优化的技巧是,对于多次在同一棵树上做 DP,可以随便处理出 dfn/bfn 序,然后按照这样的顺序转移,省掉了每次递归的常数,据说这样很快。还可以做到 O(nlogn),依赖与这样一个观察,对于在 k = C 时的方案,我认为把某两个点合在同一个连通块优,那么当 k > C,这两个点合在一起也是优的;仔细分析一下,对于两个距离为 d 的关键点,若 \(d \le k\),那么肯定要并起来。那么,考虑当 k = C 的时候,我把所有距离 \(\le k\) 的关键点并起来,形成了 \(O(\frac nk)\) 个大关键点,容易发现可以直接对这些大关键点建立虚数,然后在虚数上算 f 即可,总复杂度调和级数(可能的一个疑惑是如果所有大关键点之间的距离 > k,为什么还可以做合并,答案是因为多个大关键点合并时,之间的路径会产生重叠)。进一步的,可以做到 O(n),方法是考虑在 k = C 的时候,把一些大关键点并起来了,在 k = C + 1 的时候仍然会并起来,一共只会合并 O(n) 次,但是需要一点巧妙且优秀的实现(实际上,还需要关注到的性质是:k = i 的连通块数量 <= (k = i 的答案) - (k = i - 1 的答案),否则可以让 k = i 的答案变得更大,即用 k = i - 1 的方案;所以 \sum 连通块数 = (k = n 的答案) - (k = 0)的答案,需要关注到的连通块数量是 O(N)的)。

  • 「JOISC 2019 Day3」指定城市:首先树形 DP 算出 k = 1/2 的答案。之后,稍微分析可以发现如果要塞一定是塞在叶子。一个问题是不一定 k = i + 1 的答案可以从 k = i 补充而来,实际上可以发现,只要确定了某一个点作为必选项,那么后续的方案是固定的,于是只需要证明 k = 2 取到的两个点其中之一是必选项,这个可以结合树的直径的性质证明。剩下的问题是一个长链剖分,类似 肖申克的救赎。

  • 「JOISC 2019 Day1」馕:求出 \(pos[i][j]\) 表示对于人 i,第 j 份可以合法方案的右端点,发现答案一定可以取到 \(min pos[i][j]\),即第一次,找到 pos 最小的一个点,把对应的馕分给他;第二次,找到 i 不是第一次已经选了的 pos[i][2] 最小的,容易发现这样选必定合法,因为第一次选的是 min。

剩下很多题的总结没写,后面再来。

感觉总结排版很丑,/ll

3.7 模拟赛 + zz 网络流1

  • 8:30 想完 T4,简单思考 T123
  • 9:15 打完 T1 初步想法
  • 9:45 对拍发现三分会碰到 == 的情况,GG
  • 10:30 发现不存在单峰性质
  • 11:00 还搁这 greater 呢 。。。有单峰的,真下头。
  • 11:15 发现 T2 和我理解的不一样
  • 11:30 T2 题目理解不能,放弃
  • 11:55 发现 T3 TREE 还要构造方案,GG

这把最失败的地方在于在 priority_queue<int, vector<int>, greater<int>> 摔倒了两次。


T1,考虑一个简单贪心:先尽量选尽可能多的,然后此时还剩下一些空间,可以利用这些剩余空间把一下 b 小的换进来。

考虑这样贪心的问题是什么,问题是可能还可以删更多,交换的方式不一定是一换一。但是如果不是一换一的话,选择的总数处于变化之中,会导致一些本来可以记入答案的点变得不合法。

发现如果知道我到底选多少个就很好办了,就存在一种 nlogn 求出答案的方法。

猜测 f(选择个数) = 对应答案 的图像应该是一个单峰,那么可以考虑三分。三分过程中,发现很可能存在一大段相同,那么此时三分就失去了合法性,但是确实是单峰。

取消掉单峰性质之后,发现最终答案满足可二分性,即如果我有一种方案使得牢固掌握 x 个知识点,通过按照 bi 从大到小不买这些知识点,同时买入一些难以掌握的知识点的方式,可以构造出所有 \(< x\) 的情况。

二分答案后,直接从 1 到 n 枚举选择的总数,问题容易转换成 维护 \(bi \le k\)\(bi > k\) 的两个集合,每次查询集合前 k 小,或者从集合中插入/删除 一个数。这个问题可以 线段树/树状数组 上二分解决。

考场上最后大致想到这里了,但是看着时间不多了,决定去打 T23 的部分分。

上述算法的复杂度是 nlog^2n 的,广附老哥介绍了一种 去二分化 的思想。

即上述 DS 实际上给了我们 log 时间复杂度判定固定 总个数 和 掌握的知识点数量 之后是否存在合法方案的能力,而最终答案的值域是 O(n) 的,我们自然想到能不能只做 O(n) 次上面的判定,即让每次判定都能够让 ans ++

于是,考虑由本来的二分答案、枚举总数,转变成枚举总数,判定 ans + 1 是否可行。可以发现,对于一个特定的总数,合法的 ans 是一段区间,故而上述做法获得了合法性;nlogn 预处理出每一个 总数 对应的 l(第一个合法点),每次 ans = max(ans, l) 并不断判定 ans + 1 是否可行即可。

这样的话,如果 ans + 1 的判定失败了,由于一个总数的合法区间只连续的一个,所以可以直接 break,这样最多失败 O(n) 次;如果成功了,ans = ans + 1,最多成功 O(n) 次。总复杂度 O(nlogn)


T2,题面写得很不清楚!排序后,可以任意选择一个前缀,而不要求前缀中每一个数都是最大值。

考虑简化 m 次选 v 个数 +1,等价于可以搞出一个 ad 数组,满足

  • \(\sum ad = mv\)
  • \(\forall i, ad_i \le m\)

简单思考,可以构造证明出这两个条件是充要的。

接下来按照 \(|S| ≥ v\)\(|S| < v\) 两种情况分类讨论。设 \(T = [n]\S\)。设 \(M_T = max_{i∈T} a_i, m_S = min_{i∈S} a_i\)

选择的一个前缀合法,当且仅当 T 集合的最大值不会插入进 S 的值域中,即 \(M_T\le m_S\)

对于 \(|S| >= v\)

  • \(∑_{j∈S} max(0, MT − aj ) ≤ mv\)
  • \(MT − mS ≤ m\)

容易设 dpi,j,k 表示考虑了前 i 个人,选了 j 个人,它们 max(0, MT − ax) 之和为 k 的方案数。发现 j 的作用在于统计答案的时候判定 \(j>=v\), 考虑不记录这一维的状态,容斥简化 DP 状态,即再用一个 dp 计算出 \(j < v\) 的方案数,正好,发现 \(j < v\) 的时候自动满足第一个条件,所以不用记录 k 这一维。

对于 \(|S| <= v\)

  • \(∑_{j∈T}(mS + m − aj ) ≥ m(v − |S|)\)
  • \(MT − mS ≤ m\)

类似的,可以两个 DP 做掉。


T3,大致听懂了题解做法,正在看 std

对于广附老哥提出的 短链剖分 感到非常震撼


晚上听了网络流,对网络流有了更系统、清楚的认知。

3.8 模拟赛+广附杂题2

  • 7:40 入场
  • 7:55 想出 T1
  • 8:15 T1 求大,读入写错了
  • 8:30 T1 过拍
  • 8:50 终于读懂 T2 题意了
  • 9:50 过 T2 大样例
  • 10:50 T3 初有眉目
  • 11:30 T3 自闭

下午给 sqy 杂题的总结补了补,但是还是没有补完/oh,晚上订正 T3


T1:首先我会 n^3logn 暴力,经典01分数规划。想一想发现如果固定 l,可以考虑整体二分,但是感觉复杂度不太会算。

不管暴力,看到题目让我找第 k 小,套路地,二分答案 x 并计算 \(f\le x\) 的个数以判定是不是 k 小,然后发现这个可以用双指针算,结束。

T2:第一次以为是 加上路径上黑点数,然后写了一个暴力猜了半天题意才猜对。

枚举根,题目是求 \(\sum_p\sum (n - tim_i)\),其中 \(tim_u = \min\{\min_{v\in subtree(u)},p_u \}tim_v\)。原式 \(=(n - 1)!\times n\times n - \sum_p\sum tim_i\) 往下推:

\[\begin{align*} &= \sum_u \sum_{tim_u = x} x\times \lambda_{u, x} \\ &= \sum_u \sum_{tim_u = x} x\times (\binom{n - x}{siz[u]} - \binom{n - x - 1}{siz[u]}) \times siz[u]!\times (n - siz[u] - 1)! \end{align*} \]

\(\lambda_{u, x}\) 表示 tim_u = x 的方案数,实际上是需要从值域 [x, n] 中选出 siz[u] 个不同的数,且强制钦定 x 是这 siz[u] 数之一。我做的是简单容斥,用 \([>=x] - [>= x+1]\),另外一种是计算概率,实质上差不多,但是我这样后面柿子更好推/hanx

然后把两个阶乘提出来,剩下的和式是经典的裂项相消,最后放在杨辉三角上,发现系数就是 \(\binom{n + 1}{siz[u]}\)

剩下一个换根,结束了。


T3 考虑实际上关注的是前缀 max(h[i] - dlt[i] - i) 和 \sum dlt,可以暴力 DP 记录这些,那么有一个 nv^2logv 的做法但是啥部分分都过不了,一个尝试是把 dp 状态从前缀最大值 = j 改成 \(<= j\),然后 dp 的时候让每一个数字刚刚抵住 mid 就好。但是让 dp 失去了正确性。

一个考虑是从 CDQ 分支的角度思考问题,但是发现这样只能复杂化问题。

\(c\le 2\) 的部分分,启发将每一个点看成是 i - h 和 i + h 两个点,此后可以考虑双指针解决问题。麻烦的是如果左右都是同一个点的 i - h 和 i + h 那么会算错,然后不会处理了。

甚至考虑了网络流,然后考虑了一些垃圾算法,没有收获/ll

考场思考的部分结束了。

sol1(std):枚举最大的 a = i + h_i,发现对于 i = 1...n,代价是分段一次函数,把这些分段一次函数拼起来,实际上也就是得到了 f(a)。复杂度 nlognlogv

sol2(wmh):对 std 做法的简化,没听太懂,关键性质是 \(i<j\) 没有用。

sol3(wzy):题目可以转化为树的直径,枚举树的中心,可以用简单 ds 维护。

sol4(ljy):强行做 wyb 考场思考,对于首位属于同一个数字的情况,可以发现一直对这个数字操作不劣,那么现在转化为首尾不同的情况,且容易发现收尾不同不会转化为首尾相同。考虑二分了答案之后,每一个点的贡献是一个最多分三段的一次函数。现在需要对这些一次函数的端点脾虚,通过一点点分析,发现这个排序是可以归并的,所以排序复杂度 O(n),总复杂度 nlogv


晚上听了杂题,/bx/bx

3.9 ntf 杂题 + zz网络流2

上午听 ntf 杂题,觉得语速太快了,很多东西反应不过来,很多题都听得比较零碎。

  • CF1789F Serval and Brain Power:nb “根号”分治题。设循环节长度 len,循环次数 x,答案是 len * x,答案显然小于等于 |s| = 80,看到 \times,DNA 动了。考虑循环次数为 x = 1,2,3,我可以暴力把原字符串划分成 x 段,然后跑 LCS,这样实际上包含了 x = 4 的答案。对于 x >= 5,len <= 16,那么 把序列每 16 个看成一组/插眼法,容易发现任意一种 len < 16 的分组方案中的每一组,一定存在某一个子区间使得是 len = 16 的某一组的字串。那么我们只需要 5\times 2^16 枚举循环节,对于每一个循环节暴力判定即可。
  • CF1605F PalindORme:神仙转化题!本道题的关键在于找到“唯一确定”的东西进行计数,具体的,把一个不合法的情况,拆成一个极大的合法情况+一些不会算重的贡献。这样的思想也被用在了前段时间模拟赛 20230205 T1 的容斥。
  • [2023 集训队互测 R6T3] :建立 AC 自动机,限制是一些点不能走。在 AC 自动机上 DP,即 \(dis[x][y]\) 表示在 AC 自动机上 x,在原图上的 y 的最小 dis。需要可持久化线段树建立 AC 自动机,需要用 dijkstra 经典技巧:[NOI]弹跳,堆中维护边,每次从 ds 中取出点,每一个点只会被取出一次。
  • [2023 集训队互测 R5T1] 在路上:对 快速排序思想 O(n) 求第 k 大 的利用 + 带权随机。
  • ARC122E Increasing LCMs:构造题,考虑 规模 \(n\to n - 1\),每次考虑最后一个选啥。分析选数条件之后,发现如果有解,随便选可以构造出答案。

晚上听 zz 网络流,对其中的几道原题进行了一个复习,并口胡正确了 CF875div2。

3.10 模拟赛 + xmz 杂题

  • 8:50 不会 T1,心态不对劲了
  • 9:50 T2 一直在感性思考,没有得到有正确性的感性结论,浪费时间了
  • 10:50 终于找到了 T2 的 sb 错误/fn/fn/fn
  • 12:00 T1 还是不会/ll

T2 二分上界算错白给 40pts,警钟敲烂。


T1 分析了很多,诸如倒着做,维护 \sum x_ix_j,维护 \delta,维护 \delta^2 ,998244352 = 119 \times 2^23

其中,最重要的实际上是最后一个性质,事实上也是第一个尝试分析的性质,当时猜测(印象中认为) 998244352 应该是 2 的整幂次,那么这样若干轮之后全都是 1,那么爽死了。

然后发现不是整的幂次,还要乘上 119,感到很失望。感觉这个形式很像 六省联考2017 相逢是问候,但稍微分析还是发现了明显的不同。

GG,发现自己连 l = 1, r = n 都做不来,kk。

正解观察这道题的唯一的 可做性(突破口/性质) 在于 998244352,需要进一步观察到 \(2^24 \equiv 1\pmod {119}\),那么相当于每一个数字在进行 23 次操作之后,后续的值呈现一个循环。

前面 23 次使用势能线段树,即暴力递归到叶子修改。后面部分,考虑初始 build 线段树上每一个点维护长度为 24 的数组 \(val[x] = \sum a_i^{2^x mod 119 \times 2^23}\)。每次区间修改,实际上就是在线段树对应位置上执行循环左移一位,pushup 是对应为相加。当然这个操作也可以维护一个 cur,维护 cur 的不方便之处在于 pushup。


T3,性质分析题。罗浩/bx

看到题目这种形式,直接考虑连边 i->p_i,那么形成若干个环。

考察是否可以在环内连边,发现不行,唯一可行的情况是 n 是偶数,然后跳一步连边之类,但是这样的问题在于这个环不能再和其他环连边了。所以环内不能连边。

考察怎么样的两个环可以连边,对于长度为 a, b 的环,画图可以发现条件是 a|b 或 b|a,否则 a 上的一个点会连出 b/gcd 条边。

建立新图,若有两个环 a|b,则连接 a->b,形成了一个 DAG。现在需要在这个 DAG 上提出一部分边,使得形成一个树的结构。

画图发现,不存在 \(x<=y<z, x|z, y|z\),使得树边同时有 (x, z), (y, z);但是可以同时有 \(x, z, z\), (x, z), (z, z)。那么考虑把环长相同的缩在一起,对于这样一个大点内部,显然可以随意连边并构成生成树,对于包含 t 个长度为 len 的环的大点,如果只考虑内部连边,方案数是 \(t^{t - 2}len ^{t ^ 2}\)

一个问题是即使这些环连成了树结构,还是有可能不连通,因为每一个环内不一定联通,所以我们要求树根为 len = 1/2 的环。

发现了上面的性质之后,剩下的问题是容易的。每次在长度为 1...i - 1 的环已经拼好的树的下面,继续拼即可。

实现比较巧妙,对于上述的一个 DP,注意到对于当前的长度 i,枚举 d|i,如果两者连边,方案数是 d\times i;所以预处理 sum[i] = \sum_{d|i} cnt[d]\times d,这样不需要枚举 i 的边连到了那些 d。


晚上听杂题的体验不太好。后面一堆广附初三(?)的学生一直叽叽喳喳/fn,当然我觉得另外的一部分原因是讲题人讲得确实比较抽象。还是比较有收获。

写了 「JOISC 2019」「LOJ #3036」指定城市,简单贪心题。

  • CF1599A Weights:nb 构造题。假定当前 n & 1, s[n] = r,考虑 问题规模 \(n\to n - 1\),发现如若不管前面,将第 1,3,5,7\dots 大分给 R 是合法的。考虑若 s[r] = s[r - 1],那么刨除 最小值即可,若 s[r - 1] = s[r - 2],从 L 中刨除次小值即可;相反地,刨除最大值。也就是说,如果去掉(当前)最大值,LR 状态一定改变;去掉最小值,LR 状态一定不变,递归即可。实现很有细节。

3.11 sqy 杂题+ ljy 杂题

今天听课感觉的都还可以,比较有收获。一些题很有震撼,后面加紧补补。

写了「JOISC 2019 Day3」指定城市 和 「JOISC 2019 Day1」馕 虽然并不是今天的杂题

晚上看懂了 春测 T4 的正解,发现了一种可以被卡到 n^2k\log V 的算法跑了 LOJ rank1,ccf/ruo

  • [CCO2020] Shopping Plans:非常震撼command_block 的题解写得很好。使用了类似 求前 k 大的方案的套路 还有 十二省联考异或粽子 NOI超级钢琴,大致思想是分成 m 组,每组有 log 求组内第 k 大的手段,第一次将所有组的最大值放入 优先队列,每次从优先队列弹一个,那么在对应组找到 k + 1 大代替(以前似乎在某到淀粉质里面也见过这种套路,似乎是对于分治重心的每一个字数开一个小根堆,外面开一个大根堆之类)。发现实际上不是求第 k 大,是求的某一个状态的后继,实际上只需要掌握一个 trans(S) 方法,使得所有 val(S) \(\le\) val(trans(S)),且利用 trans 操作可以到达所有状态,且 trans 复杂度低,且 S 利用 trans(S) 转移到的状态数量不会太多(pop 掉一个元素,不会新增太多后继);如若此时 trans 转移到了太多后继,那么可以把这些后继排序,例如后继 k1,k2,k3,变成 trans(s) = k1, trans(k1) = k2,trans(k2) = k3。
  • CF1770F Koxia and Sequence:nb,太 nb 了。第一个观察是 n 是偶数 ans = 0,证明考虑对称性,swap(a[i],a[n - i + 1]) 可以得到另一组解;对于 n 是奇数的情况,可以认为贡献均发生在 a[1](将 2...n 做对称),自然想到枚举 a[1] 的二进制第 b 位,计算合法的方案数的 奇偶性,一下假装 a1 被抠掉了 2^b。考虑把 y 的限制容斥掉,即假设 f(y) 表示 \(\sum_{\sum_a = x - 2^b} [a_1 \in (y\oplus 2^b)][\forall {i>1}, a_i\in y]\),有 \(ans = \sum_{y^{\prime}\in y} (-1)^{|y| - |y^{\prime}|}f(y^{\prime})\),只关心异或,所以 \(ans = \oplus f(y^{\prime})\)。只需求出 f(y),考虑 逆用 Lucas 定理的推论,由于只关心奇偶性,将 \([a\in y]\) 变成 \(\binom {y}{a} \bmod 2\),可以发现 f(y) 的式子变成了 多元范德蒙德卷积 的形式,结束。
  • Gym 104160G Meet in the middle:首先发现这道题的形式很像 WC通道,关键点是扩展直径性质,对于 Tree2 的点 u 的所有询问,实际可以理解是给 T1 中每一个点 v 多挂一个虚儿子,边权是 T2.dis(u, v),然后求 T1 的直径端点。显然不能暴力做,考虑 u 在 T2 上移动到某一个儿子 son,那么对于 son 子树中的节点集合 S,每一个 v\in S 在 T1 中的虚点边权 -w(注意 S 在 T2 中表现为离散的集合),子树外的虚点 + w。可以想到 线段树维护树上联通块直径 的套路,发现由于是两棵树,所以如果想要在 T1 上建立这样的线段树,每次 u->son 的时候稚只能憨憨地做 |s| 次单点修改;实际上可以在 T2 上建立线段树,对于线段树上某一节点,维护其 S 在 T1 中对应子集的直径端点,因为我们可以实现 T1.getdis,所以这是可以做到的。即我们不关心树的结构,我们只关心 dis,所以不必要在 T1 上建立线段树,因为根本没有用到树的结构信息。利用欧拉序求LCA,做到 nlogn。

3.12 晚自习(闫书奕贪心)

6 道题贪心,3 道原题,\ruo

  • JOIOI 塔:简单贪心。容易发现尽量取 JOI 更优,从后往前贪心,实现聪明做到 O(n)
  • 航道管制:medium.建立出 DAG 之后,算出每一个点最紧的 k,由于保证存在解,于是直接按照 k 从大到小贪心分配即可。对于第二问,要求尽量晚分配 x,一个想法是先忽略 x 做分配;然而对于 DAG 上可达 x 的点,必须要先分配 x 才行,所以需要把这些点也全部都暂时忽略。那么,当分配到某一个时刻,发现不得不分配了,就是答案。
  • Naughty Stone Piles:容易转化成 k 叉树,一个方案的权值是 \sum dep_iw_i,贪心分配即可。

还写了 CF1599A Weights 和 CF1770F Koxia and Sequence。

3.13 whq 杂题 + why DP

感觉今天老哥选题都很小清新!

今天晚上前半段卷力大幅流失,大概是太心急了。

  • CF772C Vulnerable Kerbals:类似的题目是 CF487C 考虑当前前缀积是 i,有裴蜀定理,能够到 j 当且仅当 gcd(i, m) | j,所以对于 gcd(i, m) 相同的点实际上形成若干个团。考虑团之间的连边当且仅当 gcd(i, m) | gcd(j, m),连边数量 mlogm 且是一个 DAG,跑 DP 即可。构造方案使用 exgcd 求 i->j 对应乘上的 x 即可。
  • CF1178F1 Short Colorful Strip:简单区间DP
  • CF482C Game with Strings:首先可以考虑拆开算,即计算把字符串 i 区分出来的期望次数,这个是容易用状压 DP 做的,但是复杂度是 nm2^m,需要卡常。瓶颈在于 n,考虑不枚举 i 了,直接计算,设 f[s] 表示已经问了 s,到区分出某一个字符串还需要的期望步数,那么有 \(f[s] = \sum_{i\notin s} \frac{f[s|i]}{m - ppc(s)}\frac{al[s|i]}{al[s]} + 1\),其中 al[s] 的意义是 s 无法区分的字符串个数,转移的意义是考虑有这样多的概率问位置 i,有 xx/xx 的概率对手选择了还是不能区分的字符串。
  • CF500F New Year Shopping:小清新 DP。首先有暴力线段树分治做法,但是关注到 p 是常数,且每次询问等价于问 [a - p, a] 时间内加入的物品;于是可以使用 插眼法,每 p 个插一个眼,那么任何一个询问区间刚好跨过一个眼,对于每一个眼预处理向左向右的 DP,合并一下就好。
  • CF626F Group Projects:算是自己想出来的。首先对 a 排序,可以将一个组的最小/大值看成左右括号,容易得到 f_{i, j, k} 表示前 i 个,有 j 个左括号没有匹配,不和谐度总和 k;转移考虑如果加入左括号,k -= a;右括号 k += a。但是这样的复杂度是 n^2值域,因为可能先有很多左括号之类。考虑差分将贡献拆成单点的形式/裂项相消 即可。

还写了 Gym 104160G Meet in the middle 和 ARC122E Increasing LCMs

没看懂 CF377E Cookie Clicker

3.14 模拟赛 (GDKOI D1)+ cly 杂题

  • 8:30 不会 T1/ll
  • 9:20 放弃 T1
  • 10:40 T2 自闭
  • 11:10 打 T2 n^2logn 做法打着玩算了
  • 11:50 二项式反演。。。。。

最后 10min 的时候,想着不能摆烂,干脆容斥一下试试,然后发现 1min 推出来,写对了/qd,在最后 5min 得到了前面接近 3h 都没有拿到的分数。。。

T1 居然过了,数据没有卡掉我/cy


T1:判定 A 乘 B 是否 = C,首先尝试把 C 算出来,稍微想一想就知道不太行,好像最优复杂度是 O(n^{2.7xxxx})来着

容易发现我可以做到 O(n) 求出 C 的某一行列的和,但是这样等价于问出一个 n 元方程,C 可以看成是 n^2 的未知数,所以如果问 2n 遍得到每行每列的和是随便卡的。

简单的一个想法是 2n 遍之后还剩下一些时间,全部用于随机撒点。

然后发现不会了,一直在思考 矩阵相等 的等价条件,发现啥都不会。

solution:考虑若 vA = vB, v 是一个 1\times n 的向量,那么大概率 A = B。出现判定失误是可以预见的稀少,需要系数刚好凑上。

学到了,其实最开始有想到 向量\times 矩阵 复杂度 \(O(n^2)\) 这个条件,但是没有深挖这个思绪


T2:虽然下面的思路是失败的,但是觉得不容易,还是有一定的可能性,推得很充实,记录一下

暴力模拟一下 DP 转移方式,可以得到这样一个 DP: f_{i, j} 表示 n = i 时,j 个位置是自由的的方案数,有

\[f_{a, b} = \sum_j^b \binom bj\binom bj j! \binom{a - b}{b - j}(b - j)! f_{a - b, b - j} \]

答案是 \(f_{n - m, n} \binom{n - m}m m!\)。直接转移是 n^3 的,复杂度 O(N^3)-O(1),考虑平衡一下,发现初值有值的只有 n 个位置,考虑已计算贡献系数的方式做。

想要尽量简化我的转移,可以考虑设 \(g_{a, b} = f_{a, b} \binom ab b!\)

\[g_{a, b} = \binom ab b! \sum_j^b \binom bj\binom bj j! g_{a - b, b - j} \]

考虑把最外层的 \(\binom ab b!\) 干掉,下面均考虑初值在 \(g_{x,0}\),容易发现外层的这些东西不论 j 如何决策,最后乘起来一定是 \((n - m)!\)

考虑以转移路径的方式刻画 DP:

\[\begin{align} g_{a, b} \times \lambda(b +j, j) \to g_{a +b +j, b + j}\\ \lambda{i, j} = \binom ij \binom ij j! \end{align} \]

可以转化成这样一个问题:

  • \sum b = n - m
  • b_{back} = m
  • \(\prod (\binom{b_{i + 1}}{b_{i +1} - b_i})^2(b_{i + 1} - b_i)!\) 贡献和

\(F_{i,j}\) 表示 \(b = i, \sum b = j\) 的贡献和

\[F_{i, j} \times \lambda(k, k - i) \to F_{k, j + kt} \]

其中 \(t\ge 1\)

容易发现上述 F 的过程很像一个搭楼梯的过程,一个角度是考虑从底层往上搭楼梯而不是如同 F 一样从左往右搭,但是这样是难以计算贡献系数。

观察贡献系数在楼梯上对应部分的组合意义,提示我们考察多个 \(\lambda\) 相乘,发现贡献系数可以化成 \(\prod \frac{1}{k!}\) 之类的形式。

GG 了,上述做法等价于自然数拆分并乘上奇怪系数,复杂度降不下来了。

solution(wmh):很有启发的思路

由上述分析,可以发现如果要做到单次 log 询问是困难的,比如上述做法最终的一个瓶颈会在每次询问的时候可能需要枚举 O(n) 个初值(当然这个瓶颈也许可以通过新增一个 “0 状态”的方式解决)。

应付离线多组询问,可以考虑 整体二分/ 莫队 等等。

换一种计算 \(f_{n, m}\) 的方式,上述做法相当于是枚举了这 m 个自由位,有 j 位的 p_i = 某一个自由位,m - j 位的 p_i = 非自由位;实际上这样是相当愚蠢的,因为没有很好地体现自由位的“自由”,即枚举的 j 个当中,有一部分实际上也是错排;故而,更好的枚举的方式是枚举有 j 个自由位 pj = j,然后让剩下的 n - j 个数字做错排。

\(g_i = (i - 1)(g_{i - 1} + g_{i - 2})\) 表示错排方案数。

\[f_{n, m} = \sum_{i = 0}^m\binom mi g_{n - i} \]

把组合数拆开,可以得到:\(f_{n, m} = f_{n - 1, m - 1} + f_{n, m - 1}\)

考虑使用莫队,把 m 看成行,n 看成列,想着如果知道的每行相邻数字如何递推就好了;即考虑推导出 \(f_{n, m} = \sum \lambda f_{n-\star, m}\) 的形式

结合 \(g_i\) 的递推式,中途利用吸收恒等式 \(\binom mi i = m\binom{m-1}{i-1}\),可以得到

\[f_{n, m}=(n-1)f_{n - 1, m} + (n - m - 1)f_{n - 2, m} \]

此时,考虑 莫队维护相邻两项,简单推导可以发现借助上述两个式子可以 O(1) 处理所有的指针移动。

非常震撼!

solution(lh) 高级生成函数思想,起源于借助二项式反演推出的式子,但是没有听懂,GG,写下这个式子:

\(\sum_i^{n - 2m}(-1)^i\binom{n - 2m}i \binom{n - m - i}m m! (n - 2m - i)!\)

一个关键的点是 (-1)^i 可以凑成 e^{-x},感觉这个想法是很重要的。


T3:高级容斥,理解代码ing。

3.15 模拟赛(gdkoi d2)+ xze 构造

  • 8:00 看完题目,发现今天都是可做题?
  • 8:15 开敲 T1
  • 9:00 打完 T1
  • 9:20 放弃使用 checker,难以造数据
  • 9:30 离开 T1
  • 10:40 T2 束手无策
  • 11:11 T3 自闭
  • 11:45 摆烂

可做就怪了。。。。

T1 的数据是可造的,方法是每次随机三个点,计算出三者距离。幸好没挂听说数据很水

T2 只会 \(n4^nK\) 或者 \(8^n\log K\),比较糗大,没有写的想法。

T3 只会纯暴力,糗大。

下午浅看了一点 cayley 定理和 BM,虽然没看懂就是。晚上听了 xze 的杂题,有些收获,并终于补完了昨天的总结/ll


T3:非常震撼! BFN 序维护子树信息 + 倍增和二进制操作的良好相性

BFN 序维护子树信息适用于点的贡献和深度信息强相关,缺陷在于要求操作可差分。

很强啊,很强啊,做子树信息,已经有了:dfn 序 + 二维偏序/ 分治 DFN / 线段树合并 / 有根树淀粉质 / 淀粉树 / DSU on Tree / BFN 序

这道题,首先考虑序列上怎么做,可以设 \(f_{i, j}\) 表示 u = i,\([i, i + 2^j)\) 的答案,\(f_{i, 0} = v_i\)

\[f_{i, j} = f_{i, j - 1} + f_{i + 2^{j - 1},j-1} + \sum_{k = i + 2^{j - }}^{2^j - 1} (2^{j - 1} - 2^j[v_k \& 2^{j - 1}]) \]

后续的 \sum 的意义是考虑这些点的 dis 的二进制位第 j - 1 位多了一个 1,讨论 v_k 这一维是 0/1。

序列上树,考虑每一个点 u 向最右儿子连边权 1,右儿子向左边一个儿子连边权 0,最左边一个儿子向 u 的左边一个兄弟的右儿子连边权 0;如果 u 没有儿子但是在 u 的同层左侧的点 v 有儿子,将 u 的右儿子设为最近的 v 的右儿子,这样形成一张 DAG。

设 f_{i, j} 表示 u = i, 从 i 开始走 DAG,走 \(< 2^j\) 边权可达的点的答案,实际上也就是直到 i 的 \(2^j\) 级右儿子之前(不包含),每一个右儿子以及其向左衍生出来的一条链。

这样维护的是一个前缀信息,维护方法和序列上类似,处理好后缀和。

求答案的时候只要 u 子树内的,减去 u 的左边一个兄弟的答案即可,由此可以看出为什么要连 黑体 字提到的边。当然另外一个解决方案是先对于 u,把 u 的儿子按照 maxdep 排序?不知道,试了试发现不行,画一画的确存在一些神笔情况难以避免。

3.16 模拟赛 + sjzez 杂题

  • 7:45 T1 想法
  • 8:40 被 T1 细节卡麻了
  • 9:30 T1 自闭
  • 10:00 T1 彻底假了,当做让你 2h30min!/fendou
  • 11:10 放弃 T1
  • 11:23 发现 T2 是原

今天最大的失误在于时间分配的问题,在于开场的时候没有细看题目,只是把 T123 大致扫完一眼就上厕所去了,然后回来就开打 T1。

T2 最终一点点没有改完,再给我 5s 可以 32pts \(\to\) 80pts /ll,当时只差最后一点点就可以改对了,但是分析慢了。

虽然这把花了 2h30min 的时间去写 T1 淀粉质的假做法(淀粉质假在无法处理一条从当前子树往外走的路径对自己子树内部的贡献),并在不断尝试修复的的过程中失去了脑子;虽然 T2 最终一步之遥;但是还是感觉打得比较充实,打完没有预想的伤心。

感觉人的心情是很奇怪的,往往和自己所想象的不同。


T1:大骗子!! \(x\times y \ge lca(x, y)\) 的条件不是用于考虑根号算法之类,而是考虑容斥成为 \(x\times y < lca(x, y)\),此时发现可能合法的 (x,y) 只会有 nlogn 对,那么问题瞬间好做起来了。

这种诈骗东西,还有 AHOI2013 钥匙;wyb 自己出的水题:生生不息。

接下来的问题考虑换根 DP,容易求出 ans[1],考虑换根 \(u\to v\) 的过程,发现对于所有不经过边 \((u, v)\) 的路径,贡献不变,所以

\[\delta = \sum_{(x, y) pass\ (u, v)} [x\times y < v]-[x\times y < u] \]

考虑离线排序,问题是 nlogn 个链加和 2n 个单点查询,用树上差分。

复杂度 \(O(nlog^2n)\),没有必要执行根号平衡。


T2:原。海亮NOI集训 传统。

考场 80pts 与正解的差距细小,再给时间有信心做出来。


晚上听杂题,由于比较困所以感觉效果不是很好。

写了CF626F Group Projects 和 agc032_e Modulo Pairing。

3.17 模拟赛 + zzq 分治分块

  • 8:50 T1 好难/kk
  • 9:50 草,通过打暴力,发现 T1 读错了一个重要小细节/jk/jk/jk,下次一定!
  • 11:20 过 T1 大样例,md!今天又送了 2h30min 出去!打个锤子!

/kel


T1,最开始读成了第 i 轮,将 \forall k > i 的 a_k,交换成 \(a_{1...k - 1}\) 中某一个比他大的,实际上是 \(a_{1...i}\) 中。

因为只有按照我读错的题意,一个 ai 才会生成多个 ci,所以当时没有产生怀疑。大骗子。

然后发现这道题有点不可做起来了,想到 jly 名言:“T1不过你过锤子啊;不过题打个锤子啊”,简单看了看 T23 的题目,决定死磕。

思考方向诸如:

  • 通过手摸多个 n = 5 的情况寻找性质
  • 从逆序对角度思考,思考和冒泡排序的关联
  • 思考不同 ai 对应的 {ci} 的关联,比如是否不交(实际上有交集)
  • 思考建立 ai 和 xi 的双射,xi 表示位置 i 被操作的总次数,和 ci 是一个转置的关系
  • 考虑快速 ai->pi

很烦,啥都不行,GG。

实在没办法,开始打暴力,发现暴力写不对,发现读错题了/ll/fn/ll

题意正确之后,发现 ai 唯一生成一个一个一个 ci,那么瞬间好做起来了。简单模拟可以发现第 i 轮之后前i个必然是 1...i,那么有良好的子问题性质,用力分析即可。

solution(wzy):考虑和冒泡排序的关系,虽然没听太懂,但是这个思考是有益的。


T2(solution):分析 (i, j), (n - i + 1, j), (n - i + 1, m - j + 1), (i, m - j + 1) 四个位置,发现容易构造出一种操作序列,使得将其中三个位置执行一个轮换,而矩阵其他所有位置都不改变。

发现通过这样的操作,在不对这四个位置进行其他操作的情况下,可以到达所有的奇偶性相同的排列,12 种。

特别的,如果存在相同的数字,那么可以达到偶排列,但是方案数变成多重集。

把不存在相同位置的这样的组提出来,我们还可以通过预先做一些操作,改变这些组的奇偶性,但是注意到做一个操作,可能会同时改变多个组的奇偶性。现在问题是问有多少种本质不同的奇偶性改变合法方案,两个方案不同,当且仅当存在一个组在两个方案的奇偶性不同。

可以以一个组的左上角 (i, j) 来刻画整个组,即我只需要关心 (i, j) 被操作的次数的奇偶性。

考虑一个经典(?)的建模,将行视作左部点,列视作右部点,对点 (i, j) 连边 i, j。对于新图上的一个点,颜色是 0/1;一条边,颜色是两个端点的异或。现在求把点染色,边颜色本质不同的方案数。

此时,由于是二分图,连边后可以看做是形成了若干个森林。对于森林中的每一个树,发现由于 取值均匀,根的颜色不重要,给根钦定是 0,那么发现剩下点的染色方案和边的染色方案一一对应,所以一个树的方案书是 2^{n - 1};总方案是 2^{n - c}, c 是连通块个数。

特殊处理 n 是奇数/ m 是奇数时,中间行/列的特殊情况


T3(solution):探讨一条链的情况,发现 A必胜 当且仅当 B 选择的连通块 1 不是直径中心,此时 A 第一步可以跳到对称点上去,此后无论 B 怎么操作, A 都可以走到对称点上,那么 A 必胜。

容易发现这个结论可以扩展到树上,所以,B 选择联通块的方案是使得 1 是直径中心。

\(f_{u, d}\) 表示在 u 子树内选连通块,最深点距离 u 长度 d 的方案数,有 \(f_{u, d} = \prod f_{v, 1\dots d + 1}, f_{u, 0} = 1\)

暴力转移 O(n^2),与深度有关的 DP,可以考虑长链剖分优化。

改为计算 f 的前缀和,那么转移是点乘和整体 +1 两个部分。长儿子直接继承,考虑短链合并的过程,注意到 f 的空间的问题,假设有短链长分别是 mxd[v1], mxd[v2],如果二者合并的时候都只用 \(f[v1][1...mxd[v1]]\) 的部分给 f[u],显然是不行的,但是又关注到 \(f[v1][mxd[v1] + 1...n] = f[v1][mxd[v1]]\),所以实际上的操作是暴力贡献 \(1\dots mxd[v1]\),然后在 \(f[u][mxd[v1] + 1]\) 的位置打上乘法懒标记,最后整体 +1 打上加法懒标记。

每次在 \(f_v\to f_u\) 的时候,记得把 u 上前 mxd 个标记推下去。

由于原问题计算的是以 1 为直径的连通块个数,答案是 \(\sum_d \sum_{sp1, sp2}(f_{sp1, d} - f_{sp1, d - 1})\times(f_{sp2, d} - f_{sp2, d - 1})\prod_{v\in sons(1) \cap v \neq sp1 \cap v \neq sp2}f_{v, d}\)

一个细节是 dp 不要计算 f_1,否则由于 1 和其重儿子共享了空间,调用重儿子的 dp 值会出错。实际上也就是说,长链剖分其实是离线算法。


晚上听分治分块,有一两道题不太懂

posted @ 2024-02-29 21:41  _Famiglistimo  阅读(56)  评论(0编辑  收藏  举报