2024.2 训练纪要

THUWC + NOIWC + 过年完了,得滚回来打模拟赛了。

快要省选了哈哈。要寄大了。

WC 2024 游记 可能还是会持续更新的,毕竟讲的题整理没整理完代码也一个都没写,有点傻逼。

2024.2.15

100 / 100 / 20, sum 220, rk 12/98

我这波是致敬 WC。

R35 T2 弱化的杨表

简要题意:给定长为 \(n\) 的数组 \(a_i, b_i\),对于一个长度为 \(n\) 的合法括号序列,一个位置填左括号的权值为 \(a_i\),填右括号的权值为 \(b_i\),这个括号序列的权值为每个位置的权值和,求合法括号序列的权值最小值。\(n \le 3 \times 10^5\)

赛时做法:考虑先让每个位置全部钦定权值较小的那个,然后尝试调整使得其变成合法括号序列。考虑合法两个条件:前缀和没有小于 \(0\) 的位置,且总和为 \(0\)。先调整第一个条件,从前往后考虑,碰到小于 \(0\) 的位置就在这个前缀中找到贡献最小的反转,每次这样会使得后缀和加 \(2\)。这样操作后就满足了第一个条件,考虑第二个条件,对于一个后缀最小值为 \(2\) 的位置,这之前最多只能进行一次操作,最小值为 \(4\) 的位置只能进行两次操作,那么我们找到最小值为 \(2,4,\cdots\) 的位置,在后缀中选一个最小值即可。

R35 T3 达拉然的废墟

简要题意贺的。

简要题意:\(T\) 组询问,每次给定 \(n,k\),问:如果一个 \(2n\) 个数的排列所有偶数位置构成的子序列是单调递增的,那么说这个排列是好的。将一个好的排列按照顺序拆分成若干组,每一组个数都是偶数,形成的结构叫做一个城市。一个城市的价值是每个组内部的逆序对个数的乘积。求从所有城市中随机选取一个,它的代价的数学期望。\(T \le 10^4, k \le n \le 500\)

考虑题目可以轻松转换成在每一段中选取一对逆序对的方案数期望。分几种情况,显然不能都是偶数,那么就是奇奇,奇偶,偶奇。由于奇数位置没有限制,奇奇为逆序对的概率就是 \(\frac{1}{2}\),但是因为偶数位置的限制,后面两种概率并不好计算。

考虑用大根堆来刻画这种大小关系,把偶数位置连成一条链,偶数递增就代表这棵树是大根堆,而对于一棵树是大根堆的概率为 \(\prod \frac{1}{size}\),这个 ucup 某场有,懒得写了。那么我们用大根堆来刻画。那么对于偶奇的情况,相当于对应的偶数点下面挂一个叶子,对于奇偶的情况,我们容斥一下即可,用任意情况减去在偶数点下面挂一个叶子的概率。但是 \(\prod \frac{1}{size}\) 还是不好计算,注意到每个点下面最多挂一个叶子,也就是 \(size\) 之间的差值最多是 \(2\),我们可以考虑记录一共挂了 \(k\) 个叶子,把没出现的 \(size\) 乘上,最后除以一个 \(\frac{1}{(n+k)!}\) 就行了。

那么设计 DP \(f_{i, j, k}\) 表示考虑前 \(2i\) 个点,共划分了 \(j\) 段的期望中,\(\frac{1}{(n+k)!}\) 的容斥系数和是多少,那么有:

\[\begin{aligned} f_{i, j, k} &= \frac 12 \sum_{l=0}^{i - 1} f_{l, j - 1, k} \frac{(i-l)(i-l-1)}{2} & \textsf{奇奇}\\ &+ \sum_{l=0}^{i - 1} f_{l, j - 1, k - 1} \sum_{p=l+1}^i (i-p) (p+k-1)& \textsf{偶奇}\\ &+ \sum_{l=0}^{i - 1} f_{l, j - 1, k} \sum_{p=l+1}^i (p-l) - \sum_{l=0}^{i - 1} f_{l, j - 1, k - 1} \sum_{p=l+1}^i (p-l) (p+k-1)& \textsf{奇偶}\\ \end{aligned} \]

