2022 10 月总结

十月份。

10.2

md,怎么一来就是 DS。讲课老哥一直在鼓励提问,问题是没有会议号怎么提问。

感觉讲得有点快,太久没有认真搞 OI 了,感觉这才是应该有的强度, whk 强度不够!

爷们儿要战斗!

中午打球很久导致没有睡觉,下午......

晚上被 CF1261F Xor-Set 干傻了,思维卡在了一个奇怪的地方,下次中午一定要睡觉/fendou

DS 题先思考如何处理询问,再思考修改

[CF765F]Souvenir

naive: 首先我们可以莫队 \(n\sqrt{m}\log n\) 爆艹对吧,然后呢?

考虑主席树?但是你主席树也处理不了这种 min 的区间询问啊。

往莫队方向思考,假装 \(n\sqrt{m}\) 可以接受,思考把复杂度往 qlogn 这边转。但是不会。

more and more vegetables I have, what can I do?

sol: 莫队的“救赎”

sol2:

套路:离线之后,固定 r, DS 维护 l 的答案

此套路的应用举例:

  • CF526F Pudding Monsters 3000 以及它的升级版:CF997E Good Subsegments
  • NOI2022 D2T2 最后一步计算产生逆序对最少的位置的线段树处理。

此处有所不同,因为直接维护答案比较抽象,此处维护的是 \(ans[l] = min_{l < i \le r}\{|a[l] - a[i]|\}\),求答案还需要做一个后缀最小值。

考虑 \(r - 1\to r\) 的变化。发现如果又要更新 a[i] < a[r],又要更新 a[i] > a[r] 很烦,不妨做两次,每次只更新 >

暴力更新未免太多了,显然每次只需要更新一条单调不降的链,但是还是很多。具体的,记 prei 表示最后一个 < a[i] 的下标,需要更新的大致就是一条 pre 链(除了链尾)

思考,还有啥信息没有用完。

因为贡献是绝对值,而我们刚刚只有保证 > a[i] 的贡献,没有注意到的是这条 pre 链之间的数是完成了贡献的。

可以发现,假如已经用 i 贡献了 pre[i], 那么下一个位置必须 < (a[i] + a[pre[i]]) / 2。

那么这样每次值砍半,pre 可以用值域线段树找,\(O(n\logn\logV)\)

苦涩(sorrow)

