10.3
T3
序列修改
在时间轴上考虑,相当于每个时间除了自己该有的还能额外带上 \(k - 1\) 个东西。则对于每个数,将每两个相邻的出现中间视为一条线段,则希望选出一些线段满足每个位置被覆盖不超过 \(k - 1\) 次,并且费用最大。经典建模,建一条数轴,源向第一个点连流量 \(k - 1\),每条线段起点向终点连流量 \(1\),费用为其代价的边。最大费用最大流即可。通过 \(S \rightarrow 1\) 的边限制了每个时刻被覆盖次数 \(\le k - 1\)。
T4
将子段归零
要求 \(\max \{ \#(a_i \le x) - x \}\),发现很像霍尔定理的形式,于是转化为二分图匹配问题。由于这里匹配的特殊性,可以直接贪心。每次新加入一个东西的时候,如果可以匹配,则直接匹配。否则踢掉位置最小的匹配的 \(a_i\),换上新的东西。判断匹配也用霍尔定理,然后再开一棵线段树维护每个 \(a_i\) 是否匹配即可。
10.4
T3
魔法
形成路径,等价于连通且每个点度数不超过 \(2\)。连通性只需要把每个点向父亲连边,若点集只有一条连向点集之外的边则连通。而度数不超过 \(2\),考虑维护从小往大加点时每个点第一次度数超过 \(2\) 的时间。每个点度数超过 \(2\) 有两种情况,一种是选了三个儿子,一种是两个儿子一个父亲。三个儿子容易统计,两个儿子一个父亲的情况,由于每次更新父亲的时候需要暴力儿子,但儿子其实没有发生变化,于是把这种情况挂到父亲上统计。这样就能快速完成更新了,每次只需要更新常数个点。而对于连通性,注意到如果一个父亲下面有超过两个儿子,则第三小的儿子造成的限制没有用,因为它限制的时刻已经被前两小的儿子限制死了。因此只需要对每个点维护最小的两个儿子的连边即可。
- 我咋这都不会做?
T4
防御塔
注意到至少一对相对的方向只会各自选一个矩形。显然。不妨假设左上-右下各只选一个,则可以预处理这两类矩形分别覆盖了什么。然后枚举纵坐标最靠上的一个左下矩形,然后贪心选交它的纵坐标最靠下的右上矩形,然后再贪心选交它的横坐标最靠右的左下矩形,依此类推。可以用记忆化搜索写。但是由于最开始选的右上矩形和左下矩形的左上空白无法被左上矩形覆盖,因此需要额外选一个。这样就做完了。
- 第一步观察,即使显然。
10.7
T2
数据结构
考虑二分答案,每次 check 需要检查区间是否存在比某个数大的数。若不带修可以直接从小到大加数可持久化线段树维护,带修就直接把 \(x\) 的线段树的 \([l, r]\) 区间贴到 \(x + 1\) 的 \([l, r]\) 区间上就好。注意贴上去的过程中被贴的线段树所有被修改的节点都需要可持久化,否则会出问题。
T4
树据结构
树剖套可持久化线段树维护修改,链查拆成到根链查,子树查用定期重构,每次重构更新版本树的子树和,散块暴力检查即可。
10.8
T3
数据结构题
显然的事实是交也是值域连续的区间。考虑枚举交的右端点 \(x\),并假设右边比中间大。此时我们考察右端点往右这一块,起点为 \(x + 1\) 的最长值域连续段。由于这个段已经占据了这个值域区间,因此中间的交要是想和右边拼起来,则其必须包含这个最长值域连续段中的 \(\min - 1\)。那么在以 \(x\) 为右端点的所有包含 \(\min - 1\) 的值域连续区间中,显然我们任选两个出来作为左边的左端点和交的左端点都是合法的。于是做完了。
T4
图森破
条件即为 \(X\) 为自身的最小循环表示。发现所有最小整周期为 \(|X|\) 的串 \(X\),它们所有循环表示不同,因此具有唯一的最小循环表示。因此只需要计算长度为 \(n\) 的最小整周期为 \(n\) 的数的个数。设为 \(f_n\),则显然 \(10^n = \sum\limits_{d | n}f_d\)。莫反即得 \(f_n = \sum\limits_{d | n} \mu(\frac n d)10^d\)。于是答案为 \(\sum\limits_{n}\sum\limits_{d | n}n\mu(\frac{n}{d})10^d\)。将 \(n\) 拆开,得 \(\sum\limits_{n}\sum\limits_{d | n}\frac{n}{d}\mu(\frac{n}{d})10^dd\),即 \(\sum\limits_{d}10^dd\sum\limits_{i = 1}^{n / d}i\mu(i)\)。后面的杜教筛,前面的数论分块即可。其前缀和是好求的。
10.10
T2
过半数
对每个绝对众数 \(x\) 计算答案。将 \(x\) 视为 \(1\),别的视为 \(-1\),则我们要求前缀和序列中的顺序对数。数据结构维护即可 \(1\log\)。由于所有的总升高次数是线性的,因此考虑拿这个来均摊。扫到每个位置的时候,维护前面的前缀和的最小值,记为 \(minval\)。若当前要减少 \(x\),如果没有减过 \(minval\),则暴力减,因为这里减掉的都可以用前面的加来均摊。而若减过了,则显然不会产生贡献,直接一次减完。而对于中间的数的出现次数的维护,只需要在后面加回来的时候判一下设为 \(1\) 就好了。
10.11
T3
颜色
子树外容易,现在需要支持链加和查询儿子信息和。考虑将每个点的儿子分为重儿子和轻儿子维护。对于轻儿子,每次修改的时候跳重链,就把链顶父亲的轻儿子贡献更新一下。对于重儿子,每次查的时候直接访问即可。
- 写代码一定要注意特殊情况,如把原本颜色改成原本颜色。
T4
线下见面
考虑若存在 \(u, v, w\) 满足 \((u, v), (v, w)\) 有边,\((u, w)\) 无边,则若 \(v\) 空,我们可以让 \(u, w\) 通过操作 \((u, v, w)\) 变成空的。
先考虑树的情况。任意找到这样的一个结构,并以 \(u\) 为根。先用 \(v\) dfs 一遍整棵树,这样即使 \(v\) 一开始不是空的也已经相遇过了。因此可以视为空的。接下来清空 \(u\) 和 \(w\)。接下来我们可以清空所有第二层点。我们先把 \(v\) 上的东西移到 \(w\),然后用这个点和 \(u\) 操作,然后再 \((u, v, w)\) 就好。那么现在清空了第二层。
然后从上往下清空所有偶数层。设当前点为 \(x\)。由于祖父为空,因此通过 \((fa_x, fa_{fa_x})\) 和 \((x, fa_x, fa_{fa_x})\) 两步操作可以将 \(x\) 移到父亲。
然后从下往上清空所有奇数层。由于父亲为空,因此通过 \((x, fa_x, fa_{fa_x})\) 和 \((fa_x, fa_{fa_x})\) 两步操作即可将自己扔到祖父。
这样整棵树就全部汇集到根了。
而对于图,若非完全图则可以找到 \((u, v, w)\) 的结构。然后我们希望找到一棵生成树,满足每个点和其祖父没有边。不难发现 bfs 树满足这样的性质。于是拎出以 \(u\) 为根的 bfs 树套上面的做法即可。而完全图是容易做的,只需要轮流操作 \((1, 2), (3, 4) \cdots\) 和 \((2, 3), (4, 5), \cdots\) 即可。
-
希望获得一个空点,于是凭空创造了等效的空点 \(v\)。
-
逐层清空。
一步都想不到啊。