奇奇就是在中间选取两个点作为逆序对,概率为 \(\frac 12\),偶奇就是枚举偶数的位置,然后在前面选取一个奇数的位置,由于在这里挂了一个叶子,这个子树的 \(size - 1\) 没有出现过,所以乘上 \(size - 1 = p + k - 1\)。奇偶前面是总方案数,后面是容斥。

注意到系数都是关于 \(l\) 的多项式,次数不超过 \(3\),也就是说这个转移是 \(pre_{i, j, k, p} = \sum_{l = 0}^i f_{l, j, k} l^p\) 的线性组合,其中 \(0 \le p \le 3\),那么我们就可以维护出这个 \(pre\),然后就可以 \(O(1)\) 转移了,这样就是 \(O(n^3)\) 解决,需要卡常。

最后由于上面是对所有排列计算的,而题目要求的是所有合法排列的期望,合法排列方案数是 \(\binom{2n}{n} n! = \frac{(2n)!}{n!}\),所以需要给答案乘上一个 \(n!\)

2024.2.16

今天这场 2022 的时候打过。不过不得不说我还是太菜了,nfls 榜还是太恐怖,我真的打应该会炸飞。

唉我真的不会随机化啥的啊是。

随机语句破碎。

所以今天在补 WC 听课记录,去隔壁看去吧。

喜报:补完了。WC 2024 游记(now with 听课记录)

2024.2.17

数据结构专题哈哈。

感觉似乎应该做点计划了,但是又并想不到什么好的计划。

晚上 cf,我能上回 gm 吗。

好的下大分了,E 条件想假了一个多小时,两小时一个题没过,真弱智。赛后把赛时想法扔了从头想,半个小时会了 E。这种思路不对但是长时间不改思路的问题怎么改掉啊,麻痹了。

L2.17 T2 (P8860 动态图连通性)

首先注意到每条边只有第一次修改是有意义的,因为如果第一次删不了之后一定也删不了,第一次删了之后仍然删不了,所以我们记录每条边第一次被删除的时间,剩下的边给他随便赋一个时间。记它为 \(d_i\)

考虑这个过程,实际上会一直删除所有的边直到剩下一条路径。容易发现,这条路径的最小值一定最大,因为较小的路径就可以被删除了,同理,次小值也最大,以此类推,最后剩下的路径应当是边权所形成的集合的字典序最大的一条路径。那么我们可以使用经典 dijkstra 加主席树来解决这道题。

存在一个更简单的做法:注意到这里有一个性质,边权两两不同,也就是主席树的过程不会发生进位。这样的图实际上有优秀的性质。考察 dijkstra 的过程,需要找到当前未固定的最短路最短的点,这样的点一定都是某个确定最短路了的在集合中的点向不在集合中的点连边,我们考察两条路径 \(dis(u) + w(u) \to dis(x)\)\(dis(v) + w(v) \to dis(y)\),比较两者的大小。假设 \(dis(u) < dis(v)\),注意到由于 \(x\) 未被拓展而 \(v\) 已被拓展,那么一定有 \(dis(u) + w(u) > dis(v)\)。考察 \(dis(u), dis(v), dis(u) + w(u)\) 三者的二进制表示,由于 \(dis(u) + w(u) > dis(v) > dis(u)\),那么去掉 LCP 后,不同的三位只可能是 \(110\) 或者 \(100\)。显然由此可以得到 \(w(u)\) 一定是当前这一位,而这一条边还没有被经过,\(dis(v)\) 也一定不可能经过了这条边,所以三位只可能是 \(100\)。那么此时,假如 \(w(v)\)\(w(u)\) 大,那么一定有 \(dis(v) + w(v) < dis(u) + w(u)\),反之一定有 \(dis(u) + w(u) < dis(v) + w(v)\)。也就是说,两者的大小关系只取决于最后一步出边的大小关系,那么我们就可以 \(O(1)\) 比较两者的大小关系了,于是就可以在 \(O(m \log m)\) 复杂度内解决本题。

L2.17 T11 (P6845 [CEOI2019] Dynamic Diameter)

这题做法应该是很多的,比如可以无脑边分树加线段树 \(O(n \log^2 n)\)

有一个神奇的做法:考察路径长度等于 \(dep(u) + dep(v) - 2 dep(lca(u, v))\),把这个东西放到欧拉序上,发现相当于 \(dep(u) + dep(v) - 2 \min_{i \in [u, v]} dep(i)\),那么我们只需要对于所有 \(u \le i \le v\)\(dep(u) + dep(v) - 2 dep(i)\) 的最大值就行了,这可以直接线段树上类似于最大子段和的方法维护,即可 \(O(n \log n)\)。对边权的修改相当于进行区间加,线段树上维护一下。