naive: 对区间最大值进行操作,这很吉司机,复杂度应该会往这边靠。心绪不宁(划水,没多想。

sol:

先标记永久化一下,每次操作最大值,对于那些误杀的节点,insert 进去就好。这种误杀发生次数 qlog 次(?),每次 log 处理。每次只会往下面递归一支,找到具体叶子和删除并列,也是两个 log。

bugs:

基本一遍过,但是不懂为什么线段树开 4 倍会 RE。

upd:理解了。线段树因为 mid = (l + r) / 2,会多一层,然后这个位置代码实现对叶子做了 pushup。

CF1261F Xor-Set

非常神的一道题。

首先考虑暴力,发现 n^2 个区间对应计算真的很烦,没有性质。

但是注意到如果把一个区间分割成为 \(O(log)\) 个小区间,每个区间代表范围 \([C, C + 2^k), 2^k | C\), 也就是二进制高位固定,低位可以取遍所有。那么,这样性质的两个区间进行异或是非常舒服的, 得到的也是满足上述形式的区间。

拆区间可以用线段树搞,左儿子表示 C << 1,深度表示 C 的二进制位数。

现在是 n2log2 个,要去重,所以还要排序。

优化。注意到上述的浪费在于,实际上,当我们把某一个 [l, r] 往下拆分成多个区间时,毫无疑问,这些区间都要与 A 中某一个 [L, R] 进行操作。观察这些操作,发现所有分出的 [l, r] 的 C 按照线段树上的路径,补成和 [L, R] 一样长,再进行异或是等价的,或本应如此的。

题解表述:一个长度为 2^x 的区间 A 和一个长度为 2^y 的区间 B 异或,其实也就等价于 A 与另一个同样长度为 2^x 的区间 C 异或,其中 C 比 2^x 更高的位和 B 相同。

考虑维护两棵线段树,第一棵存 A 集合区间包含的所有节点,第二棵存 B 集合区间经过的所有节点,然后把两棵树同一层存下的所有区间两两异或,再交换两集合重新做一遍,可以发现这样依然是对的。每一层的区间数是 O(n) 的,这样最终得到的答案区间数就是 O(n^2logV),

CF1658E Gojou and Matrix Game

全讲中最简单的一道题吧。。

首先最大值点肯定是可以选的,反复很跳即可。

次大值要选必须保证最大值在 k-距离 之内。

次次大值呢?简单分讨之后可以发现求解方法和 SG 函数一样。

抽象总结一下,每一个人下一步必须走比当前格点大的,所以 SG。

(没写代码。

upd 10.11 写了。

BZOJ2122 工作评估

naive:首先注意到出现一个 top, 那么后续的操作是固定的。问题在于可能一直没有 top 咋办。

数据范围提示分块,每一个块需要实现的是一个关于初始价格的函数,非常难蚌。还需要考虑的是块内的区间等等。

sol:

nq 做法:记 cur 表示当前钱数,小于初始 w 就 cur = w,取过程中 cur 最大值。

设 f(l,r,w) 为初始资金为 w,从 l 走到 r 最终的钱数,\(s_{l,r} =∑_{l≤i≤r}ai\)
那么就有 \(f(l,r,w) = min(f(l,r, inf),w + s_{l,r})\)

考虑分块,因为是取过程中最大值,所以分成四种情况考虑:

首先 \(O(n^2)\) 预处理一下 f(l, r, inf) (?)

  • 块外进块内结束:取出 \(\frac nB\) 个二元组 \((f(l, l\dots l + \frac nb, inf), s_{l, l\dots l+\frac nb})\),做成一个单调栈,而后根据 w,在单调栈上二分出取 top 的点。
  • 块内开块内结束:块长平方个二元组
  • 块内开快外出:取出后缀区间。
  • 块外进块外出:一个。

上面的单调栈都可以提前预处理出来,块长根号很合适。

10.3

把昨天最后一道题补完了。

晚上偶然看到有人用了根号平衡的 TRICK, 去找 lxl 的 ppt 简单复习了一下。

写今天第三道题的时候代码实现明明很简单但是被卡了很久,原因是压行导致的把括号范围看歪了。c,裂开、心态炸了。

CF1527E Partition Game

naive:

想了一个 n^2k 的 DP 死活优化不动,看了一眼 PPT,发现他把这道题标注为一道分治决策单调性的升级版,懂了。

浅证一下决策单调性。

第一,\(w(i + 1, j) + w(i, j - 1) \le w(i, j) + w(i + 1, j - 1)\)

即证:\(w(i + 1, j) - w(i + 1, j - 1) \le w(i, j) - w(i, j - 1)\)

显然,都是新增一个 \(j\),但是右式范围更宽广,更可能出现 pre.

其次,设 \(f_{p,j - 1}+ w(p + 1, i) = \min{f_{k \le i, j - 1} + w(k + 1, i)}\)

那么 \(\not\exist q<p, f_{q,j-1}+w(q+1,i+1)\le f_{p,j-1}+w(p+1,i+1)\)

反证法:\(\exist q < p, f_{q,j-1}+w(q+1,i+1)\le \min{f_{k \le i, j - 1} + w(k + 1, i)} + w(p+1,i+1)-w(p+1,i)\)

\(k = q\), 那么 \(w(q+1, i+1)+w(p+1,i)\le w(q+1, i)+w(p+1,i+1)\) ,这是违反四边形不等式的,所以假设不成立。

所以直接套分治优化决策单调性就好,复杂度单 log ?

一共花了 1h50min 把这道题搞出来的,但是实际上写的是一个复杂度错误的分治(遍历[最左决策,中间询问))/jk/jk/jk

sol2:观察转移,拆开 w,w 是简单分段函数,所以可以线段树。

CF1175G Yet Another Partiton Problem

naive:

我们继续猜决策单调。

想证明 \(w(i + 1, j) - w(i + 1, j - 1) \le w(i, j) - w(i, j - 1)\)

分讨一下,如果 j 是新的最大值,那么左边区间长度小;j 不是,左边区间长度小。

仿照上述做法即可,问题在于如何算 w,可以类似莫队算?(可以使用上面的假做法暴力算

md,好像必须要 log^2。

想象了一下,考虑 \(f_{i,j} \to f_{k>i, j+1}\),把 k 当成横坐标,\(f_{i,j}+w\) 当成纵坐标,那么这长成一个斜率上升的下凸壳(若干条线段)的样子。整体就是多个凸壳叠在一起取凸包。

这貌似很李超线段树,这个思考也留下一个斜率优化的方向。

考虑李超在干嘛,问题在于一个 \(f_{i,j}\) 会插入多条线段,而且插入线段的复杂度是 log^2 /jk

发现这些线段的特点是斜率固定,很多平行线,只是截距在变化。可以看出很多线段都是重复的,强者恒强,弱者恒弱。

搞不懂了/yun,感觉截距一变化,delta 非常难蚌。

考虑结合之前所述决策单调性?于是可以发现,\(f_{i}\) 的凸壳肯定是压在 \(f_{i+1}\) 上面的!

呸,错误的,这个性质是错的。

仔细想想,好像如果这样的话,我有 nk 做法???

呸,错误的,每一个 fi 的凸壳不是连续的,所以不存在什么强者恒强的说法,G。

唔?好像依旧满足强者恒强?很奇怪,感觉可能是脑子不太行了。

回头看了一眼那个决策单调性,突然发现证明错了,如果 j 是新的最大值,存在问题。G

sol:

Salieri 写得比较清楚 上述方向正确,但进一步走没有可以用的性质了,所以这里考虑直接暴力处理这个玩意。

  • 假如当前想要求解 f[i], 它首先会被多种斜率(多种最大值)的线覆盖(称之为一类直线),具体的,是把 a 做成单调栈之后的栈中的那些斜率。
  • 如上所述,这存在多条平行线的关系,我们还需要找到每一种斜率对应的最小截距。
  • 在找到最小截距之后,把这条直线加入李超线段树即可
  • 在李超线段树上询问 f[i]
  • \(i\to i + 1\),由于可能存在单调栈形态的改变,所以涉及到李超线段树的撤销,使用可撤销李超线段树/可持久化李超线段树。
  • 单调栈形态改变之后,需要快速算出新的截距。
  • 对于相同的 最大值 M(斜率)截距的计算方法是:\(f_i = \min{f_j-jM+iM}\),欲令 \(f_i\) 最小,iM 对所有 j 一视同仁所以扔掉,想让 f_j - jM 最小,视 -j 为斜率,f_j 为截距做斜率优化即可(称之为二类直线)。
  • 这里涉及到单调栈形态改变之后合并多条二类直线的问题,斜率优化如果用凸包做那么就是启发式合并凸包,但是上面都已经来了一个李超了,来都来了,干脆李超线段树合并。
  • 李超线段树合并的时间复杂度分析

正确的。

bugs:一箩筐。特别注意空间的开法。

CF1699E Three Days Grace

naive:

可以唯一分解之后理解为找到拼凑的最优方案,有点 DP 套 DP 的味道,但是难搞。

极差考虑双指针。可以发现 l 最多到最小值。进一步思考,l 当超过某一个数字的根号的时候就会使得一个数字固定。

首要的问题是 l, r 的范围太大,次要的问题在于如何判断一个数能不能拆成 [l, r]。我的评价是都很抽象。

暴力做咋做,暴力就是随机组合每个数的质因数。

注意到总质因子种类不会太多。

sol:

我的思考的最大问题在于顾及到多个数字之间的相互制约而一直不肯把目光放在单个数字的处理,没有把问题切开。

这道题是妙妙题

化解为求解 f[i, j] 表示把 j 分成 \(\ge i\) 的最大值最小。f[j] 仅在 i|j 的时候 f[j] =min(f[j],f[j/i]),所以刷出 f[i, j] 只需要 mlogm 的时间。

再用双指针的思想。倒序枚举 l,求解 f[l, j],询问 f 最大值可以把 f 丢进桶执行根号平衡或者知道 r 递减直接往下扫。

10.4

有趣的博弈论,上午大脑飞速旋转,非常充实。

下午小困,问题不大。晚上略颓。晚上给 zqm 讲了 Alice 和 Bob 又在玩游戏。

强烈要求 放 10.7 晚自习 + 10.8 上午 而不是 10.8 下午。

想不明白为什么放下午,回去吃饭睡午觉吃饭然后就回来了,放了和没放没啥区别。

搞不懂,平时周末好歹也算是放了一天,重点是放了一个晚上,可以睡懒觉,非常有助于学习工作节奏的调整。

UOJ 51 元旦三侠的游戏

签到,状态数很少,直接 SG。

QOJ 4808 Great Party

naive:

手模了 n = 1, 2, 3 猜到了:

结论:n 为奇数,先手必胜;n 为偶数,后手必胜

结论的证明:

2k - 1 成立推 2k:如果 xorsum ai-1 = 0 那么先手将会面对 2k + 1 的必败情况。

2k 成立推 2k + 1:

下面默认 ai = ai - 1;

记 s 为异或和,只需要保证能够找到一对(i,j),然后让 j 只剩下 d=(ajkai)-ai 并把 d 送给 ai 就好。然后这个 d 需要保证 0 <= d < aj,这是可以满足的。

对于 n=3 的话,考虑 x y z 二进制数最高位。要么 1 个 1,要么 3 个 1。若只有 x 最高= 1 的话,那么满足 y - z <= x, 对应 d <= aj, 选 aj = x, ai = z 就好。若 3 个 1 ,此时 x y z 随便抓两个数,做差都小于第三个数。然后对于更大的 n,1 个 1 就选最大值为 a,3/5/7/9/... 个 1 只需要选中最大值为 aj,ai 为最高位是
1 的某一个,剩下的数的异或和最高位必然也是 1,所以差值 < aj。

sol:

猜出结论之后,询问的意思是问区间有多少个二元组,这很莫队。

QOJ 2213 Knight

naive: 啥都不会。

sol:

显然染色后是多个二分图。

(证明:将 (r,c) 视作向量,设 (r, c) 与 x 正半轴的夹角为 alpha, 那么希求 2PI/alpha 为奇数。这是不可能的,因为当 r, c 为整数时,tanalpha 为有理数,遍历 360 的奇数因子,没有。(好像多此一举了,最开始以为可以直接证明 alpha 只能取小数/无理数))

若 a, b 不在同一个二分图,那么结束与偶步之后,都是偶环,所以 a 必胜。

若 a, b 在同一个二分图且同色,那么 b 不可能对 a 造成干扰,和前面一种情况一样。

若 a, b 在同一个二分图不同色,那么 b 必胜。 b 的策略是先随便选择一条能走到 a 的增广路,不管 a 怎么走,对着增广路上下一条边反复横跳,直到自己要不合法了,就往增广路推进一步。由于 B 在换边,所以不会存在跳着跳着 b 不能反复横跳的情况。然后就把 A 卡住了。

Alice 和 Bob 又在玩游戏

给 zqm 讲过一遍,所以认为理解到位了,不用再写一遍了。

一句话:视一个局面为以某点为根的树,选择子树内某一个点为转移到下一个局面的方式,下一个局面的 SG 是各个子树等等部分的异或和,对所有局面取 mex 得到当前 sg,用 Trie 优化上述过程。

QOJ 2103 Termity

神仙题。

首先我们假装序列长成 0.....0

性质1:如果最大值在边界上,那么第一步肯定是取最大值。如果最大值是唯一的,那么第一步最优策略是唯一的。

性质2:对于形如 \(x<M>y\) 的三个数,如若先手取 x,那么后手必然取 M(边界最大值),那么先手必然取 y。因为考虑如果此时先手取 x 是最优策略,那么唯一的解释是想要取 y。因为取 x 会把 M 送给对面,如果不取 y 而去取另外一边,那不如直接去另外一侧博弈。缩成一个点 x+M-y

利用上面两个性质,最后缩成一个单谷序列的样子,从大到小排序即可。多个 0...0 段混在一起排序即可。

问题在于有形如 ....0 的段,此时直接取最大值可能是不合法的。再次利用性质,思考这样一段序列,前面的单降序列必然是在这段结束阶段的时候操作的,且对于 AB....0,套用类似上面的结论,如果先手取了 B,那么后手必然取 A。所以预处理一下就好,到底是谁先取根据非 0 数总数奇偶性来判断。

小细节:3 合 1 可能会连续发生多次,写 while 而不是 if

10.5

好像这几天都是上午状态不错,下午直接萎掉,可能是因为中午打了球之后影响了睡眠。

感觉今天做题,做 T2 的时候是很好的,做其他题的时候都有点急着看题解的意思。

[APIO2010] 巡逻

简单图论,简单分析之后知道应该就是求两遍直径的事情。

一个值得注意的问题是如果有负权,那么不能两遍 dfs 求直径,只能用 DP,因为两遍 dfs 的原理是保证能够找到直径的一个端点。

[CEOI2019] Dynamic Diameter

naive1:

如果非强制在线的话,CDQ 应该是可以的,只需要仿照 WD 与地图,使用合并两个联通块的直径的做法,这样应该是可以做的?

强制在线,有点动态 DP,上一个树剖,每一个节点开一个线段树维护轻儿子,每条链开一个线段树。(在 bfn, dfn 上分别开两颗线段树)。然后还需要用一个 BIT 维护每一个点到链顶的距离。这样是 nlog^2。

发现这样很蠢,没有必要专门用一个 BIT 维护,dep 小容斥一下就好。

写了一下,发现有点不对。

啊啊啊真的烦,为了得到答案,每次得把所有链顶问一遍?这样是不行的,c,好像 G 了,BFN TREE 只维护了轻儿子。

回顾上述算法:树剖,求初始d1d2,BIT 维护点到根的距离,SEGB 维护 bfn 上 (d1+到父亲边权,d2+到父亲边权) 二元组的合并。 SEGD 维护 dfn 上 (轻儿子d1+到根距离,轻儿子d2+到根距离)。每次查询一个点的 (d1,d2) 相当于查询从这个点到重链底的 SEGD 然后减去 2*自己到根距离。每次修改一条边边权,首先在 BIT 上修改,然后在 SEGD 上做一个区间加法。查出 top 的 (d1, d2),然后在 SEGB 上单点修改,然后在 SEGD 上单点修改 top(作为 f[top] 的轻儿子),然后令 x = f[top] 重复上述这一句话。

上述结构的作用在于实现了 \(O(log^2n)\) 修改一条边边权,\(O(log)\) 询问单点 (d1,d2)。是无法应对询问的,一个思考是树套树,观察到修改一次边权只会影响到 点到根的路径上的(d1,d2),但是实际上这些 (d1, d2) 现在还是不知道的,还需要花 Log 时间查出来,所以套毛线。

再思考,想要维护实时的 (d1, d2),每次改权理解为类似单调栈推平。不妨二分一下会替换哪些 d1, 那些 (d2),这样是 log^2,然后就有了做区间修改的权力了,再开一个线段树维护实时(d1,d2),取 max(d1+d2) 来维护答案即可。

一个问题在于需要把点到根的路径提出来,不然我咋知道当前我二分到什么地方了。二分不好做,用倍增做,即另外一种 lca 求法,预处理 2^k 级祖先

md,以后在想这种题的时候一定要把算法流程写下来,空想就容易导致发生上面忘记自己的想法的情况。导致修锅的时候修的不是同一口锅

感觉上面的做法应该是修对了吧,但是不想写了。/ts

naive2: 换一个方向思考,思考合并联通块直径的思路,容易得到一个 log^2 的做法。每次对一部分 repushup 就好。

naive3:发现 naive1 最大的掣肘在于 (d1, d2) 和 d1 + d2 的割裂,想着能不能找一个方法合起来。不会,GG

sol1: 对naive1因为dp状态太丑而无法套ddp的解救
全局平衡二叉树优化

sol2: naive2 的实现举例

sol3:优雅欧拉序+线段树 维护方式有点巧妙,不必保证贡献有正确性,保证错误贡献较小即可。

跳蚤王国的宰相

知道重心答案为 0

考虑重心的儿子,做法是把重心的其他儿子排序,从大到小嫖。

考虑重心儿子的子树,显然是可以从所属的重心的儿子 + 1 步转移的(再切重心)。
或者是继续砍重心的其他儿子,此时也是从大到小嫖。

注意第二种方式,存在双指针的意思,对于重心的每一个子树内的点,分别按照 n - siz 排序,双指针。

[CEOI2019] Magic Tree

naive:显然树形 DP。上一个线段树合并就好,但是想起了被 [BZOJ4919]大根堆 支配的恐惧(2022HL总结

这样伴随的问题是不能 !p || !q 时立即 return ,因为这样没有把 pt 和 qt 的影响辐射到 p + q 里面
所以这个做法 G 了,维护区间max的标记的做法在这道题线段树合并的要求之下并不适用,GG
另外一个视角看待,此处由于单调性,所以每次实际上是仅仅是区间加 1 ,发现维护区间加法标记非常好写,一发就过/hanx
为了规避上述中存在的种种问题,可以直接维护 f[i][j] 表示长度为 j 需要的最小值。这样进行 DP ,就不存在什么区间 max,区间增加之类的问题了
这种解法也可以使用 multiset 做启发式合并

(具体还是进去看吧)

所以直接暴力想要上最大值线段树合并是不行的。

解决方法 1:如上所总结的:区间加法非常好做,所以 Yansuan_HCL

sol:

解决方法 2:每次继承某个单调序列,然后对这个单调序列的后缀取 max。这个玩意很像什么?像 JOISC 2019 day2 两道料理!

所以我们可以维护差分序列,可以 线段树合并+线段树二分 / 启发式合并 map

所以这道题就是两个见过的技巧合起来

[BALTICOI 2016] 交换

神仙,抽象,高明。

设 a = val[rt], b = val[ls], c = val[rs]

最难处理的是 a > min(b, c) && b > c 的情况,涉及到 a b 谁进左子树,谁进右子树的问题。不妨设 a < b。

性质:在最后的答案序列中, a 放在 b 的前面。这是显然的,设 a 进左子树按照“策略”走到 p1, 进右子树走到 p2,如若 p1 < p2,那么肯定不会迁就 b,会让 a 进左子树。因为根据性质,如果把 b 放进左子树按“策略”走到的位置 >= p1,肯定不优。

“策略”:dfs(u, v) 表示 v 现在走到 u,贪心走最后会走到哪里。类似上述 a b c 交换方式进行贪心。特殊在于,需要讨论 a 和 b 的大小。若 a > b,那么要迁就 b 的意愿,要算出 dfs(ls,b) dfs(rs,b),让 b 尽量取小。若 a > b,直接取 min(dfs(ls,v), dfs(rs, v))。

note:上面让 A 进左子树更正确的理解是:A 能放到 p1 说明它有本事,它放 p1 很优(注意“策略”里面是关注了 b 的意愿,不会使得原字典序变坏)。如果把它放 p2,就浪费了它的天赋了,显然不优。

很对,很对。

树高 log,所以可能的爆搜状态 nlog。

sol2:(没弄懂)

用 dp 计算上述 dfs(u,v),即设 f[u][v] 表示点 u 上放 v 最小走到哪里。

这个显然是可以转移的,而且是长成 f[ls] f[rs] 两个单调不降序列的 min,尤其观察到 f 是一些连续的颜色段,所以可以 ODT 优化。

sol3:(没懂)

只有 左儿子/右儿子/祖先和祖先的左儿子 可以到达,通过巨大分类讨论得出那些是真的可以到的,顺次处理,贪心取值。

10.6

上午写了 [BALTICOI 2016] 交换,思考学习了 拜神。

下午和 zqm 讨论 [BALTICOI 2016] 交换, 有了更深刻的理解。

晚上略有浮躁,有点水。

「JZOI-1」拜神

神仙题。

naive: 去复习了一下 SA 的那套东西。

解放一个 height 的意义是合并 sa[i] 和 sa[i - 1] 联通块。

想到可以二分答案然后对 height 分组。但是还是很难判断。

sol:/bx alex

现在想知道的是每一个 i 下一个最近的同连通块的点是啥,知道之后可以线段树区间最小值。

考虑 height 的解放过程,不妨把 height 从大到小排序然后预处理线段树 T[1...n] 表示 >= i 的 height 解放之后,每一个点下一个同联通块点下标的最小值。这很双指针。

每次合并连通块启发式合并,在 set 里面 upper_bound 一下然后到线段树里面更新。

这里线段树肯定是要可持久化的,所以上述的更新操作也需要放到一起做,不能一次更新 insert 一下,不然空间开不下。

这样,空间复杂度上界启发式合并的次数乘树高,即 nlog^2n,时间复杂度 nlog2n+qlog2n。

类似题目:NOI2015 品酒大会。

CF555E Case of Computer Network

naive:

一眼竞赛图,但是不是完全图。

每条边两个方向,考虑 2-SAT 但是连不出限制边。

考虑建图,考虑必经点那一套,不行。

考虑网络流,考虑可行流,GG

考虑 LGV,但是好像复杂度不行?(不懂 LGV 理论)

观察样例,Sample1 给出了一个基环树,发现如果存在环的话,环可以缩成一个点。

放到无向图上,就是把边双缩掉,那么一棵树,剩下的随便做了。

sol:剩下可以用树上差分记录两个方向定向次数做。

20min 写完 一遍过/hanx,刚好 100 行代码。

[GXOI/GZOI2019]旅行者

naive:因为做过 [ZJOI2016]旅行者,所以见过这种类似分治的方法,感觉很可做但是没有细想,这个行为需要反思。

对于 DAG 的部分分,最短路径树之后就好做了。

sol1:类似 [ZJOI2016]旅行者,处理 f[i] g[i] 表示这个点走到某个关键点/从关键点走到最短路。

sol2:对关键点二进制分组跑 logV 次最短路。xht

15min 一遍过。(图论就是好啊,板子好写)

[AHOI2022] 钥匙

naive:在思考部分分,在往根号平衡这边靠,但是不会。

视作括号匹配,求出可贡献点对,转化为矩形加,单点查询,离线树状数组。

这道题最妙的地方在于统计询问路径覆盖了多少已知点对,转化为 dfn 序上已知点对对询问路径贡献次数。

写调 50min

反思做这道题的时候的注意力不集中和中途打摆,反思今天整体动力不够,心绪芜杂:太过于渴望,沉溺于虚幻的想象,反而扼杀了自己的可能。

10.7

pb 的东西听不太懂,上午来的时候有点困,睡了 20min

起来直接看题解,跟着 pb勉强悟了一点。然后滚去补图论。

下来大致看懂了CF1693E Outermost Maximums CF1687E Become Big For Me pbT6

AGC044B Joker

最开始想错了,误以为可以通过相邻两个位置时间戳大小固定边权。

题解很妙,因为所有位置不考虑有人离开的步数总和 n^3,所以每次直接暴力 upd 维护 dis_t[i][j] 表示时刻 t 的 ans(i, j)

20220923 T2 距离

naive:看到 min,我们想到经典老梗 "min-max" 容斥:min=2*all-max

正好 max 是切比雪夫,所以结束。

10.8 模拟赛

今天垫底,20pts,谁与争锋。

考场上感觉头脑状态不是很好,有点晕。

T3 看错题目浪费 1h ,沉没成本直接上头。决策失误,不打暴力就开冲,死得惨。

T1 一来不是很敢开代码,感觉应该是一道细节题,想了想暴力然后走。

T2 乱入 SG,然后 DP 计数感觉状态数有点多,口胡了一个线性基以为可以优化状态但是没有正确性。

T3 看成求最大长度,1h 不会。感觉应该是要设闸值然后两个做法。搞了一个 k 比较大线段树分治 nlogqlogn,k 比较小狂暴 bitset。问题在于线段树分治复杂度算错了,是 nlogqlogn*mx;bitset 计算存活点个数的时候没有去重。

T4 会了暴力走人。

由于放弃 T3 的时候只剩下 1h 了,决策是 T2-T4-T1,但是发现 T2 SG 是错的,修了半天不懂。

剩下一点点时间,以为 T1 暴力比较好打,但是时间确实不够。

本以为要保灵,T2 乱搞居然 20,6.

反思一下,T2 大概是 SG 玩傻了;T3 是眼前一亮的,以前一直认为这种根号平衡的题目一定是两个做法结合,第一次见到合在一起做的;T4 眼前一亮,高明聪慧的 DP 优化。但是主要问题还是决策,可能有影响的是状态确实不佳.

静下心来(好难

忘记今天有 ABC 了/fn,以为今天是星期天/kel, unr 看了 DEFG,然后去学习 zqm 的博客了。

20220921 T3

sb 题,状态数很少。 没写代码。

20220921 T4

上厕所的时候想了一个根号平衡做法,但是走回来就忘记了,GG。

首先直接维护序列长啥样是不行的,平衡树是可以修改了,但是你怎么询问呢。

如果把每一个序列中的人视作 (位置,时间戳)二元组,即辅助一维?不行、

sol:如果把连续的相同小组的人缩在一起,那么插队不会产生影响

惊为天人。(所以还是维护了序列长啥样)没写代码。

10.9 模拟赛

考得很菜,感觉状态真差,考场上没有那种做题的时候的感觉,感觉这两天都有点头晕,每场都没有深入思考的经历。

也许这就是结局吧,with profound sorrow surrounding

做 ARC, 但是不会 B,人都傻了。

upd:会 B 的,被细节卡死了/ll

10.10

上午状态不错,下午有点困,晚上状态不错。

晚上后面在和 zqm 讨论 zqm 自己出的题,非常有趣的体验。

今天略微划水,因为最近是 LOL 世界赛/xyx

[SNOI2019]通信

naive:第一眼感觉很网络流,感觉 |ai-aj| 的贡献有点 ARC122F 的味道,这很建图。但是网络流怎么表示一连串数字的和呢?不知道,否掉。

题目可以转化为最小权链覆盖之类,或者设置一个虚点,转化为固定起点的最小权链覆盖。贪心地想,把 ai 视作重力势能,那么每次肯定是选择极值点。那么可以考虑 DP。但是状态数有点难蚌,没找到优化空间。

sol:

网络流确实不能表示一连串数字和,但是费用流可以。

所以建图:s->i(1,0) i->j+n(1,abs) i->T (1,0) i + n->T(1,0)(错误建图:s->i W 费用,i->j |ai-aj| 费用,i->T 0 费用。均为 1 流量,问题在于 W 变成必经)

考虑优化建图,每次连边 i -> j+n 的条件是 j < i,这很 cdq,所以考虑分治建图。然后类似 BZOJ 2259,把当前区间 [l, r] 的数排序去重,[l,mid] 被对应点连,[mid + 1, r] 链接对应点。这条数轴作为结构,流量 inf。

很妙啊,一遍过。

[NOI2019] 弹跳

naive:

第一眼以为可以可持久化值域线段树优化建图,即把 x 当成时间,y 当成值域。

有两种处理方式,一种是动态开店,然后每一个点上开一个 vector,一路 insert 一路 pushback;一种是只在叶子节点开 vector。

但是这样的问题是,vector 并没有可减性,对于第二种做法,显然的缺陷是当你 insert 到叶子的时候,不敢连边上一个版本的叶子,本质是,这种可持久化线段树实际上是一种可以获取前缀时间信息的线段树,只是在普通线段树优化建图的基础上附加前缀信息。
对于第一种做法,同样有问题,对于当前想要连边的一个节点,与第二种面临同样的尴尬,解决方法是干脆让可持久化滚开,然后线段树套线段树。

问题是空间变成了 nlog^2。

sol:

根号平衡时间换空间

内层线段树换set+ dij 性质

最开始看成了每一个点只会被扩展到一次,看了半天不懂

为了节省空间,我们使用 set,但问题是连边数量并没有减少,甚至我们连不出边了。

一种 naive 的 set 模拟 dij 的算法是:优先队列里面存 (dis[v], v) 表示每一个点,然后取出最小的 dis[v],然后再线段树上从 set 中暴力取出所有,然后更新。

我们发现如果把每条边链接到具体的点上,那么会导致一个点被反复更新,反复从 set 中拿出点,是非常 sb 的。

聪明一点的模拟方式是在优先队列里面存储 (dis[v], e), 表示一条边(起点一个点,终点一个矩形),起点 dis。由于到一个点的最短路,一定是 到它所有入边的最短路中,最小的一个,所以你每次取最短路最小的边,那这条边的终点的最短路一定是到这条边的最短路的。

所以对于到底更新了哪些点的查询只会在最短路确定的时候发生,所以每个点被查询的时候是最短路确定的时候,所以如果我在每一个点被实际取出,被查询到的时候,把这个点从 set 里面删掉,那么这个操作显然只会发生一次。

所以时间复杂度就是 mlogm 的优先队列 + 每一个点删除一次 nlog^2n

这也可以非常直观地理解为什么平时 dij 的复杂度是 mlogm。通过这道题,应该对 dij 有了更充分的认识。

此思想的运用在本题中的另一种应用

CF1215F Radio Stations

前缀和优化建图秒了。

「SCOI2007」修车 && [HNOI2007]紧急疏散EVACUATE

高明的拆点技巧!+ 二分答案

拆点(加点)是网络流建模中必不可少的一个环节,一般的动机来自于:1. 将对点的限制/费用转化到边上(这个很常见);2. 表示更多的状态(比如 SCOI2007 修车中由于修车的顺序不同会导致费用的不同,所以将“一个人”拆成“修第几辆车的人”;HNOI2007 紧急疏散中由于每扇门每秒只能通过一个人,但一个点一条边只能限制“每扇门”和“一个人”,所以拆成“每秒”的门来限制时间)。

网络流中部分题目会与二分答案相结合:有的会用最大流根据最大流是否为总流量来判断(HNOI2007 紧急疏散);

10.11

感觉做题有点太快了,对前 10 天做的题目做了一个简单的复习。

受昨天晚上 zqm 启发,也想出题,然后看到了一个分治 DFN 获取子树信息的 trick,思考了半天找不到和 DSU on Tree 本质区别,GG。

好像是有的,于是造出了一道题。花了 几乎整个上午+晚上的小前缀 去修正做法、思考弱化版、造题面,很有意思的体验。虽然最后决定造弱化版题目(因为原版正解没有完全想出来/qd),但是很有趣。

上午下午状态不错,晚上有点困,效率比较低。

Problem:

给定一棵树,给定 a_{1\dots n}, C。每次给定 (u, v),保证 u 是 v 祖先,询问多少组 (x,y), \(x\in subtree(u)\backslash subtree(v), y \in subtree(v)\),使得 \(a_x + a_y = C\)

naive0:换根,求出向上向下。但是还是容斥不动。

naive1:分治 DFN 序+前缀和。

-> 凭啥前缀和。

naive2 : 分治 DFN 序,每一层分治开一个可持久化值域线段树,此部分 nlog^2n。对每条从根到叶子的链分块,设 ans[i][x] 表示点 x 的第 i 块中的祖先的贡献,ans 的求解复杂度 n * 块数 * log (每次询问点 x 在时间 [l,r] 的合法匹配,对 ans 执行一个区间加法,前缀和)。每次询问,剩下块长个点单独在线段树合并里面问一遍。

这是在线算法,如果允许离线的话,那么直接问就好了。

-> 每次分治 DFN 序,处理的是所有 L< mid, mid < R 的点,信息不一定到根!

naive2+: 最多有 log 个祖先的答案不在计算范围内?

对于一个点到某一个子树所有点的答案,可以先求到子树的根,然后一步一步下移,dlt 在之前分治过程中已经算出来了。

-> 剩下散块的点线段树合并里面怎么问啊?bitset。

弱化版1:a 随机。那么合法对数少,容易转化二维数点。

弱化版2.0: 树高 log,即形态随机。

naive:(from zqm)线段树合并。每一个点预处理去掉这个点的子树,父亲的线段树(先计算 pre,suf 常数小优)。

复杂度打问号。但是应该可过。

弱化版2.1: 树高 log 且值域小,线段树换成 bitset。

idea2:给树上的点分配颜色,称一个点的 pre 是深度最深,颜色相同的父亲。每次可以把一个子树搞成 -1,每过一时刻,如果 pre 是有颜色的,那么 -1 会变回原来颜色。q 次操作过后,问 -1 数量。

CF802C Heidi and Library (hard)

有趣的建模。

假装所有书都只买了一次,但是这个是不可以的,每一个时刻有容量限制。

而可以观察到,如果某两本相同的书选择买两次,那么会放松一段区间的容量限制。

发现了这种分配关系,这恰恰是网络流所擅长解决的。

问题转化为:一些有权值的区间,要求覆盖时间轴上每一个点至少 n - k 次。

建模:时间轴 (i,i+1,k,0) (s,firstpos,1,c) (lastpos,t,1,c) (prepos,nowpos,1,c)

ARC150 C

想了一会儿不会,看了题解的第一部转化:设 f(p) 表示路径 p 最多匹配到 b[i],那么原问题等价于 f(p)min = k。

naive: 考虑这个 min 怎么求,考虑新增加一个在 p 的后面,那么 f(p) 的变化是可以根据贪心策略容易求出的(fp 是最大匹配位置),那么就是一个最短路!

sol:最短路边权 01,使用 01 BFS/gz/gz/gz

反思:一定要会转化题目啊,这种要求所有的 xx 都满足条件,等价于极端情况满足条件。类似的转化是 CF1699E Three Days Grace(前几天的题目),当时也不会转化,现在也不会,属于是没长记性。

ARC150 D

理解了很久。

naive:题目等价于计算一个点被涂黑的次数期望之和。

sol:

计算被涂黑的次数期望只关注 u 到 1 的这条链。被确定的是一个前缀,只关心有多少个点没有被确定。

有结论:

Not only bad vertices but also good vertices can be chosen.

认为只关注没有被涂黑的数量(u 是否涂只和 u 的祖先的状态有关,涂了一个已经是黑的不会改变状态,涂了一个被固定的也不会改变状态,二者是等价的),所有把黑色再涂一遍的操作都和答案无关。

等价于计算把 n 个数都选择至少一遍,任意一个数被选择的期望次数。即每次随机⼀个 [1,n] 的整数,问期望⼏次能凑⻬所有数。答案是 ∑in/i。每次设已经抽出i−1个,要抽出没抽过的,成功概率(n−i+1)/n,期望次数为n/(n−i+1)。所以每一个数被选择的期望次数就是 \sum 1/i

10.12

下午有点困,决心减少乒乓球时间。

看了 [NOI 2011] NOI 嘉年华 ,没完全看懂,找时间补。

CF1342F Make It Ascending

看错题,开门红。以为如果想要 aj+=ai,需要满足 i < j

轻松地设出了一个 DP:f[i][s][v] 决策到 i,s 集合可以被选,ai 变成了 v,最小操作次数。(Trick:交换状态和答案)

轻松地发现知道 s 就可以知道操作次数,所以可以搞成 f[i][s] = v,决策到 i,可选集合 s,v 的最小值。最后只需要把所有合法状态取出来就可以了。分析一下,这样的复杂度是 n3^n。

以为过不了,思考了一下优化,发现没啥优化空间。然后发现这道题 7s。

开始写,发现问题了,s 里面存在两类数字,一类是必须被操作的,但是现在还不知道要操作给谁;一类是可操作可不操作的。这两类是需要区分的。

处理方式是反着做,f[i][s] = v,表示 v 的最大值,然后从 n 到 1 转移,此时,s 仅表示可操作可不操作的,必须被操作的已经被操作了。

复杂度是对的,写出来甩了几个小样例,按照我的题意是没有锅的,然后发现读错题了,寄。

然后重新设了一个状态,设对了,写出来了。

因为是 spj,然后手模样例摸错了,导致以为自己的代码是错的,然后虚空调试了 1h/jk/jk/jk

我果然是天使。

CF1152F2 Neko Rules the Catniverse (Large Version)

神仙题。

naive 地,有 f[i][s][v] 表示放了 i 个,ai=v,值域剩下 s。不仅蠢,而且没有优化空间。

思考这个过程,发现主要矛盾是 s 太大了,而如果按照 i 来 DP,那么必然面对 val 上蹿下跳的情况,而且并没有充分地使用 m 很小这一个性质。

换一个角度考虑,按值域顺序从小到大 DP

这样的好处是,显然不会重复。需要记录当前考虑了值域 \([1, i)\),填写了 \(j\) 个数字,还需要记录值 i 可以填在那些已经填写过的数字后面。

值 i 可以填写在 >= i - m 的数字后面,所以我们需要记录 大小为 2^m 的状态 s 表示 i-1,i-2,...,i-m 是否使用。

如果当前选:\(f_{i, j, s} \times (ppc(s) + 1) \to f_{i + 1, j + 1, (2 * s + 1) \bmod {2^m}\),ppc + 1 表示序列首位是可以选的,序列首显然是没有限制的;2s+1 表示 (i+1)-1 被选了。

如果当前不选: \(f_{i, j, s} \to f_{i + 1, j, (2 * s) \bmod{2^m}\)

容易发现上述过程唯一对应了一个序列。

i 比较大,那么矩阵加速,注意 f_i 的意义是考虑值域 \([1,i)\)

CF739E Gosha is hunting

md,wqs 二分好题。

首先 fijk 表示 i 个使用 j 个 A,k 个 B 最大值。

发现如果 固定 ij, B 是凸的,具体来说,其相当于一个关于 k 的函数,而这个函数是一个凸函数,因为第一个 B 类球一定会抓期望最大的精灵,第二个则抓次大……以此类推,容易发现这
个函数增长的速度会越来越慢。

有了 n^2logn 做法。

同理,A 也是凸的(震惊我一百年),所以可以 wqs 二分套 wqs 二分。nlog^2n 做法。

bugs:wqs 二分如若执行次数过多,反而会出问题,大概是精度遭不住。

另外一种非常优秀的做法:固定 ij,wqs 二分 B。求出每一个球用 B 和不用 B 的差量,sort 即可。

panyf

[PA2014]Druzyny

神仙题。

看似是 DP 题,实际上是 DS 题。

多维偏序问题可以使用 CDQ。也可以 启发式分裂

CDQ 可以 暴力分类讨论 + DS 或者 高明的做法

10.13

上午有点旷,下午后半段状态不错。

NOI2011 嘉年华

很 nb 的 dp 题。

写了很久,被 n 多细节卡了,感觉人有点旷。

时刻注意题目中给的时间区间是开区间!!!

离散化时间。首先要想到需要算出 pre[i][j] 表示前 i 秒 j 个活动在场地 A,场地 B 最多能选多少个。

pre 的计算需要 tot[l][r] 表示时间 [l,r] 完全包含多少区间。

注意,某些 pre 可能是不合法的,标为 -inf

同理计算出 suf。设 f[l,r] 表示强制选择 [l,r] 的答案:

\[f_{l,r} = \max_x\max_y\min\{x+y+tot[l][r], pre[l][x] + suf[r][y]\} \]

注意到随着 x 增加,y 不降,这样是不劣的,所以双指针就是 n^3。

注意 f 并没有处理到类似 [L,R],L< l,l < R < r 的活动,所以 ans[l][r] = max(f[L<=l][R>=r])

[AHOI2017/HNOI2017]大佬

诈骗题。

naive:显然怼人和保命无关。

怼人的次数可以 DP 求出,要想打出 x 的伤害,对 x 做唯一分解,那么花费是 f(x)=\sumc max(p) + 1,可以附加一段 -1 和,设 g(x) 是打 x 的最小次数,那么 g(x) = f(i <= x) + x - i

然后发现 g(x) 并不好求,而且就算是 f,做唯一分解的复杂度也是错的。

sol:

先考虑求 f(x),可以上 BFS 并加入两个剪枝: f > maxc || d > limit 就离开,状态数可以接受。limit 表示可以攻击的次数。

然后考虑求出的二元组 (f,d) 表示伤害和需要次数,需要判断是否存在 f1+f2 <= c, f1+f2-d1-d2+limit >=c。这个可以按 f1 排序然后双指针,f1 逐渐变大,f2 变小,算 max{f2-d2}。

反思一下,这个双指针写了半天没想清楚。其实本质就是找到某种指针移动方式,使得所有曾经贡献 mx 的 f2 现在也能够贡献。

CF1188D Make Equal

最终是所有数字都变成 max + delta,即让 \sum ppc(max+delta-ai) 最小化。

令 ai -> max - ai, 则让 \sum ppc(delta+ai) 最小化。

考虑 DP,发现需要记录哪些 delta + ai 在上一位发生进位。

妙点:假设当前处于二进制第 k 位,在第 k - 1 位发生进位的点,必然是把 a 按照前 k - 1 位的大小排序的一个前缀。

所以,设状态 f[i][j] 表示当前处理了二进制前 i - 1 位,对 i 位的前 j 个数产生进位。

考虑转移有两种思考角度,一种是枚举 delta + ai 这一位是啥,一种是枚举 delta 这一位是啥。然后你会发现这两种分析出来的转移是恰好相反的。推了好久没看懂为什么反了,原来是枚举的东西不一样。而实际上 delta+ai 是不能枚举的,因为 delta + “an” 是一样的,现在的 ai 已经变质了。

这种按照二进制位枚举,而后状态里面和二进制位进位有关的题目还有(考场上不会做的):NOIP2021T2数列

JOISC 2020 Day4 治疗计划

反思一下,感觉做这道题的时候思考太少了,一来感觉非常难做,看到是黑的然后就直接看题解了。

一个愚蠢的优化建图是开两颗可持久化值域线段树,然后按照时间 t 依次往里面插入 l_i + t_i 或 l_i - t_i,每次提取前缀区间里面的数,并把这个区间删除(rt = 0)。

这样的问题在于,因为删除,所以不能是 insert 的时候,每一个 rt 都要 clone,这样会导致删不干净。

但是由于可能多个值相同,所以每一个叶子节点实际上应该甩一个 vector,但是上面的可持久化方式导致一个尴尬的问题,即可能误删(时间大小不对)。只能是每一个叶子节点,扔一个数据结构维护,这样复杂度还是对的,因为这个并不是树套树,但是常数很丑,而且很不优雅。

优雅的优化建图是开两颗可持久化下标线段树。线段树上维护最小值,每次询问暴力找就行,因为最小值保证了能够找到,均摊就是 nlogn。


神仙题!神仙建模转化/考虑 DP 现实意义。JOISC + 建模,DNA 动了。

最后形成的可行方案可以看作是一条条线段覆盖了整个区间,那么把这些线段按照左端点考虑,可以理解为是覆盖 [1, a] -> 覆盖 [1, b > a] -> 覆盖 [1, c > b] -> [1, n]。即把方案放在 村民-时间 二维图上。只不过,两条线段能够完成这种配合需要满足一个和 t 有关的关系。

那么,如果把这些关系连成边,那么就是一个 dij 的事情。DS 优化建图即可。

实际上,这样的思考角度排除了时间的恼人限制。

CF1463F Max Correct Set

naive:

有点 Division into Two 的感觉,但是只是感觉。

下意识想要容斥,想了一会儿,突然想起来这道题不是求方案数的题/qd

如果只有一个限制,那么是简单的,可以看作 x - 1 条互不相关的链。y 的作用可以理解为把一些链链接了起来(无端联想:肽链之间的二硫键/jk/jk)

暴力 DP 可以爆设 f[s] 表示 s 可选。

sol:

啊啊啊,啊啊啊,同一个坑跳了两次了!!昨天才做的 CF1152F2 Neko Rules the Catniverse (Large Version) 也是这种挑选数字,然后数字之间有值域限制的题目。

这种问题的解法是从小到大考虑每一个值,可以干掉互不相同的限制,然后可以证明选出来的数字唯一对应一个原方案之类。

对于值域的限制,常见的优化方法是只关注 >= i - \(\epsilon\) 的数字。

所以设 fi,j 表示考虑了 [1, i],选取情况为 j 的最优解 -> 第二维的选取情况我们也只用记录到下限位置,每次更新的时候移除超过下限的数,再加入 i 本身的选取即可。

复杂度 \(\mathcal{O}(2^{max\{x,y\}}n)\)

进一步优化:

ttd 的 ppt :
首先,设 p = x + y,若我在一段长为 p 的值域中选出了 k 个数的合法集合 {a1, a2,…, ak},我可以通过给这个集合的每个元素加 p,将答案扩展到整个值域。考虑反证,显然,集合 {a1, a2,…, ak} 与集合 {a1 + p, a2 + p, a3 + p} 内部不可能存在不合法的情况,我们可以不失一般性的假设 ai + p − aj = x(y),通过移项后有 ai − aj = x(y) − p,则有 |ai − aj| = x(y),与前提矛盾,即得证。
接下来,设 r = n mod p,t = ⌊n/p⌋,将区间化为形如 r, p − r,r, p − r……r 的 2t + 1 段区间。设 Ai 为我们在第 i 段区间中选取数的个数,显然,我们可以选择两段连续的区间形如 Ai, Ai+1(i ≤ 2t),将整个选取方案用这两段区间的选取方案覆盖。设:\(S_o =∑_{i∈odd} Ai, S_e =∑_{i∈even} Ai, B_{2i−1} = (t+1)A_{2i−1}−S_o, B_{2i} = tA_{2i}−Se\)
上述 B2i−1 即用 A2i−1 覆盖所有奇数段的贡献,B2i 即用 A2i 覆盖所有偶数段的贡献。那么如果对于任何选取方案,都存在 Bi + Bi+1 ≥ 0,则我们能够证明最终的答案存在 p 的循环节。同样考虑反证,根据 B 的定义,有标为奇数的 B 和下标为偶数的 B的和都为 0。则根据 B2 + B3 < 0, B4 + B5 < 0,…, B2t + B2t+1 < 0,有 B1 > 0。根据 B1 + B2 < 0, B4 + B5 < 0,…, B2t + B2t+1 < 0,有 B3 > 0。以此类推,有所有下标为奇数的 B 都大于 0,其和自然不可能为 0,故矛盾。

因此,我们只用求出第 1 段的答案即可。

10.14

今天是构造专场,然后 T1 一来就不会做

CF1734E Rectangular Congruence

naive:

首先感觉一下,能不能关于中心点对称填写,这样只需要保证矩形组成不同即可。但是不行。

把 x+y = i (mod n) 的 (x,y) 看成一组,题目转化成同一组的数不能作为任意一个矩形的对角。Bi 相当于定死了一些。算一算同组 (x,y) 的对数,发现大概是有解的,但是给不出方案。

sol:

题目意思是,一个矩形,左上角-左下角!=右上角-右下角。(此时行坐标相同)

aij = i\times j。为了符合 bi,把 i 行整体不断+1。

反思:题目条件转化太垃圾。

[Baekjoon 8121]Step Traversing a Tree

很好想,随便画一棵树手模一下就知道了。大致长成两个函数相互递归。

[ZOJ 3823]Excavator Contest

naive:只会 n 为偶数,弯弯绕绕即可。

sol:

给出 n + 1 次不转弯的机会。考虑缩小问题规模:找到某种缩小规模的方式,使得 n 每减小 1,花费 1 的不转弯代价。

非常妙的思想啊。每次可以 n->n-2,注意最后出口在边界。

[AGC030C]Coloring Torus

naive:k<= 500 简单。

考虑 k = 1000, 发现可以把 k = 500 的每行改成两种颜色交错。但是奇数怎么办呢。

sol:对角线颜色交错。

[ARC107E]Mex Mat

想出来了,打打表,发现只需要处理前 4 行 4 列,后面不会变。

理性证明:

101 会让 0 延续。考虑 01212120 这种段,发现会变成 010 或者 0120,再来一轮,就会发现不变。

[ARC106E] Medals

因为胡乱理解 FWT 被卡了 2h/ll

naive:二分一个答案然后考虑贪心,但是发现没有办法贪心,因为涉及到分配问题。

sol:分配问题考虑网络流,这里表现为二分图最大匹配问题,相当于 n * k 个奖牌往时刻连边。使用 Hall 定理。发现可以视为 n 类奖牌,因为取了一个,把一类都取了显然更有助于 Hall 定理的判断(连边相同)。

可以预处理 g[i]=s 表示时刻 i 能够发给 s 集合奖牌。设 f[s] 表示 s 集合连向多少个点。

naive:

for(int i = 1; i <= lim; ++ i) ++ f[g[i]];
for(int i = 0; i < (1 << n); ++ i)
    for(int j = 0; j < n; ++ j) 
        if(! ((i >> j) & 1))
            f[i | (1 << j)] += f[i];

right: FWT

很显然, naive 中的代码是算重了的,用于更新 f[i] 的 f[s_1] 和 f[s_2] 可能 s1 和 s2 有交。

对 FWT 有了新的理解!

[ARC084C] Finite Encyclopedia of Integer Sequences

upd 10.17:补了。

k 是偶数,那么 k/2,k,k,\dots,k 就好

k 是奇数,那么对于一个 a[] 而言,ai = k + 1 - ai 与之一一对应。唯一不对应的是 (k + 1) / 2 开头的 n 个,移动移动即可。

[ARC110F]Esoswap

大致懂了,找时间补。

10.15 模拟赛

最开始 2h30min 鼻子不爽,连带着头脑也不是很清醒,都在做 T1。

T1 题面一直在改,不知道在干啥。

T1 性质想对了但没有用好,细节考虑错了;T2 当时有网络流的感觉但是没有建出图,尝试写了一个高斯消元发现不是很靠谱;T3 想到了区间 DP,但是面对 |s| > 1 束手无策,墨守状态;T4 骗分。

反思:

感觉 T1 虽然想到了性质,但是没有把这个性质用到关键点,而仅仅是让这个性质作为爆搜的一个剪枝,非常蠢笨。而且想错了 a = b 时候的解法,犯的错误和在 [AHOI2017/HNOI2017]大佬 中犯的错误如出一辙,直接认为答案是 \sum c。

T2 看到构造有点心慌。对于这种网格图,一个可能比较通用的构造思想是先满足一部分性质(比如行的性质),然后调整列。这个网络流建模比较像 放车(?)的建模,不够熟悉。

T3 想到 DP 后就心满意足了,但是一方面确实时间不够了,打一个部分分可以走了。

下午懂了,找时间写。

晚上 ABC,因为擅长 STL 导致只能使用 Vector,映射关系搞得非常复杂,导致 D 题写了 40min,GG。

强行加离散化的出题人都是 ** 出题人。

值得欣慰的是,可以感到最近代码能力有所上升,比如 ABC 的 D 一遍过,犯的唯一错误是读入字符串。

10.16 模拟赛

状态不错。感觉房间里面比较热,出去吹了吹风。

T1 垃圾题。

T2 题目描述不甚清楚(非整数位置能不能刷),导致我的 DP 写错一个细节(思路是对的)。但是更大的错漏在于写错了内外层循环的顺序,这个问题上次发生是在 10.13 的 [ARC106E] Medals 对 FWT 的错误理解。说明其实对这个解法的理解是不充分的。

T3 简单题。

T4 不会,打了一个暴力求出题人数据水但是数据并没有那么水。

T4 是好题!!!

总体来说,还行。晚上主要是在找 T2 代码问题 + 补了 1015T1 + 通过视频学习 T3 std 做法 + 通过文字题解和小部分视频理解了 T4 + 打了一点 T4。(时间被 PYB 关于 ban qq 占据了一部分)

感觉欠账突然有点多了。。。

10.17

上午都在写昨天 T4,但是我的做法 G 了,一直修修补补但是 0 产出。

下午看懂了 std 总算是写出了 T4,前前后后花了 7h+。觉得这样的体验不错,上午状态不错。

感觉失去了 QQ 之后,整个人都不好了,感觉下午失去了做题的动力,只想 copy。

感觉整个人都不好了,晚上也没有啥做题的动力。破防了,md。

可能是因为昨天 T4,精力消耗过大,中午虽然睡了觉,但是下午还是比较困,基本上是强迫自己兴奋起来,但是这种强迫已经发生了很多次了,虽然通常都是先趴一会儿,然后起来洗帕脸————有点厌倦和讨厌这种强迫了。

感到压力很大,在诘难自己是否因为刚刚出了一点成绩就开始骄傲,不然你凭啥划水呢;是否失去了一些对 OI 的兴趣,不然你为啥贺题呢。

不知道,可能只是有点累了。压力。

看了会儿风景,觉得好多了,回来做了 1015T3。

晚上回家摆了一会儿,觉得好多了/fendou

10.18 模拟赛

今天纯纯暴力场,全程基本都在打部分分,没咋想正解,体验不是很好。统计了一下,发现这场交了差不多 16kb 的代码上去。。。(码力之王!)

T1 打得有点急,一眼双指针,但是写得很假,搞成了 m 个指针,复杂度错了。然后分析了一下,由于受到了之前一道模拟赛 T4 的影响,分析复杂了,憨憨地上了一个吉司机,写完发现完全没有必要。最后上了一个 n^2mlogm 的 sb 做法。1h。

T2 感到暴力分很多,然后一直在打暴力,然后造数据拍。大概花了 1h 把所有暴力打完,给了 30min 想正解。超了 10min 想到了正解莫反,但是没有想到迪利克雷后缀和,所以复杂度是 n log n,但是问题不大。但是只剩下了 1h20min 了,后面两道题都是白的,T2 正解有斜挂的风险,于是选择先打后面的暴力。

T3 打完暴力,发现还有 20 分暴力扫描线+线段树。可惜忘记 *C,亏了 10pts。

T4 最开始没有理解题意,做了一会儿阅读理解,写了暴力,没看到后面还有 10pts 的动态开点 BIT,亏。

最后剩下 10min,开冲 T2,没冲完,GG。

很可惜,感觉如果再给我 5min 就可以冲完,所以说 T1 写太久了。

下午卡了卡 T1 的常数,最后换了写法;T2 把后缀和写成了前缀和;大致听懂了 T34。

下午小困,问题不大。去看了 zqm 新出的题。

晚上开冲 T3,有点南充。发生了和 zqm 一同不会求单调栈的糗大(没看出来就是一个单调栈),然后单调栈改完就过了/jk/jk/jk

剩下的时间回味了一下 20221015T4 公交,并试图用里面的 Trick 造一道题,但是失败了。

T4 思路大致懂了,以后再补。

10.19 贪心

上午看题的时候顺便复习了一下 ABC250Ex,觉得还是挺好的题。

中途有点不想贪心了,然后去补了补昨天晚上出题的想法,不断修改,虽然最后得到的题目并没有很好地体现 公交 的 Trick,甚至还非常简单。

不甘心,然后疯狂修改贡献方式,探索还原 原题的思想,但是最后搞出来的东西自己做不了,G。

CF976E Well played!

简单贪心,秒了。代码注意一个细节:在枚举把 A 操作给非前 b 大的时候,可能会占掉前 b 大一个 B 操作的名额。

CF1384B2 Koa and the Beach (Hard Version)

转化到 时间-位置 二维图上看,容易得到贪心结论。

CF865D Buy Low Sell High/ atcoder abc250G

经典反悔贪心。

CF912D Fishes

小转化之后,考虑每一条鱼的被覆盖次数越多越好。放在中间肯定是最优的,像四周扩展尝试,优先队列算一算即可。

CF1396C Monster Invaders

naive:如果我被弹出去了,那么肯定是要两关一起做更优。(想到这里比较高兴,没有往后面想)

sol:按照上述思想列 DP。

细节:

  1. 可能当前这关想要用 AWP 秒掉实在代价太大,也可以跳过去但是不打人。
  2. 可能在 n - 1 结束

CF1251E2 Voting (Hard Version)

原题:[CCO2017]Professional Network

CF196D The Next Good String

看样例会正解。这道题代码的 hash 非常巧妙。

CF802O April Fools' Problem (hard)

对 wqs 二分和 CF865D Buy Low Sell High/ atcoder abc250G 有了更深的理解。

首先我会费用流做法,然后就没有然后了。

一种 nb 的做法是线段树模拟费用流,但是不会。

注意到 费用流的本质是反悔贪心, 而且费用流具有凸函数性质,那么可以 wqs 二分。

wqs 二分:

  • 目标求 \sum a+ \sum b 最小值,那么每次二分一个 mid,让配对贡献变成 a+b-mid,只配对 a+b-mid 为负数的对,每次反悔将一个大 b 换成小 b。所以 priority_queue 做小根堆,里面甩 a-mid 和 -b。此时,这个 mid 并没有实际的意义,他的作用在于控制最后选择的个数,只需要保证在个数正确的时候,对应的方案就是一个正确的方案就可以了,这是 wqs 二分的本质,其实并不是很关心 mid 到底是什么东西。
  • 转化成 CF865D Buy Low Sell High 来做,给出了 mid 的具体意义:NusGhy

10.20 模拟赛

感觉今天打得不是很自信,状态不是很理想。

最开始突然流鼻血/qd,耽搁了一段时间。

8:30 把所有题看完,感到有点绝望的意味,因为看起来今天的题都不怎么可做。

10:00 拍完 T1。

然后后面 T2 性质没有探索观察出来,T3 只会暴力,T4 的 n^2+q 做法没想到,特殊性质分感觉很可做但是没有细想(当时想的是预处理后缀最大值,但其实这样做是错误的,因为可能随着区间的变小,后缀最大值的位置可能不优)。

这场比赛打得很奇怪,中途对 T3 有点 DP 的感觉但是却没有细想,T1 也很 DP 但是也没细想,感觉这场状态有点小奇怪。

然后 T1 应该是乘逆元但是直接 /2 + subtask 的分类没写好导致 T 亏了 30pts 并调了一个下午。

T2 YES 搞成小写亏了 4pts

T4 调试行没关亏了 20pts


T2 是很巧妙的性质观察题,对于题目操作中的不变量的观察非常独到。

T3 用到了原根把乘法转化为加法,新技巧。正解没看懂。

T4 花了很久看懂了正解,优雅的笛卡尔树+申必李超线段树。T4 当时一直在往启发式分治这方面想,实际上把启发分治的节点提出来就是笛卡尔树。没有写完。

继续努力。

10.21 模拟赛

时间分配:

1h 拍完 T1
1h 发现 T2 算错复杂度,卡了错误的常数(
20min 想到 T2 拉格朗日插值
5min 放弃 T3
10min 想到 T4 序列自动机并亲手叉掉
35min 尝试优化建图
10min 打脸自己。
20min 发现 T2 好像插不动。。。
补 T3 暴力,检查代码

T1 顺利切掉;T2 太执着于 DP 优化了,但是常数太大怎么都卡不过 70pts,没有真正把问题抽象出来,实际上是一道组合计数的题目,对于容斥/二项式反演有了更深刻的了解;T3 是神 DP,通过精简状态(规定转移方式) 来避免算重;T4 想到了序列自动机,但是复杂度分析错了,naive 地认为简单的序列自动机可过。。。。题解讲授了一种 DAG 链剖分,一种观察得到答案串连续段长的特点进行倍增(ababa... 的字典序指数级变大)。

下午后半段有点小困,晚上稍微睡了一会儿。今日划水时间略长

然后发现明天 DP 的 T1 是在 HL 打的 ABC 的 G,而且刚好是当时的待办列表里面的题。一道细节充足但是思路清晰的 DP 题。

去了解了一下 DAG 链剖分。

10.22

感觉今天上午想题的时候不是非常专注,比如做 Cigar Box 的时候,实际上并没有去仔细分析题目性质,而是预先假定了这个是 ARCE,我做不出来所以摆烂,坐在那里实际上并没有思考。大概是水鬼附体了(

反思一下以前做题有没有这种情况,肯定是存在的,说明我并没有我想象的那样努力,杂念太多了。

ARC112E Cigar Box

性质分析好题,一定要善于抓住不变量

观察没有被操作的数,这些数作为原排列的一个子序列和 al...r 相对应。对于操作的数,其进行有意义的操作的时刻(顺序)是固定的。

所以这个问题瞬间好做了很多,只需要决定什么时候“浪费”操作次数就好了。

设 f[i][l][r] 表示进行 i 个操作,l 个有用左操作,r 个。

精简一下,可以搞成 f[i][l+r] \times binom(l+r,l) = f[i][l][r],优雅的。

[JOISC 2015 Day1]有趣的家庭菜园2

naive:首先答案肯定是两个单调序列拼起来。

然后 yy 一下,感觉只需要转移 h 相同的和 h 比他大一点点的位置。

那么可以用线段树计算贡献。

小技巧:nlogn 找到所有 (x_i, y_i), xx > x 且 yy > y 的第一个点:n 到 1 扫描,树状数组维护后缀 min。每次 add(y, x), 查询 ask(y) 之类。

sol:

显然每次只往后面更新一个是非常不正确的。

于是使用了一个比较优雅的 DS 优化建图。

模拟赛

这把最开始状态不是很好,因为是 13:00 开始,所以有点困。

T1 把 n, m 数据范围看反了,然后莫名其妙的自信建上下界网络流图,然后开始根据残存的记忆现场推导有源汇上下界可行流,居然推对了,但是然并卵。

此时已经过去了 1h,心态有点小炸,接杯水回来写了一个暴力,然后开始想 DP 优化。发现这个 DP 很 [NOI]弹跳,显然是可以用最短路优化的,这里可以写 BFS。

问题是没有保证每一个点只被访问一次,因为这里需要取出的是 包含 s 集合且 sum(s)< w 。这个最开始尝试了一下线段树,发现这个势能实际上是优化不动的。

然后蒙蔽了,心态有点不对了。

去 T2,建图上头了,对着 T2 开始建图,发现不会,先写了一个暴力 DP。观察了一下,发现这个 DP 可以 DS 优化。一遍过。

T3 有点奇怪,回到 T1。

此时心态基本平复,细细思考,开始 SOHA,即把用线段树找变成 dfs 找包含 s 的集合,直到不能再扩大集合,此时 q.push。同时加记忆化。现在算算复杂度,感觉应该是对的。

T3 写了暴力,然后想到了线性基,但是后面的贪心写错了。

T4 摆了,懒得写暴力了。

只能说是不够沉稳。

后面发现 T1 正解 DP 设的状态和考场上第一个尝试的状态是差不多的,我设的是 f[i][j] 表示前面一共剩下 j。。。可惜了。

ABC274

这场打的时候家里面格外嘈杂/qd

ABCDE 都比较简单,难点在于读懂题面。其中 E 空间开小了,但是为什么是 WA 而不是 RE(

F 想歪了,我的思考是有用的时刻点肯定是在两条鱼可以同时抓住的时候,这样的时刻只有 \(O(n^2)\) 个,那么现在只需要找到 O(1) 算贡献的方法就可以了。

发现好像 O(1) 算有点难,然后有点小懵逼,跳了,决定 soha G,因为 G 很网络流,但是没写完(想错了一个细节导致代码实现变得复杂),GG。

10.23 CF

感觉今天做题的心态很差,不够沉稳,理想的心态应该是不骄不躁,但是我给自己设定的预期太高了,同时开场之前还处于一个打摆的状态(

A 想得很快,被细节卡了;B 想得很快,多测不清空;C 最开始想歪了,但是 #define int long long, printf("%d")。

没想到 CF 卡这么严格,平时都觉得无所谓的。

这场比赛是一个警钟。实力在的,但是别急。

去订正了 ABC274 FG

10.24 模拟赛

想不到任何不打开 QQ 的理由。信誓旦旦,不思其反。

时间分配:

8:15 想出 T1 最长子序列做法
8:30 发现 T1 可以排序。。。。。
8:50 T2 乱搞贪心做法被叉
9:00 T2 暴力
9:20 T2 基于个数的贪心不会,网络流难以优化
9:40 DP 做法被叉
10:00 鞭尸 DP
10:30 放弃 T2
11:00 T3 暴力
11:11 开敲 T3 “正解”

今天被 T2 打爆了,可以很清晰地感到 T2 应该是一道简单题,但是不会。

T1 最开始以为不可以排序,然后思考出了加强版的做法(

感觉 T2 就很贪心,最开始的想法是尽量匹配 BC,然后剩下的交给 AB, AC。但是这样的问题是可能 A 比较多,然后 BC 会消耗掉 AB AC,很亏。

把部分分打了,思考出了一个基于 A, B, C,数量多少的贪心,即考虑先考虑数量比较少的怎么匹配,但是不会。

显然有网络流做法,但是不是二分图。

想到可以视作括号匹配,设 f[i][j] 表示前 i 个,剩下 j 个左括号没有匹配是否可行。容易发现可行的是一个 f[i][l...r] 区间,所以只需要维护 l,r。

但是这样的问题是会匹配出 BB 这种东西,G。

如果多记一维 k 表示有 k 个是左 B,那么此时转移变得难蚌,复杂度炸了。

考虑贪心优化这个 DP 过程,发现不会,鞭尸。

时间不多了,去后面看了一眼 T34,感觉 T3 也是可做题。

回来再次确认了 T2 的死亡,放弃 T2。

打完 T3 暴力发现不会了,然后考虑建图准备跑01-bfs,然后上了一个线段树优化。但是这样的问题是难以限定 n 个必经点,如果强行限定,那么状态数炸了。

T4 没时间了。


反思一下,心态问题仍然存在,可能是对自己实力的认知不足,可能是做题方法不太优秀。比如,T2 的一个重要问题就是虽然观察到了所有都必须被匹配这一个性质,但是并没有很好地利用它,没有意识到 BC 的对数实际上是可以算出来的。

咕咕咕咕咕,呱!

20221022T3

当时想到了线性基,但是由于对线性基的理解不够导致后面的贪心没有写出来。

后面的贪心要注意的点在于由于线性基里面的数是有“尾巴”的,所以即使两个数这一位都是 1,那么也要讨论一下是否因为之前异或的值导致了反向。

留下的一个问题是,为什么 n <= 10 的时候有一个点用正解跑跑不过?反复测试,确认数据的确是没有问题,但是解法思考之后是正确的?

复习了一下线性基。

20221022T4

巧妙的 DP 转移!!

首先,正难则反。

考虑反着做然后找不降序列,设 f[i][j] 表示当前 i 有 j 个(没有向上合并)

每次加入 ai,首先 f[i + 1][a[i]] 有所动作。然后对 f[0...n][>a[i]] 进行刷新操作。

这样的妙处在于,在之后加入 aj > ai 的时候,进行的第一类转移实际上和之前刷新上来的值进行了合并,实际上和 ai 组合在一起形成了一个序列。也就是说,DP 进行转移的时候并没有选择下一个数是什么,只需要保证下一个数进行转移的时候能够拿到正确的值就好。

一个担忧是会不会出现 j < i, aj > ai,然后 ai 刷表刷给了 f[a[j]][...]。但是实际上问题不大,因为这里并没有枚举下一位选择什么,所以实际上做的是替换而不是合并成一个序列。

CF830div2D2

勇敢暴力题。

记录一下删去 x 可能会导致那些数字的答案变小,每一个数字搞一个 set 叫做 del 存一下那些可能成为新答案。

分析一下 del 的大小,发现不会很大,因为 q 很小。如果 x 在 del[y] 里面,那么意味着 y, y + y, y + 2y...x - y 这 x/y 个数字都在。如果 y 不是 x 的较大因子,那么这个数将会非常大;如果是的话,那么总复杂度不会太大。

10.25

我误以为这又只是在梦境上演的须臾

上午被跌宕起伏的情节,单纯炽烈的情感所捕获了,掉进了小说的圈套。

上午稍微看看题,补了 CF1463F Max Correct Set 的代码,下午听课感觉前面还好,后面有点懵。

CF1601D Difficult Mountain

naive:

考虑这样一个 DP:设 f[i][j] = p 表示爬上 j 个人之后的最小难度。观察一下,发现每次转移形如前缀 max,区间整体加 1 之类,分类讨论一下应该是可以做的。

sol:

按照 max(s, a) 排序,容易发现这样肯定是不劣的。

[HDU7216]Triangle Game

naive:想错了,但是歪打正着。想成了对面积进行操作,然后猜对了结论。

sol:(a-1)(b-1)(c-1) = 0 为必败态,容易发现一个必败态必然合法,而必胜态必然可以走到一个必败态,也是合法的。

[HDU7241]Simple Math 4

比较高妙的 DP。

对于一组合法的 A,如果存在 i != j 使得 Ai, Aj < R 且 Ai 与 Aj 二进制下末尾极长 1 连续段长度相等,就可以给它们同时加一,这样在不改变异或和的同时增大了和,更优。那么有抽屉原理,最优的 A 一定满足至多 O(log R) 个元素 < R。

dp:设 fi,j,k 表示已经填完了前 i 位,有 j 个元素前 i 位与 L 相同,k 个元素前 i 位与 R 相同,异或和的前 i 位与 X 相同,此时的最大可能和。状态数 O(log3 R),转移 O(log R)。

注意这里的转移比较细节,如若 n > log,那么令 n = log,多余的部分直接构造成为 R。那么,在转移的时候,直接认为是在对于顶住 L/R 的数字进行操作,以表现连续段长度不同。

[HDU7247]Average Replacement

数学题,容易发现总和 \sum a_i(deg_i+1) 固定,且同意连通块内最后长得一样。

稍微模拟一下这个过程,可以认为是在每条边上互通有无,可以感性理解每一个点的答案是 \suma_i(degi+1)/ \sum(deg_i+1)

一个坑点是 G++ 和 C++ 的编译方式不同,G++ 会被我的逗号换行搞蒙蔽(恼

    a += b + 1, 
    c += d + 1;

10.26 模拟赛

打摆的一天,属于是赛前摆烂了。

T1 思考方向:

  1. 写出 BF 式子,发现与 S 有关,有 n2^n 算法
  2. 计算 >= x 的概率但是发现和 1 本质相同。
  3. 受 a=1 部分分启发,思考 E 之间是否存在某种比例关系。发现 E 总已知。猜测 EI:EJ=AI:AJ,猜测 ei:ej=aj:ai 均不对。在暴力 DP 的式子基础上尝试了推出比例关系发现不是很推得出来(有时间再推推

9:40 放弃 T1

T2 思考方向:

  1. 二分之后暴力判断
  2. 发现随着 x 的变化 cnt 变化奇怪
  3. 发现随着 lim 变化,x 变化奇怪
  4. 猜测让总和最小的 x 就是最好的,但是 G
  5. 思考某些位置是否有固定策略
  6. 感觉数据范围很根号,思考能不能把询问用莫队给他日了。c,要求在线,不太行。
  7. 感觉数据范围把暴力复杂度砍一点点就能过。
  8. 考虑优化 f(x, lim) = cnt,,转化成 f(x, cnt) = min(lim)。得到一个垃圾根号做法,但是不是很敢 soha。

10:50 放弃 T2。

11:20 打完 T3 暴力(wssb)

11: 23 T4 暴力

11:50 soha 完 T2 “正解”,发现 T2“正解”复杂度分析错了。

感觉这场考试题奇奇怪怪的,T1 期望题只能说技不如人,以后面对期望题一定要注意线性性的思考。T234 居然都可以随机过题,而且考题方向奇奇怪怪。。。

UOJ47 【清华集训 2014】文学

注意到若干个半平面的并的补是一个凸集,也就是说对于所有横坐标为 x 的点,至多只用两个“有效”的半平面取覆盖它们。

也就是用一条平行于 y 轴的直线砍这个凸包,我们只需要关注被砍到的这两条边。这个是凸包的一个重要性质,即最多砍到两条边。

设 f_k[i][j] 表示上下直线 i, j, 囊括了前 k 个点(对点按 x 排序做转移)

T1

E(1被选中的时刻)=E(在1之前被选中的数量)+1

T3

奇妙构造,主要思想是递归成为子问题,感觉和前几天拖拉机那道题的思想类似。

T4

在那一天,人类又想起了被 FWT 统治的恐惧。

10.27

[LOJ3776]「BalticOI 2022 Day1」Uplifting Excursion

被卡常了好一会儿,发现开 O2 就过了/lh

奇妙的性质观察题,经验是:

  1. 遇到这种看似“经典”的题,正解不一定是经典的,要把思维打开,不能太局限。
  2. 有些时候,无法贪心就要考虑 dp,而无法 dp 也许要考虑贪心。
  3. 尝试将题目弱化一下,或许能够有利于走向正解。

本题的精髓——先贪心构造出一组不超过/不小于的解,接着发现不需要做过多的调整,从而问题"变小",就可以通过 dp 及其他技巧将其调整为一组最优的合法解了。感觉这个思想很值得推广应用。

关于调整很少的证明:

首先我们考虑取所有数字,然后如果 > 想要的体积,那么贪心地从大到小删直到<=想要的体积。

剩下的部分考虑调整,注意此时已经有的体积在范围 [L - m, L],调整过程中不会让体积超出 [L-M,L+M]。考虑调整过程中如果出现两个相同的体积,那么显然可以忽略中间的调整过程,所以调整不超过 2m 体积,正负数的存在,调整价值(物品个数) <= 2m。

所以背包容量上界是 \(\mathcal O(m^2)\),使用单调队列可以优化到 \(\mathcal O(m^3)\)

[JOISC 2020 Day3]星座 3

naive:

由于这个是树上问题专题,所以我们考虑树。由于这个是奇奇怪怪的网格图而且与最大值有关,所以我们建立大根笛卡尔树。

容易列出 DP 方程,但是转移复杂度太高了。

sol:观察转移,发现只需要转移一个位置,所以复杂度不高。线段树合并维护即可。

具体

模拟赛

下午状态最开始并不是很好,有点困倦。做了一会儿好起来了。

/kun/shui/qd/hanx
2:27 T1
3:20 粗略 T2
3:40 不管 T2
3:50 上状态了。
4:30 容斥写完。
4:40 发现过不了 5 7 28
4:50 发现是暴力写错了/lh
5:00 走入 T4
5:20 感到 T2 很危,给 T2 想了一个 log-log^3 的 lj 做法也不敢打。
5:40 T4 “正解”
6:20 T4 果不其然地挂了。

attention!!!

  1. 造 T1 数据,写 T1 暴力
  2. 回防 T2,输出一下 SIZ, TOT 或写一个内存池

赛后发现 T2 被卡常,T3 模数写错了。。。

T4 方向是比较正确的,性质的分析比较到位,但是忽略了 必要条件和充要条件 的差异,没有把限制体现出来,GG。

10.28

今天上自习,复习了 Tarjan, Trie, AC, SA, SAM, 笛卡尔,高斯消元,KMP 并打了模板。

AGC041D Problem Scores

神仙转化!!

naive:显然第三个条件容易转化。

sol:

维护 \Delta = 前 k+1 个数之和 - 后 k 个数之和。

容易发现 Δ 初值为 n。

对于每一个 i 容易预处理出 w_i 表示对前缀 A[1…i] 进行一次操作时 Δ 会发生什么变化。显然无论对哪个前缀操作 \DeltaΔ 都会减少。

那么现在就转化为一个完全背包。

[SCOI] 喵星人的点名

把几种做法都学习了一下:

  1. 新技巧:可以在 SA 上二分出一个区间使得 sa[l..r] 开头的后缀包含某一个字符串 s。对于每一个询问串二分出来之后,变成区间数颜色,莫队即可。对于第二问,差分,在第一次加入这个颜色的时候 +剩余询问个数,退出的时候 -剩余询问个数。扫描线大法好!
  2. SAM,和 SA 差别不大,都是转化成莫队。
  3. AC 自动机。在 Fail 树上,若 A 是 B 的子孙,那么 B 是 A 的后缀。如果要判定 S 是否是 T 的字串,那么可以遍历 T 的所有前缀看 S 是不是前缀的后缀。所以对于第一问,可以枚举每一个名字串的前缀,然后覆盖到 Fail 树上根,覆盖多次算一次,每次询问单点询问。覆盖多次算一次,排序 dfn 序,减去相邻两个数的 lca 进行容斥。第二问差不多。

10.29 CSPS2022

写于 10.30 晚上,晚上主要是整理了一下心态,然后看了看其他选手的整活代码,开始一点一点写总结。

经过这次的考试,我确认了自己的实力确有充分的进步,但是还不够,还差一点,还差一点。

进考场的时候脑子状态不是很好,T1 最开始没想清楚,搞了一个 dp[1..4][j] 表示当前是第几个点,在哪里。然后发现不过样例,于是瞬间清醒过来了,感觉到开始升温,属于是上状态了。

然后稍微画了画图,打了一个 n^4 的暴力。想着要是 n^2 就好了,于是往 meet in the middle 这边靠。仔细分析了一下暴力做的是什么操作,解构解构,发现其中确有可以解耦的部分,解决。

进入 T2,打了一个暴力,优化一下暴力,过了。

看一眼时间,T1T2 总用时 1h30min。不错的开局,和 10.27 的模拟赛的开局基本一模一样,只不过 27 号是 T2 稍微想错了一点。

打了 T3 O(qn) 暴力,然后想正解,先糊了糊线段树分治,发现实在不行。然后看到一个 1e5 的部分分,猜测是分块。共用了 1h,得到了这样的做法:

对每一个点按照入度分类。对于度数 > sqrt(m) 的点 u,维护一下块 S 内点的 出度总和 sum(对于 v\inS, 不限于统计 v->u)、链接的边没断的个数 cnt。
1 操作:断掉 v->u。修改所有包含 v 的 S 的 sum,修改 out[v],把 vis[v->u] = 1
2 操作:断掉 u 的入度。如果是大块,那么 sum -= cnt, cnt = 0。(虽然这没有完全修改到应该修改的块的 sum,但是足以判别是否有解。到时候复原一条边可以利用 vis 保证不会把 sum 没有变化的 S 改到);小块暴力修改并同时统计信息。
3 操作:修复 v->u。如果 vis = 0,说明只能增加 u 的 S。 记得复原 vis。
4 操作:修复 u 的入度。

(现在来看,实际上是有问题的,因为 3 操作小块暴力修改没有对应到大块上啊。

时间是 17:00 ,决策是先打 T4 暴力。

感觉 T4 好像很可做,设 V 表示每一个点一步可达的点数量,先上了一个复杂度 O(nV\log V) 的最短路(c,现在差点算成 VlogV,当时算对了的),感觉能不能过 n = 2000 完全看 CCF 脸色。

再上了一个 k = 1 的裸树剖,然后感觉这个东西很倍增,但是如果直接设 f[i][j] 表示 i 往上跳 2^j 步的话相当于是强制钦定选点了,是错误的,有点不对,暂且搁置。

看到树高 log 的部分分,最开始没有考虑到 k = 2 的时候就已经可以先跳到子树内再跳出来了,然后憨憨地写了一个 DP 发现不太对(感谢大样例)。然后想出了解决方案:只需要像换根 DP 一样预处理一下前缀后缀祖先mn即可。

时间是 17:50(左右?),面临的抉择: T3 q\sqrt(n) 信仰过题但是算法正确性有点怀疑 / T4 树高 log 30pts(?) 部分分但是代码实现难度高。

抉择是相信自己,爆冲 T4,失败了。一个失败的原因是考虑到 lca 处的确很特殊,但是忽略了区间询问处理 pre 和 suf 是不够的!需要加一个 ST 表!如果写成 bfn 上 ST 表的话,代码复杂度将会骤降!!!

全场一共打了 17KB 代码。

出考场的时候很不甘心,觉得自己 T34 的决策有问题,感觉 T3 代码复杂度明显小很多但是当时没有开的勇气。有点郁闷。但是现在来看确是一个正确的决策,虽然结果不是很好,但是冲 T4 部分分肯定比冲 T3 假做法好。但是会不会冲 T3 冲着冲着就想出了真正的正解呢?毕竟这个做法的思想已经和正解很像了。不知道,尽人事,听天命。

考完回家车上没事干,花了 5s 给 T4 糊了一个矩阵 DP。

晚上刷 UOJ 群的时候突然发现 T1 因为 BFS 初值 -1 所以要判断连通性,心脏骤停,睡觉的时候满脑子都是 T1 挂了,还做了一个 T1 挂了导致 CSP 错失一等的梦。

T1 没想到连通性问题,深挖就是平时背板子入脑,对算法的理解不够,考虑的不够细致(bfs 写的是 dinic 的板子,但是 dinic 的 bfs 的一个作用就是判联通)。当时为什么不对拍呢?虽然暴力也是错的。还记得当时写了一个 maker.cpp 但是想着要建立一个连通图,要保证无自环重边,造数据太麻烦了所以相信大样例。可见只能说是连通性是一个思维盲区,看到图就默认联通。受教育了。

T3 正解集合 HASH,旧 trick,首次见于 公价大爷游长沙,长见识了。

T4 正解的确是倍增,上面的问题是不能固定跳到哪里,所以状态设成 用 \(f(u,p,i,j)(0≤i,j<k\) 表示考虑从 u 开始往上 \(2^p\) 个点构成的数列,从距离 u 为 i 的点走到距离 2p-th father(u) 为 j 的点的答案。也就是说,如果当时的思考在深入一点就有了,即既然这个状态会有问题,就增设状态表示跳到哪里。

upd:cccccccccc,实际上已经差不懂已经有了的!为了打树高 log,设的状态是 f[i][d1][j][d2] 表示从距离 i d1 走到距离 j d2,只需要把这个改成倍增形式就好。

upd:没拿到 k = 2 的部分分,蠢了,k = 2 如果要进子树的话肯定是不优的,可惜。

综上可见,现在确有实力,但是还不够,差点码力,差点思维。在接下来的一个月里,如若再有所增进,未免没有 T1 考虑完善的希望,未免没有场切 T3/4 的希望。

10.31 模拟赛

10 月的终章!11 月的序曲!

读题一遍。
9:05 切 T1
9:45 总算写对 T2 暴力,发现是爆栈了而不是错了
10:30 放弃 T2
11:15 放弃 T3
11:45 T4 蒙蔽
12:10 抢救 T2

T1 最开始以为可以直接贪心。然后稍微转化题意发现 01规划,只不过多了一个选 k 个的限制,那么我们 wqs 二分。一个错点是应该写成二分答案套 wqs 二分,而不是反过来。因为有凸性的不是二分答案的结果,搞清楚有凸性的是啥。

T2 随便搞了一个 nk 的 DP,然后猜了一个矩快但是由于转移涉及到 +1 就不会了。观察分析了半天转移,发现这个 +1 很难办。然后思考期望的线性性,试图计算 i 发抽中的期望次数以做一个背包,但是期望线性性要求拆开的这些东西是无关的,所以 G 了。

跳到 T3,有点麻,首先搞一个 Trie,然后发现每次抉择的时候会强制一些数必须被操作等等,分类讨论一通得到了的做法类似题解的部分分做法,即虑枚举所有可能的最高位组合,剩余部分每一位是独立的,贪心选取。

没敢写,因为感觉有点 bug,跳到 T4,打了 40pts 的暴力分,发现 ans<=10^6 感觉很可做但是不太会。感觉这个很点分治啊,一个 naive 的点分治是考虑枚举一对点的 lca,画了画发现不是很好算,而且涉及到一个容斥的问题。一个思考是类比 d 邻居,定义 k 邻居,但是还是不是很会算。

时间不多了,计算了一下分数发现不容乐观。决定 SOHA T2,因为 T2 看起来就很矩快。

抢救回来了,nice,原来矩快里面还可以设常数项。。。。属于是 [THUSCH2017]大魔法师 没掌握。

剩下 5min,想着把 T3 K = 1 乱搞一下,但是没有时间了。

可以发现这把 T2 亏麻了,一共花了 2h 的时间,导致后面没有打 T34 性质分的余地。

下午干的事情:学习理解写 T4 代码

晚上干的事情:复习点分树、思考CSPT4倍增做法,思考 CSPT4 矩阵做法、学习 CSPT4 点分治做法、学习总结数点覆盖去重技巧。

晚上通过水 UOJ 群加深了对于 DP 的理解

感觉今天晚上人都思考麻了。

20221031T4

神仙点分治题!加深了对于点分治的理解!

sol1:

考虑 3 个点的 k 邻居集合的交集一定是一棵树,考虑枚举 3 个点的交集里面的点 u 计算有多少个点和它的距离 <= k / 2, 设为 cnt(x), 那么 u 对答案的贡献是 C(cnt(x), 3)

k / 2 不好计算,所以我们先拆一次边。

问题是交集是一棵树,所以会算重,一个巧妙的解决方法是 点-边容斥。那么我们再来一次拆边(没有实际拆),把边搞成看成点。

问题变成对于所有 x 计算有多少个点距离 <= k,对每条边计算有多少个点到两个端点的距离都 <= k。

有如下一个巧妙的点分治:

对于两个存在“父子关系”的分治中心 fath 和 u,在分治到 fath 时,遍历 fath 管辖范围的所有点并计算出这些点和其他子树有多少 <= k 的(为了避免算重到自己子树的,需要像普通点分治一样进行容斥,即对每一个子树,将初始 dep = 1, sign = -1 进行计算。)如此,实际上计算的是点分树上 u 子树内的点和 fath 子树内,u 子树外的点的贡献。

巧妙啊。

感觉似乎可以把这个思路应用到我的 Problem 上面。仔细想了想发现不太行。

sol2:

观察满足条件的三元环,发现三者之中距离最长的一对的一个点必然是这三个点中深度最深的,不然可以调整成最深的。

那么考虑枚举每一个点作为深度最深的点,计算有多少个深度比他小的点距离 <= k。这很 震波,只需要按照 bfn 序一个一个为点赋权即可。

CSPS2022T4

看懂了一个老哥的申必点分治做法,明天再来。

posted @ 2022-11-01 21:29  _Famiglistimo  阅读(213)  评论(1编辑  收藏  举报