L2.17 T5 (P7125 [Ynoi2008] rsmemq)

感动,好像是自己想出来的

首先注意到实际上我们只需要对每一个位置,考虑以这个点为中心有哪些区间半径是合法的,然后区间计数一下即可。对于每一个中心,注意到其合法半径可以由这个数出现次数个区间组成,也就是说这样的总区间数是 \(O(n)\) 的,如果我们能求出所有的这样的区间,那么就可以二维数点计算答案。

有出现次数,那么我们考虑根号分治一下。首先对于出现次数大于 \(\sqrt{n}\) 的数直接暴力即可。对于出现次数小于等于 \(\sqrt{n}\) 的数,我们可以考虑二分找到每个区间,二分需要查询区间内众数是不是给定的数,发现这个东西单次肯定没法低于根号,但是注意到出现次数小于等于 \(\sqrt{n}\),我们可以把问题改变一下,改成查询区间内所有数的出现次数是否都 \(\le t\),其中 \(1 \le t \le \sqrt{n}\)。考虑对每一个右端点,合法左端点肯定是一个后缀,我们可以直接双指针处理出来每个右端点对应的最靠左的左端点,然后就可以轻松 \(O(1)\) 查询上面问题了,于是我们就可以 \(O(n \sqrt{n})\) 预处理,\(O(n \log n)\) 二分解决这个问题。

最后查询区间内的合法子区间数,考虑将区间拆成中心在左半部分和在右半部分两种,中心在左半部分只会受到左端点的限制,右边同样,考虑左边,记合法位置区间为 \([l, r]\),考察的一个合法区间中心为 \(i\),半径为 \([L, R]\),那么限制条件为 \(i \in [l, r], i - L \ge l\),贡献为 \(min(R - L + 1, i - L - l + 1) = min(R, i - l) - L + 1\),拆一下 \(\min\) 即可,可以变成一个二维数点问题,直接做即可,这样总时间复杂度就是 \(O(n \sqrt{n} + m \log n)\)

2024.2.18

100 / 100 / 45, sum 245, rk 2/59

哈哈。

T2 大分类讨论题,没啥意思不写了。T1 整出一个挺有趣的做法,还当了一会最优解,虽然后来被抢了。

arc 居然上分了,感谢 uu 对我 E 的指导与我写爬山随机数从 \([0, n]\) 中随机而不是 \([-n, n]\) 中随机导致调了半天调不出来。不过 D 爬山过了挺哈哈的,咋都会正解构造,无法想到正解构造,哭哭。

R37 T1 A Dance of Fire and Ice

简要题意:有一个变量 \(x=1\),给定 \(n\) 个操作与一个质数 \(p\),每个操作形如 \(x \gets a_i\)\(x \gets x \times a_i \pmod p\),选择任意个操作以任意顺序执行,问能够得到多少种操作。\(p \le 2 \times 10^5, n \le 10^6\)

首先离散对数转化一下,然后直接 bitset 优化就能做到 \(O(\frac{np}{w})\),此处 \(n\) 太大了并不是很能接受。

有一个直观的想法,就是似乎经过若干次操作之后不能被表示的数就很少了,考虑当所有数都能被表示了就直接 break 掉。但是显然构造一堆 2 的倍数就可以卡掉。

不过还可以继续考虑类似的思路,观察到能够使得新的数被表示的操作实际上只有 \(O(p)\) 次,如果我们能把 bitset 操作降到 \(O(p)\) 次就能得到 \(O(\frac{p^2}{w})\) 的复杂度,是很能过的。

考虑什么时候加入一个数不能使得新的数被表示。发现当且仅当对于任意 \(i\)\(a_i = a_{(i+v) \bmod (p-1)}\),那么此时 \(a_i\) 一定可以划分成 \(\gcd(p-1, v)\) 段完全相等的部分,那么我们考虑直接把 \(a\) 序列的长度缩减到这个级别,这样如果一次操作 \(v\) 是当前 \(a\) 序列长度的倍数那么可以直接跳过,否则要不然会表示出新的数,要不然会使得序列长度减少,这样实际上只会进行 \(O(p)\) 次操作,于是这样就可以得到一个 \(O(\frac{p^2}{w})\) 复杂度的算法了,可以通过,赛时最优解,但是赛后被常数小的老哥用这个做法把我爆了。

R37 T3 字符串

简要题意:对于一个映射 \(f : \{0,1\}^{2k+1} \to \{0,1\}\),定义其合法当且仅当其满足对于任意一个长度无穷的 01 串 \(s\)(其中 \(1\) 的个数有限),每次令 \(s[i] \gets f(s[i - k, i + k])\),无论进行多少次操作,\(1\) 的个数不变。将这样的映射写成一个长为 \(2 ^ {2 ^ {2k+1}}\) 的 01 串,每次寻味给定一个 01 串,找到字典序大于等于这个 01 串的字典序最小的合法映射。\(k \le 5\)

这题感觉很有趣啊。首先有一个转化,直接整一张 de Brujin 图,边权设为加的字符,对于某一个映射,将对应的边减去对应的值,这样条件就可以转换成,对于任意一条从 \(0\)\(0\) 的路径,路径长度为 \(0\),这等价于所有从 \(0\) 到某个点的路径的路径长度相等。那么如果设 \(0\) 到每个点的距离 \(dis_u\),条件就是对于每一条边,\(dis_v = dis_u + w\)

字典序可以考虑贪心构造,我们需要 check 对于一个固定的前缀,是否有解。对于固定的边,必须满足 \(dis_v = dis_u + w\),而对于没有固定的边,一定有 \(dis_v = dis_w + 0/1\) 或者 \(dis_v = dis_w - 0/1\),可以考虑用差分约束来描述这个条件,这样只要差分约束有解就是可行的。暴力 SPFA 判断负环是 \(O(nm)\) 的,所以暴力做的时间复杂度就是 \(O((2 ^ {2k + 1})^3)\)。注意到这张图中每个点到每个点的最短路是 \(O(k)\) 级别的,于是实际上每个点只需要入队 \(O(k)\) 次就可以判断存在负环了,于是判负环只需要 \(O(km)\) 即可。于是复杂度就降到了 \(O(k (2 ^ {2k + 1})^2)\)

ARC172D Distance Ranking

考虑增量构造,假如我们随便固定一组 \(d(i, j)\),然后尝试构造满足这个条件的点集,感性手模一下,二维的时候只要满足三角形三边不等关系就能有解,三维时只要在二维的三角形基础上找一个神秘点,这个点可以由三个点分别作三个球的交点得到,如果这三个球的半径和三角形三边长度差不多那么应该是有交点的,于是我们把 \(d(i, j)\) 设成一个比较大的数加上一些微调,然后每次爬山找到交点,然后乘 \(10^8\) 取整就好了。

2024.2.19

100 / 100 / 0, sum 200, rk 20/78

T3 口胡了个做法,以为过不去,结果是正解,虽然好像有理论复杂度更优的做法,不过网络流嘛理论复杂度有个寄吧用。

T2 由于线性无关集合是拟阵,直接使用 [HNOI2014] 画框 的做法即可(最小乘积生成树)。

下午开了 USACO,啥都不会,好像有个 T2 做法,但是不想写,也不懂对不对。我是摆烂大师。

2024.2.20

100 / 100 / 10, sum 210, rk 8/94

咋感觉现在成天打类 WC 模拟赛,T1 T2 全都会 T3 全不会,然后全是 \((200 + \epsilon)\) 分。

T2 考过原题,虽然确实一点不记得了,here。不过这次我会连续段 DP 了,感动。

T3 感觉看着不是很可做啊,咕了(

哎我怎么这几天都懒得改题了。尝试写了会昨天的 T3,然后写了一会就去体活了,体活回来发现洛谷掉登陆了,登陆显示密码不对,这下给我惊到了,什么人盗号先盗我洛谷号啊。然后赶紧找我妈把密码改掉,把号找了回来,吓得改了好几个号的密码。然后缓了一会去找了粉兔,提供了大量信息,然后粉兔没查到这段时间内有可疑信息,有的记录都和我对上了,感觉就是洛谷出 bug 了。呃呃了。然后晚上就不想写题了,摆烂。

怎么明天一天时间整一堆数学题啊??麻了。nfls 的讲课怎么全是数学。

下了一天的雪,放假的时候下雪好啊,操场一个人都没有,雪快到脚踝了,完成了 曾经要干的事情,在操场上滚了一下hhhh

2024.2.21

哎我日这专题都什么逼题。直接弃了。

终于把前天 T3 补掉了。

R38 T3 PolarSea 与遗忘的森林 (Recover a functional graph)

其实思路挺简单的,就是细节很多有点难写外加不知道这玩意还能跑这么快。

首先考虑没有问号怎么办,注意到只需要满足对于每一个 \((h_i, l_i)\) 一定存在 \((h_i-1, l_i)\)\((0, l_i)\) 的个数是 \(l_i\) 的倍数即可。构造很简单,先把环整出来,然后接一条链,剩下的就接到链上对应深度的点上即可。

考虑有问号,发现我们可以找出每一个 \(l_i\) 对应的 \(h_i\) 的最大值 \(mx_i\),那么问题就是要把问号填充进一个数,使得 \(([0, mx_i], l_i)\) 均出现了至少一次并且 \((0, l_i)\) 出现次数是 \(l_i\) 的倍数。对于前者,这就是一个简单的二分图匹配模型。后者,我们注意到可以只把之前还没拼好的环拼起来,新加环显然是不优的。那么我们记录一下每个 \((0, l_i)\) 还需要多少,这样直接二分图匹配就好了。但是还有一个问题,就是有可能有一个 \(h_i\) 很大的 \((h_i, -1)\),如果 \(l_i\) 确定后可能会使得 \(mx_i\) 变换,这就很恼火了,但是注意到所有的这样的点可以让 \(l_i\) 相同,我们直接枚举一下选哪个就行了。复杂度是 \(O(n F(n, n^2))\),其中 \(F(n, m)\) 是二分图匹配的复杂度,匈牙利 \(O(n^4)\),dinic \(O(n^{3.5})\),常数不是很大反正都能过。

2024.2.22

100 / 0 / 6, sum 106, rk 63/85

蚌埠住,T2 少考虑一种情况直接保龄,改一下就过了。虽然写的还是随机化乱搞,因为真的不想写那个恶心线段树做法,但是事实证明 \(O(n^2)\) 剪枝就能过了。麻了。

这个 T3 看着属实阴间啊。感觉就算是能看懂也基本写不动。

啊一天又没改题也没做题,寄吧了。

L2.21 T1 (P3543 [POI2012] WYR-Leveling Ground)

首先差分一波,改成任意一个位置 \(+a\) 一个位置 \(-a\) 或者任意一个位置 \(+b\) 一个位置 \(-b\)。先全部除以个 \(\gcd(a, b)\)

\(c_i\) 进行了 \(x_i\)\(+a\)\(y_i\)\(+b\),负数则为 \(-a/-b\),即 \(c_i = x_i a + y_i b\),由于答案应当是 \(\frac{\sum |x_i| + |y_i|}{2}\),那么直接 exgcd 求出 \(|x_i| + |y_i|\) 最小的解。但是必须满足 \(\sum x_i = 0\) 才能一一匹配,所以考虑调整 \(\sum x_i\)。如果 \(sum < 0\) 则进行若干 \(x_i + b, y_i - a\) 的操作,否则进行若干 \(x_i - b, y_i + a\) 的操作,由于 \(|x_i| + |y_i|\) 最小,可以推出 \(sum\)\(O(nb)\) 级别的,所以操作次数 \(\frac{sum}{b}\)\(O(n)\) 的。容易发现 \(|x_i - t b| + |y_i + t a|\) 是凸的(两个绝对值函数相加),所以可以直接每次贪心选择增加最少的一个进行增加,拿堆维护一下即可。

2024.2.23

哈哈一题不会摆烂了。坐等放假了属于是。

2024.2.26

100 / 30 / 15, sum 145, rk 47/84

人不仅菜,而且挂分水平一流。T3 写了个 70 分结果有个细节挂了只剩下特判的 \(a_i\) 随机的分数了,呃呃。

T2 我还是不会啊??感觉还是完全不会图论啊,完全不知道怎么刻画强连通。于是下午阅读了下一些内容,还没读完,可能明天才能发学习笔记。

R43 T1 序列

简要题意:给定序列 \(a_i\),每次对 \(i \in [2, n - 1]\) 操作,使得 \(a_{i - 1} \gets a_{i - 1} + a_i, a_{i+1} \gets a_{i + 1} + a_i, a_i \gets -a_i\),问进行任意次操作后 \(\sum |a_i|\) 的最小值。

挺套路的东西,很像 NOIP2021 T3 的做法,不过比那个简单。发现一次操作后三个数和不变,考虑整体做前缀和,发现操作是将两个前缀和进行了交换,那么问题就变成了将中间部分随便排列,使得相邻两两差的绝对值最大值最小。最后一定是两次折的形式,且交错左右放肯定最优,证明调整,贪心即可。

R43 T2 ddtt (GYM102759C Economic One-way Roads)

哎我还是不会啊!

有一个好东西:一个图是强连通图,当且仅当其存在耳分解。我们可以用耳分解来刻画强连通图,这样的好处是可以增量。

耳分解就是,初始从一个环开始,每次加一条起点终点都在当前点集,中间点不在点集中的路径,然后把所有点与边加入当前点集和边集,每次加的路径就叫耳,容易发现这个过程就是把整张图划分成了若干个耳。

那么直接暴力整点子集 DP 就能 \(O(3^n \mathrm{poly}(n))\) 了。然后改成动态加点,但是没法记录哪些边加了哪些边没加,导致有些边加不上。注意到只有 DP 过程中的边的方向选择是重要的,剩下的没加的边实际上选哪个方向都可以,那么我们先钦定所有边全部选权值较小的方向,这样就不需要要求所有边必须全选了。然后再进行上面的 DP,就可以 \(O(2 ^ n \mathrm{poly}(n))\) 了。具体来讲,每次枚举加入的耳的起点和终点,然后每次让起点进行移动,当起点终点重合的时候就再加其它的耳。注意不能出二元环(正边反边不能同时选),所以需要记录一下当前选了多少边,或者可以在统计答案的时候钦定先走一步,这样一定至少是三元环。

R43 T3 扫雪

简要题意:给定排列 \(a_i\),在平面上表示 \(n\) 个点 \((i, a_i)\),相邻两个点连线。同时每个点有一个权值,初始为 \(0\)\(q\) 次查询,一种是令区间内所有点权值 \(+x\),一种是查询从 \((u, a_u)\)\((v, a_v)\),每次可以从 \((i, a_i)\) 走到 \((j, a_j)\),必须满足 \(i < j, a_i > a_j\) 且中间不穿过任何线或经过任何点下方,求路径上经过的点的权值和最大值,或输出不存在方案。

发现题意可以转换成从 \(v\) 开始每次跳到左边第一个比他大的位置,然后求 \(v \to u\) 经过的所有位置的 \(b_i\) 和,还有 \(b_i\) 区间加法。

这相当于区间单调栈啥的,可以直接上兔队线段树,然后 \(O(q \log^2 n)\) 做完了,轻松跑过,哈哈。

我好像就没会过兔队线段树说实话。

2024.2.27

100 / 61 / 0, sum 161, rk 32/77

开场两个多小时才会 T1,然后突然发现 T2 是弱智题,然后结果寄吧出题人还卡逆元,T3 爆搜还 TLE 了,哎真你妈恼火了,,,

我日博客忘写了。。。省选前能写完吧应该

T1 小 Z 与函数

简要题意:有这样一个函数:

int get(int n) {
	int res = 0;
	for (int i = 1; i <= n; i++) {
		int vs = 0;
		for (int j = i; j <= n; j++) if (a[i] < a[j]) swap(a[i], a[j]), res++, vs = 1;
		res += vs;
	}
	return res;
}

问对一个数组的每个前缀执行该函数的值。

考虑一个 \(O(n^2)\) 的做法,就是每次加入最右边的数,会使得原来的过程发生什么变化。发现最后一个数永远不会影响之后每一轮的初始值与原来选择的值。也就是说加入一个数只会影响每一轮的最后一次操作,我们只需要考虑每一轮最后会不会把当前值换成最右边的值即可。注意到这恰好操作了比加入的值小的本质不同的值数次,那么用树状数组容易维护出这个次数。然后就是有效轮数,注意到我们只关心每个位置没有被操作前的初始值,我们只需要拿个 set 维护出来所有没有被操作过的位置与其初值,直接模拟过程就能找出哪些位置被改了。

T2 拼数

简要题意:有 \(n\) 个数集 \(B_i\),令 \(a_i\)\(B_i\) 中随机选取的一个值,定义一组 \(a_i\) 的权值为按照某种方式将所有 \(a_i\) 拼接起来(字符串拼接)得到的最大值,然后求权值期望。

考察固定 \(a_i\) 怎么做,考虑如果只有两个字符串那么比较 \(a + b > b + a\) 就行了,然后打表验证一下发现是满足严格弱序的,所以可以直接 sort 了。那么我们只需要把所有串全部 sort 一遍,分开考虑每个串的贡献,这样我们只需要知道最后集合中比它小的串的长度之和即可,它的贡献就是 \(a_i \times 10^{len}\)。然后求这个期望就比较简单了,可以直接扫描线,维护 \(10^{len(a_i)}\) 的期望,从小到大考虑每个值,贡献就是所有与当前不在一个集合内的期望的乘积,然后更新一下期望即可,注意不要维护所有乘积然后每次除以当前位置的期望,因为邪恶出题人可以构造数据使得当前位置的期望等于 \(0\)

T3 敢览求

简要题意:给你一棵二叉树,每个点有两个权值 \(a_i, b_i\),你可以进行一下两种操作,一种是单点进行 \(a_i \gets (a_i + j) \bmod k, b_i \gets (b_i + j) \bmod k\),一种是子树加。问至少进行多少次操作可以使得所有 \(a_i \ge b_i\)

子树操作会对子树内造成影响,我们考虑把这个影响压入状态中,记 \(f_{u, i}\) 表示子树 \(u\) 的祖先对它的贡献为 \(i\),使得子树内合法的最小操作次数。

首先考虑操作一,那么 \(f_{u, i} \gets f_{lc, i} + f_{rc, i} + [(a_u + i) \bmod k < (b_u + i) \bmod k]\)。然后操作二,我们可以将整体子树贡献进行平移,也就是说 \(f_{u, i} \gets \min\{ f_{u, j}\} + 1\)。注意到进行第二个操作后,所有的 DP 值得差值不超过 \(1\),那么我们就可以改成维护最小值与所有最小值的位置,发现这样的转移就是若干集合取并取交一类的东西了。直接 bitset 优化即可做到 \(O(\frac{nk}{w})\)

注意到上述集合都是由一些连续区间组成的,所以考虑更高效的维护这个集合。有个神奇做法:考虑线段树合并。我们先考虑求交,求并的过程类似。线段树节点上维护这个节点内的区间是否完全被覆盖,然后考虑合并。如果两个节点有一个为空,那么返回 \(0\),因为空集合与任何集合求交肯定是 \(0\)。如果两个节点中有一个节点完全被覆盖,那么返回另外一个集合。否则,我们可以按照普通线段树合并的方法合并,容易发现这样复杂度与正常线段树合并的复杂度是一样的。求并是类似的。从而我们可以在 \(O(n \log n)\) 的时间内维护出上述所有答案。

求交求并的代码:

int mand(int x, int y) {
    if (!x || !y) return 0;
    if (t[x].val) return y;
    if (t[y].val) return x;
    int z = ++tot;
    t[z].lc = mand(t[x].lc, t[y].lc);
    t[z].rc = mand(t[x].rc, t[y].rc);
    if (!t[z].lc && !t[z].rc) return 0;
    if (t[t[z].lc].val && t[t[z].rc].val) t[z].val = 1;
    return z;
}
int mor(int x, int y) {
    if (!x || !y) return x + y;
    if (t[x].val) return x;
    if (t[y].val) return y;
    int z = ++tot;
    t[z].lc = mor(t[x].lc, t[y].lc);
    t[z].rc = mor(t[x].rc, t[y].rc);
    if (!t[z].lc && !t[z].rc) return 0;
    if (t[t[z].lc].val && t[t[z].rc].val) t[z].val = 1;
    return z;
}

2024.2.28

100 / 100 / 50, sum 250, rk 1/65

不过 T1 是典中典题,T3 我考过但是当时就没看懂题解,但是暴力是容易的,然后 T2 是个交互。冲了半场多 T2 过了(

不过 T3 没打 5 分部分分亏了,因为写完 T3 暴力就已经 12:10 了然后我们吃饭点是 12:10 于是我直接吃饭去了(

算了明天模拟赛必考炸,要不然省选 rp 掉没了。

晚上吃了小火锅 😄 但是今天下午加晚上又啥都没干。唉我那个学习笔记还是没有写,日了。但是我现在完全看不下去那个东西啊。

R45 T2 交互题

简要题意:交互,有一个 \(n\) 个点的链,每次你可以查询一条长度为 \(n\) 的链与这条链的交的大小,还原出这条链,\(n \le 500\),询问次数 \(\le 8000\)

次数大致是 \(O(n \log n)\) 次,那么就考虑二分找出每一条边。

有一个朴素的想法,就是每次询问一个 \(i \to i + 1 \to \cdots \to i + n\) 一类的东西,这样相邻两个做差就能知道每相邻两个边的差值,注意到如果存在一个差不等于 \(0\) 那么就可以确定这两条边是什么了,而如果所有边差都等于 \(0\),由于不可能有 \(n\) 条边,于是一定所有边都是 \(0\)。这样我们就可以确定所有 \(i \to i+1\) 的边了。

类似的想法,我们可以去依次对于每一个 \(d\) 确定 \(i \to i + d\) 的边。当然直接暴力肯定不行,我们考虑二分,二分就需要找到一个区间内存不存在 \(i \to i + d\) 的边。那么我们就需要构造出一个包含一个区间内所有 \(i \to i + d\) 的边的路径。考虑一个大致形如,先从最左边的点开始,一直跳 \(d\),然后通过 \(O(1)\) 的变换跳到下一条链上,然后这样遍历所有链。但是问题是第一次跳到的链可能在所有链尾中的中间部分,这样我们可以遍历后面的所有的链或者前面的所有的链。不过我们实际上不需要必须只通过 \(O(1)\) 的变换,由于我们是从小到大考虑所有 \(d\),我们只需要保证跳的距离小于 \(d\) 即可,那么我们可以先走后面的所有链,然后一次跳跃跳到前面的链上,然后再遍历前面所有链,反正随便构造一下就行了。注意这样构造实际上是需要比区间多 \(d\) 的长度的,所以查询的长度不能大于 \(n-d\),不过我们只在乎 \(d \le \frac n2\)\(d\),所以我们查询两次分别考虑两半中的所有边就好了。

2024.2.29

100 / 100 / 50, sum 250, rk 1/67

啥玩意,搁这刷 rp 呢,,

T2 还是有趣的,T1 比较无聊。T3 不会,不过有高达 50 分暴力。

下午打了一些板子,仍然没有打 Tarjan,我相信我是会 Tarjan 的!!!!!11

学习笔记写完了。怎么会有人省选前读论文的啊???

R46 T2 Xor Game

如果固定了 \(2n\) 个,注意到先手实际上是废物的,因为这是个两两匹配的博弈,后手可以做到任意一组匹配,先手选哪个后手就选对应的匹配点即可。那么我们问题就是将数两两匹配,使得 \(\max (a_x \oplus a_y)\) 最小。在 Trie 树上考虑,依次考虑每一位,如果在某一层上某一个点的左子树与右子树的大小为偶数,那么一定有方案使得子树内两两匹配,使得所有值在这一位上都等于 \(0\),否则一定存在值这一位上是 \(1\)。那么我们从高往低考虑,如果某一时刻存在了奇数的子树大小,那么答案就是当前层所有奇数的子树大小之间匹配最小值的 \(\max\)

那么把 \(2n+1\) 个问题放到一起考虑,发现也就是多出了一条链满足一个奇子树一个偶子树,假如删除的点在偶子树就会使得当前这个点变成奇数,那么直接计算当前层的答案就行了,否则就可以直接递归下去接着做。假如删除的点在偶数中,我们就可以直接把偶子树内的所有点全拉出来,在另一棵子树内查询异或最小值,我们要删除每一个点看最大值,那么记录一下最大与次大值就好了。而递归是往奇子树递归,所以这样每一个点最多被暴力遍历一次,所以复杂度是 \(O(n \log n)\) 的。对于第一层出现奇数奇数子树的点,我们到这一层直接停就好了,这时候暴力遍历的节点数最多也是 \(O(n \log n)\) 的。

posted @ 2024-02-15 20:38  APJifengc  阅读(386)  评论(0编辑  收藏  举报