策马踏雪翩然过,携来人间万千烟火 ---May Part Two

发布时间 2023-06-01 22:26:59作者: Reanap

May Solution Set Part Two

ARC160E Make Biconnected

被加粗专门强调的性质是每个点的度数最多为 \(3\)

那么这一定是一棵二叉树。不妨对于每一个点考虑。

删去他,最多把整棵树分为三个连通块。至少要在三个连通块中连两条边。

选一个叶子做根。

每个叶子一定会往外面连边,然后叶子配对。每个子树最多向上传三个。

然后传到根,只剩一个,则直接连根。剩两个,则需要保证选根的时候选到了最优的根,即能与根连的点的权值最小。

「20230516 模拟赛」万家灯火

贡献可以转化为到根节点的边中,下面是暗的,上面是亮的的边数量。

然后这个可以直接点分树维护。顺手维护一下每个点在当前层儿子的亮儿子数量。

「20230516 模拟赛」逃亡

犯傻了,犯傻了。套用卡特兰,计算到达距离当前为 \(i\) 的点的概率。实际上一个组合数前缀和就可以完成计算。

然后对于整个问题,计算每个可能被到达的格子不被到达的概率。这样的格子有 \(O(nm)\) 个。

于是 \(O(nm^2)\) 就可以解决。

「20230516 模拟赛」地铁

区间是一个树形结构。那就是平面图,考虑平面图最短路转最小割。

然后限制就是限制两个子树内要么都割出路径,要么都不割出路径。连一下双向边即可。

但是,实际上,连上限制后,这并不一定是平面图了。也就是说,我们求出的最小割不一定对应最短路了。

那么我们考虑进一步限制。如果最小割不对应路径,那么就说明,有两条割是包含关系。那么就有下面的属于 \(s\) 集合的点连向上面属于 \(t\) 集合的点。所以我们把每条边的反向边的权值置为 inf 就可以保证不会出现下面的 s 集合连向上面的 t 集合。所以就保证了最小割一定对应最短路。

「BJOI2018」链上二次求和

考虑滚前缀和计算贡献。那么就需要维护前缀和的区间和,前缀和的等差和。

那么维护好了之后答案是易于统计的。

现在就是维护修改。后面一坨区间加,好改。

中间一坨需要加上等差数列。哦,实际上就是给个平方和也可以直接计算上去。

但是还有一个 tag 合并的问题。哦,相当于是和累加,公差累加。

「THUSCH2017」如果奇迹有颜色

一眼 Polya。考虑怎么算。

考虑到首尾仍有可能发生不合法行为,所以我们使用状压 dp 对其进行限制。

显然有 \(m^{\underline{m-1}}\) 的矩阵。然后可以跑暴力。

听说正解要 BM 还要打表,我破防了?

「THUSCH2017」杜老师

用线性基去想感觉就舒服多了。直接用 bitset 构建异或线性基,大概可以拿到 \(50pts\)

但是每个数,会发现只有最多 \(\log\) 位置是有值的,用 bitset 处理巨浪费。

换个方式构建线性基。每次拉一个他的最小质因子出来,然后看一下那个位置是否有值。

实际上,根号分治,对于大于根号的质因子只会出现一次。然后我们每个数只用检查它最大的质因子对应的位置是否有值。有值就异或上。

然后再用 bitset 反复异或维护线性基。

但是会发现这个 r-l+1 实在是太大了!其实大于 \(2\sqrt{N}\) 的时候所有出现过的质因子的位置都会被填上。

只用检查素数即可。

CF1832F Zombies

确定哪些区间在一个组后考虑确定最优区间。

本质上是最大化总交集。一定存在最优方案使得我们确定的区间的左/右端点在给定区间的左/右端点上(或者是数轴的边界)。

否则一定可以使用调整法使得其不劣。

所以可选区间的数量降低到了 \(O(n)\) 个。

我们应该可以定义 \(f_{i,j}\) 表示当前区间左端点在 \(j\) ,选择了 \(i\) 个区间的最优交集大小。

那么,实际上,我们可以进行二分选择新的区间的代价,实测发现整数代价就可以得出正确答案了。

那这里其实有一个贡献的改变问题。

\(j \rightarrow k\)

  • 左端点在 \(j\) 左边的,让 \(j\) 贡献更优。
  • 左端点在 \(j,k\) 之间的给定区间 \([l,r)\),仍需讨论:
    • \(r \leq i + m\) ,则这个区间归给 \(i\) 更优。
    • 否则,右边的区间,在右端点达到这个位置之前,贡献都是 \(m\),再往右移就会减少。再差分预处理一下贡献变化量就好了。
  • 左端点在 \(k\) 右边的,让 \(k\) 贡献更优。

于是可以维护一个 \(val_{i,j}\) 表示区间选在 \(i\) ,那么左端点 \(\geq j\) 的区间与 \(i\) 的交集和是多少。

复杂度 \(O(n^2 (\log V + \log n))\)

细节好像有点多,CF 叉人太猛了,把我给叉烂了。

CF1545E AquaMoon and Time Stop

不如先做 easy version

时间静止往往有两种情况。一个是在一个诅咒即将生效之际,一个是在这个人将要跨入诅咒区域的前一刻。我们每一次移动可以只移动一个极小单位,那么等价于我们可以快进时间。

当然,我们也可以花费代价去加速行走。根据节约精神,我们走过一个诅咒的右端点的时候,时间要么是某个诅咒结束时间 + 该诅咒左端点到当前点的路程。要么是这个诅咒的开始时间。

那考虑只记录左端点。如果我们在转移的时候来到一个左端点,诅咒没有开始,那么我们检查能否冲过去。如果能那就冲,不能的话就决策是留下来等诅咒结束还是一波加速冲到诅咒右端点。

冲过去还面临问题,那就是诅咒可能还有包含关系,冲过去可能就直接撞在别的诅咒上面了。


来不起了。

先把过程搬到二维平面上。

有四种移动方式:斜右上,水平向右,水平向上,水平向下。

后三种产生代价,大小等于距离。

显然有 \(O(XT)\)dp 解法。

然后离散化一下时间轴。考虑相邻两个时间 \(x_i \rightarrow x_{i+1}\) 的转移。

\(\Delta = x_{i+1} - x_i\)

\(p_j\) 表示所有覆盖 \((x,x_{i+1})\) 的限制里,离 \(j\) 最近的那个边界是什么。

然后从 \((x_i , j)\)\((x_{i+1},k)\) 的转移有两种情况:

  • \(j + \Delta \leq p_j\),那么一定是 \((x_i,j) \rightarrow (x_{i+1},j+\Delta) \rightarrow (x_{i+1},k)\)
  • 否则,一定是 \((x_i ,j) \rightarrow (x_i+p_j-j,p_j) \rightarrow (x_{i+1},p_j) \rightarrow (x_{i+1},k)\)

然后实际可以观察到每一个时刻的 dp 值其实是一个分段函数,每一段斜率都是 \(1\)\(-1\)

那么我们考虑去考虑维护,分段函数的所有极小值(即峰谷)。

有一个关键性质:如果 \((x_i,j)\) 是极小值,那么 \((x_{i+1},\min\{j + \Delta,p_j\})\) 有可能成为极小值。同时没有被这种情况覆盖到的则一定不是极小值。很好理解。

于是我们去维护所有有可能成为最小值的位置。

考虑第 \(x_i\) 列的情况,如果这一列有矩形左边界。那么 \((x_i , l)\)\((x_i,r)\) 也有可能成为最小值。

还要考虑这些关键点互相的转移,正反扫一遍即可。

然后就可以 \(O(n^2)\) 做了。

妈呀,写个 \(O(n^2\log n)\) 要了我半条命。先看看别的题再回来做 E2 吧。

对于 E2 ,我们去维护每个时间的连续段。形成若干个由关键点组成的平衡树。然后实际上,如果区间没有变动,我们的其他段的平衡树是可以直接打懒标记的,等需要合并了再一起处理。

一起处理的时候,可以将那些顶到上界的全部拉出来,取一个最小值再塞回去。

为了控制这个勾八复杂度,我要写一坨答辩。

我是答辩。哈,哈哈,哈哈哈。哈。

CF1718E Impressionism

首先每行每列的颜色集合不会改变。考虑先通过交换列使得行种类相同。

爷又来不起了。


问题等价于确定两个排列 \(p,q\),使得 \(a_{i,j} = b_{p_i,q_j}\)

对于 \(a_{i,j} > 0\) ,那么从左部点 \(i\) 向右部点 \(j\) 连权值为 \(a_{i,j}\) 的边,得到二分图 \(A\),所以这就是一个二分图同构问题。

不妨设 \(n \leq m\)。我们似乎可以一个连通块一个连通块地去判断!

我们假定 \(p_i = i'\),那么可以确定 \(j\) 要与 \(j'\) 一一匹配,即 \(a_{i,j} = b_{i',j'}\)

递归地,我们也可以继续确定整个连通块的对应情况。

只需要对两个图两部点大小相同时进行判断。实际上保证左部点大小相同即可保证复杂度。

那么复杂度平衡一下就是 \(O(n^2m)\) 的。

「THUSCH2017」巧克力

考虑给每个种类的颜色随机赋权。那么我们就把问题转化为了每个颜色都要选的最小中位数。

一次的正确概率是 \(0.0384\)。我们只用跑 \(150\) 次就能够有 \(99.8 \%\) 的正确率。

然后二分一个中位数,检查是否能够达到。

发现 \(\min \{n ,m\} \leq 15\)。可以考虑状压。那暴力做一遍都不一定跑的下来,还跑 \(150\) 次?

那可以考虑使用一下性质,就是说在保证块数最小的情况下保证中位数最少

那么可以先求最小块数。然后,定义 \(f_{i,j,s}\) 表示包含 \((i,j)\) ,考虑了前 \(i\) 行的生成树包含了颜色集合 \(s\) 的最小块数。这个可以一行一行算。复杂度 \(O(nm3^k)\)

加上权值就是二分一下,然后最小化权值即可。

牛客挑战赛68 妖怪之山

一步操作,可以删除一个白格子,可以将两端的白格子向两端移动任意距离。

不妨先考虑极限情况。首先这是一个公平组合游戏,先后手胜负关系确定。

如果全是黑格子怎么做?先手选一个黑格子,染白。白格子不可能继续变多了,所以之后还有 \(2n + 1\) 情况,直接就可以判断。

除非全黑,否则白格子不可能变多。我们不妨把全黑归作含一个白格子的情况。

所以,如果全黑或者只有一个白格子,则先手必胜。


不行了,等题解。

等到了。

假定我们的白色格子数量大于 \(1\)。那么我们每次操作,要么白色格子数变小,要么两端的白色格子距离变大。所以在此时不用考虑游戏结束的情况。

我们定义一个局面的权值为所有白色格子的位置编号之和。考虑我们每次操作对权值的影响,这 \(2n + 1\) 种操作会使权值减少的值恰是一个排列。由于第一次接手到有不超过一个白格子的人赢,所以我们可以定义第一次接手到全是黑格子的人输。那么这是一个巴什博奕,所以这个权值 \(\bmod (2n+2) \equiv 0\) 则先手必败,否则必胜。

CF1810F M-tree

唔,考虑二分答案。然后对 $a $ 进行判断。

每一层考虑增加的叶子数量,如果不翻倍,那就是值域连续地出现一车定值。

那么我们可以花费 \(\log\) 的时间,将我们的叶子数量翻倍。做完了。待会儿写。


假了。重来。好像还是很简单。相当于给每个位置赋个权,维护一个 \(m\) 进制数的给特定位的加减法。

线段树随便维护。然后找到最高位,随便讨论一下就做完了。

「20230520 模拟赛」 西克

\(x \rightarrow LCA\) 可以倍增跳,算出到 \(LCA\) 时的颜色。

\(LCA \rightarrow y\) 可以离线下来并查集统计。

「20230520 模拟赛」苯为

萌萌题。答案只跟最终的环长有关。实际上列出式子,然后线性递推解出通项。

虽然有次幂,但是次幂只与路径长度有关。于是按照路径统计的方式计算即可。

「SiR-1」Bracket

所谓 变换 操作,大概是只会做一次的。因为明显多步 变换 可以直接改写成一步变换。

不妨这一步变换放置到最后来使用。然后,假定变换是必须的。我们就只用将其当成环来看。

如果左右括号数是相等的,那我找到前缀最小的位置,把它右边换到前面来就合法了。

所以,现在需要判断的是有多少括号子串在添加括号后会直接成为合法括号串。为了让括号串不用变换直接赢,那左括号一定加在开头,右括号结尾。

那么如果前缀最小值在末尾则可以不变换直接赢。所以我现在只用维护前缀最小值的数量。

另外还有些基础的结果,可以树状数组做。卡我,要用一些特别的维护方式。

「SiR-1」Lighthouse

计数题,好讨厌。但 1e9+7 ,让人安心一点了。

不如讨论每个点的贡献情况。

首先是选择它对自己产生的贡献,是 \(m n^{m-1}\)

然后是对别人。对别人产生贡献,还要枚举一下在哪个时刻产生的贡献。即我们要计算 \(\sum w_{i,j,t}\)。其中 \(w_{i,j,t}\) 表示 \(i\)\(j\)\(t\) 时刻产生贡献的方案数。假设他们之间共有 \(d\) 个点。

则其为 \(\sum_\limits c \binom{t-1}{cd} (n-d)^{t-1-cd} n^{m-t} \frac{(cd)!}{(c!)^d}\)。注意到这个东西只跟 \(d\)\(t\) 有关。因此可以预处理数组 \(val_{d,t}\) 解决。

然后还可以给 \(val_{d,t}\) 滚一个前缀和。复杂度不小。

是不是偏了啊?好怪。


没偏,纯菜。整理一下答案就是。

\[Ans = n^{m-1} \sum_{d=1}^n V_d \sum_{c=0}^{m-1} \frac{(cd)!}{(c!)^d(n-d)^{cd}} \sum_{t=0}^{m-1} \binom{t}{cd} (\frac{n-d}{n})^t \]

所以实际上就是求解:

\[f_{cd,d} = \sum_{t=0}^{m-1} \binom{t}{cd} (\frac{n-d}{n})^t \\ \]

巧妙之处是把 \(cd\) 看成一个整体。因为我们不关心 \(c\) 的值,于是直接用 \(cd\) 的值找递推式。我格局小了。

\[f_{cd,d} = \sum_{t=0}^{m-1} \binom{t-1}{cd-1} (\frac{n-d}{n})^t + \sum_{t=0}^{m-1} \binom{t-1}{cd} (\frac{n-d}{n})^t \\ f_{cd,d} = \frac{n-d}{n} (f_{cd-1,d} + f_{cd , d} - \binom{m-1}{cd}(\frac{n-d}{n})^{m-1} - \binom{m-1}{cd-1}(\frac{n-d}{n})^{m-1}) \\ f_{cd,d} = \frac{n-d}{d}(f_{cd-1,d} - (\frac{n-d}{n})^{m-1} \binom{m}{cd}) \]

「NOI2011」 兔兔与蛋蛋游戏

很有二分图的特征。

就是说,空格子在偶数点的时候只能与奇数点换。那么就有空格子与一个棋子交换后就再也不会有机会与其交换。于是左部点只保留黑棋,右部点只保留白棋。那么操作本质上就是走路径,不经过重复点。不能走的败。

然后就是二分图博弈板子题。

「BJOI2018」二进制

一个二进制数是三的倍数需要满足什么条件捏?

重排后是三的倍数对 01 数量有什么要求?有偶数个 1 反正一定可以变成 3 的倍数。

如果只有一个 1 就飞了,否则奇数个 1 还需要两个 0 帮忙。至少有两个 0 很不好处理。

不如容斥,减去那些有不超过一个 0 的子区间。

那就是直接划分段。全 1 的,经过特定 0 的。什么简单题。

但好难写,好难写。

「NOI2012」骑行川藏

先把每段路的速度设定为风速。则此时消耗的能量为 \(0\)

考虑微元法,现在,我们需要花费能量按性价比大小提升每段路的速度。那么不断如此操作,每段路的性价比会是一样的。即 \(\frac{\Delta T_i}{\Delta E_i} = C\) 。其中 \(C\) 是一个常数。

那么二分一个最小的 \(C\),使得且能量不超限。

\[-\frac{s_i}{2k_is_iv^3-2k_is_iv_i’v^2} = C \\ 2Ck_iv^3-2Ck_iv_i'v^2+s_i = 0 \]

因为 \(v > v'_i\) ,所以该函数在 \((v_i' , \inf)\) 单调递减,二分解方程即可。

AGC062A Right Side Character

好难。卡了好久,这就是 AGC 吗。呜呜呜。

观察操作,发现每次删除的都是开头的数。

如果最后一个连续段是 A ,则一次操作后最后一个连续段仍然是 A,因为这个连续段前面如果没有 B 则显然,否则那个 B 一定会让这一段最靠前的那个 A 挪到最后,所以此时答案是 A

如果一段 A 前面有 B,则这一段 A 最开头那个一定会在一次操作后留在后面,而这一段 A 后面如果有 B 则这一段 A 还会把一个 B 带到前面去,则那个最开头的 A 前面的 B 的个数不会减少,除非他到了最后一个位置,而如果它到了最后一个位置则答案已经确定。

所以判断是否全 A 或者是否存在一个前面有 BA 即可。

AGC062B Split and Insert

被打烂了,被打烂了,被打烂了。

记住正难则反,记住正难则反,记住正难则反。

正向操作方式限制太死了,进行操作的时候会巨抽象,想破防了。 Para 让我逆向考虑。

反向操作限制没那么死,相当于每次把一个子序列拖到最后面去。那么最基本的排序方法就是将整个序列划分成若干个值域连续的极长子序列,然后每次拖一些到后面去,显然我们每次肯定把整个值域连续极长子序列拉到后面去。实际上,我们可以多线程操作,一次性把多个子序列拉到后面去,拉到后面去的目的是拼出值域更长的子序列,那么以值域为基础进行区间 dp

具体地,我们可以记录 \(g_{i,j,w}\)。表示用前 \(w\) 次操作拼出值域在 \([i,j]\) 的极长子序列,至少需要多少花费。做完了。

AGC062C Mex of Subset Sum

乱搞!乱搞!乱搞!

先排序,定义 \(S_i\) 表示前 \(i\) 个数的前缀和。我们记录 \(f_i\) 表示只考虑前 \(i\) 个数有哪些数是不能被拼出来的,存下来。

然后从 \(i\) 转移到 \(i +1\)。检查加上 \(A_{i+1}\) 后那些能被拼出来的数还能不能被拼出来。

然后 \(A_{i}\) 加上 \(f_i\) 中的数很可能也是拼不出来的,我们实际上此时已经在 \(f_{i+1}\) 中存储了不超过 \(S_i\) 的用前 \(i + 1\) 个数拼不出来的数,所以我们只用存下那些超过了 \(S_i\)\(A_i\) 加上 \(f_i\) 的数。

此外,如果 \(S_i < A_{i+1}\) 还要给 \(f_i\) 扩一波容。另外,\(f_i\) 中的 \(< A_{i+1}\) 的数都是可以加入答案的,直接加就好了,如果答案集合够大了就直接结束程序(因为我们是在从小到大找)。

不妨分析一下复杂度。

  • 如果 \(S_i < A_{i+1}\),则 \(|f_i| \leq k\) ,复杂度显然正确。
  • 如果 \(S_i \geq A_{i+1}\),只有 \((S_i - A_{i+1} , S_i]\)\(f_i\) 集合的数会被重新加入集合。我们不妨来讨论这个集合元素的多少。分析不来,滚了。

「20230523 模拟赛」 最大异或和

被打爆了。

注意到这个线性基可以直接差分一下,那么操作就变成了单点异或,区间清空。

单点异或可以看做先删再加。清空直接看做删。

写一个带删除线性基就做完了。呜呜呜。

「20230523 模拟赛」上帝之手

几乎没有怎么想。不妨再想一想。

考虑 \(O(n^2)\) 的算法。即快速求解 \(x_b\)。那么实际上就是后缀 \(d\) 的和加上终止 \(l_i\) 的和的最小值。

从后往前扫一遍即可。

然后考虑 \(1\) 操作。询问是求解第 \(k\) 大的 \(x_b\)

因为不断增加,到后面很快会超限。我们可以先预处理一下,每个位置从上一个位置超限转移过来,走多少步会超限。那么容易发现,随着起始点位置的左移,\(x_b\) 并不增加。所以答案位置是容易确定的。

考虑操作 \(2\)。考虑每个位置的 \(x_b\) 的值。有两部分构成,一部分是当前位置全程不被限制的情况,一部分是后缀最小值,这两个东西取个最小值就是当前位置 \(x_b\)。注意到前者单调不增,后者单调不降。那么他们的交点就一定是最大值。所以我们二分一下就好。

考虑操作 \(3\),相当于求严格后缀最小值的个数。因为如果不是严格后缀最小值就会被后面的数限制住而产生重复答案。这个线段树二分算一下就好了。

「THUPC2021 初赛」狗蛋和二五仔

甚至!我把所有信息存下来状态数都相当小。

然后我就存下来瞎转移一下就做完了。

飞了。调吐了。卡常卡常卡你妈的常。

精神胜利了。

「THUPC2021 初赛」方格游戏

题目保证了矩形在列和行的投影都是不交的。

如果没有障碍我会怎么做?行列分开算。

奶奶滴!不仅不交,而且投影不能贴贴!

那绕路只会是因为单一矩形的影响,所以随便做。行和列分开算即可。

「THUPC2023 初赛」喵了个喵 II

完全相等的两个子序列啊!完全相等。

令第一个数属于第一组,考虑第二个数。如果两个数不同,则第二个数一定属于第一组。一直找到第一个能和第一个数匹配上的。那么这就是我们的决策点。若该点属于第一组,则后面两个同种数需要属于第二组。即每种数最重要的就是第二个的归属,因为我们可以钦定第一组的元素数量任意时刻不少于第二组。那么第二个元素归属确定,该种元素剩下的归属也确定,现在我们让其合法化。其实第三个元素的归属与其是等价对应的,所以也可以从第三个的角度去考虑。


来不起了。草。

还是基于两种划分方式,我们对每种数的两种划分方式进行建图。

要求是任意两个区间不能有交点。

然后主席树建图即可。

「模拟赛20230525」 fantasy

这场模拟赛除了这道都是好题。当然,如果这道题出现了理论复杂度正确的做法我就收回这句话。

野蛮做,直接对于每个给定字符串拉出每一个后缀作为状态。

然后对于每个长度,考虑两两之间转移到的方法,要么是直接转移到。要么是首字符相同,除去首字母检查更短的两个状态的最小操作次数。

然后每一次都跑一边 Floyd 即可。数据很离谱。状态去一下重就可以过。

「模拟赛20230525」「CEOI2021」tortoise

好题。但没有很多结论,反而是很多技巧经验性的东西,暴力 dp 恐怕和正解没有太多的结论差异。

我们假定在负无穷和正无穷处各有一个空地。

改变一下限制,改成每个商店只能在不晚于某个时间点的时刻买糖。

考虑一个连续商店段。我们对于每一个有糖的商店先算出里它最近的空地。

考虑在商店买糖会在哪里卸货。如果在最近空地在左边的商店买糖就会反复折返买糖放糖。

我们在某一次领了糖之后,可以不再折返去左边的空地,相反地,我们可以直接去右边的空地放糖,那么可以使得我们存在一次买糖发糖是不会花费任何额外贡献得到的。于是我们想要这样的一次买发糖能够替换掉一个花费时间最多的买发糖,即我们需要确定这个糖该在哪里买。

容易发现,对于最近游乐场是左边的商店,我们处理掉一块糖相当于是花费从商店到左边空地一次往返的时间。对于最近空地是右边的商店,我们处理掉一块糖相当于是从右边空地到商店一次往返花费的时间。

由此发现,那个白嫖的糖应该从离最近空地最远的那个商店去拿。

接下来我们需要考虑从每个商店买多少个糖。这里考虑反悔贪心。

考虑我们到达每个商店时,最多可以有多少时间用于额外的往返花费的时间。我们先假定不断往返把商店买空。然后每次删除往返一次花费时间最多的糖直到在限制之内。

这里要注意一些实现上的细节。就是说就算龟兔同时到达商店,兔还是能买糖,实现上需要加上一些额外费用使得它能够成功买了一些糖。

「模拟赛20230525」 dl

好题,但放 OI 考场怪怪的。

考虑极长联通不着火的段。

大小 \(>\sqrt{n}\) 只有不超过 \(\sqrt{n}\) 个。 大小不超过 \(\sqrt{n}\)\(\sqrt{n}\) 步后会消失,着火块是一步一步加进来的,暴力删除复杂度与前面相同,分裂块显然不影响复杂度。这么一分析就会发现,我们每次操作后暴力遍历每一个不着火段的复杂度对飞了!

于是拿链表存一下不着火段。写一个 \(O(\sqrt{n})\) 查询区间和,\(O(1)\) 查单点的分块就好了。

厉害,有启发,但不适合 OI

「PA2019」Podatki drogowe

注意到 \(n \le 2.5 \times 10^4\),但时限 5s。很奇怪的范围,大胆猜想,一个纯正的 \(O(n^2)\) 的做法足以通过此题。

不妨先考察最高位小于 \(t\) 的路径有多少条。通过并查集加边我们很容易算出答案的最高位是多少。

哈哈!暴力背包复杂度很对!我对每种边权做一次背包就行了。假了。


随机二分。每次随机找到一条在权值区间内的路径作为 mid

然后点分治,主席树维护路径权并应用 hash 比较大小。

每次 check 一下就好了。但是卡常。

「2021 集训队互测 Round 12」蜘蛛爬树

由于每个树的平移边是一样长的。所以一旦开始平移那就一定平移到指定树才停止。

所以每个询问可以使用 \((u,v,d)\) 三个量来描述,其中 \(d\) 是平移次数。

跟举办陈亮州那题很像。直接把询问使用树剖拆分成若干部分。

LCA 处,可以直接李超树加点分治离线计算。

路径上可以通过重链剖分拆分成询问子树和一段重链的轻儿子两部分。

询问子树离线下来算。询问一段重链则可以对于每条重链分治计算。

CF1817F Entangled Substrings

牛宝教我学基本子串!

我们可以直接枚举串 acb ,设其在基本子串的位置 \((l_0,r_0)\),那么 \(a\) 的坐标 \((l_0,r)\)\(b\) 的坐标是 \((l,r_0)\)

那么有 \(r_a \leq r < l \leq l_b\)。则答案为 \(\sum\limits_{l=r_a}^{l_b} l - r_a = \frac{(l_b - r_a)(l_b-r_a+1)}{2}\)。那么我们可以对每一个等价类做一遍双指针,维护前缀行的 \(\sum l_b^2,\sum l_b,\sum 1\)。所以可以 \(O(n)\) 直接做。

「20230527 模拟赛」 划分

简单题。直接分治然后区间合并跑 NTT 即可。

「20230527 模拟赛」 基因

根据题解。对于叶子贡献不乘以 \(2\) 的限制,我们使用容斥去处理。乘以 \(2\) 的限制可以看作染色。

具体地,我们期望去减去存在叶子是黑色的方案数。然后枚举黑色叶子集合容斥即可。

所以现在的瓶颈就是如何算出含有一个点集的基环树的数量即可。善用子集容斥递推即可。

详情看官方题解。

「ULR #1」打击复读

实际上是基本子串板子题!

建出来,然后算出答案关于 \(wl\) 的线性关系即可。

「2018 集训队互测」Fim4

不会做,去赏析代码。首先有一个 \(\frac{n^2}{w}+n2^w\) 做法的,很好理解,处理下 AC 自动机每个节点向后跳 \(w\) 步会到那个点,因为字符集大小为 \(2\) ,所以有 \(2^w\) 种跳法。

但好像还有个根号的,而且跟字符集大小无关,继续看看。

他先把所有的串都插入了 AC 自动机 。然后对长度大于 \(\sqrt{\sum |s_i|}\)\(s_i\) 进行一些预处理。

然后找到每个节点往后匹配一个 \(s_i\) 后会到哪个节点。那么我们就可以解决询问在 \(< \sqrt{n}\) 的段匹配的答案。

然后我们再一块儿处理在 \(> \sqrt{n}\) 的块匹配的答案。我们把每种块的起始匹配位置存下来,如果只有 \(< \sqrt{n}\) 种则可以暴力匹配,复杂度完全正确。

如果有 \(> \sqrt{n}\) 种,我看不明白了。麻。

CF1837F Editorial for Two

有一个 \(O(n \log^2 n)\) 的做法。就是直接二分答案,然后对于每个前后缀检查最多可以选择多少个数使得其不超过限制,看一下能否限制到 \(k\) 即可。但好像被卡了。但卡过去了。

哦,把堆换成链表就可以了。至于怎么插入,每个元素维护一个在他之前的元素中第一个比他大的和第一个比他小的。对于维护已选择元素的那个堆,我们可以把当前元素插入到那个比他小的元素之后,因为当前元素都需要插入,那比他小的更需要。同理,维护未选择的那个堆可以把当前元素插入到那个比他大的元素之前,因为当前元素都存在,那么更大一定更存在。

做完了。

「20230530 模拟赛」 解码

巨多细节!对于每个位置计算什么时刻被确定。

具体地就是枚举一个最长循环前缀,还要比较这个时间与发生可观察的进位现象谁早最后确定答案。

「20230530 模拟赛」 图

构造,一生之敌。

对于二分图,我们先抽出一个生成树。期望树根染成 0 ,除了树根都可以染成我们想要的样子。考虑树根怎么办,我们只用把他的两个儿子的边同时 +1 即可。所以选择树根的时候我们要选择度数大于 \(2\) 的。

对于三部图。我们也只用抽出一个生成树,把非树根染成他给我们划分的样子。然后找到一个奇环,把根定在奇环上,然后将环交替 +1-1,则根的值会 +2,而别的位置会不变。做完了。

「20230530 模拟赛」 表达式

问题明显不弱于 2-sat 问题。我们先建一个 2-sat 的图出来。然后缩点。

发现,要求每个 A ,它的两个点不能到达任意一个别的 A 拆出来的点。这个好处理,在 DAG 的反图上 dfs 一下就是。然后 2-sat 还有一个性质就是 \(\overline{A} \rightarrow B\)\(\overline B \rightarrow A\)。所以在判断一个点能否同时到达别的点对的时候实际上与上面的情况包含了。直接判就是了。

「DROI」Round 2 进制与操作

单次询问,思路就是从高到低枚举位,当众数大于一半的时候我们才选,否则操作数不会减小。贪心选就好。

然后考虑随机化,每次枚举变成某个数的前缀。因为这个答案前缀是唯一确定的,我们随机的时候直接检查其能否将我们当前的答案扩展。复杂度 \(O(mk \log^2 v + m \log^3 v)\)

稳稳可以通过。

「SDOI 2013」 淘金

首先可以发现 \(f(i) < i\)。那么相当于是坐标压缩了。

我们尝试去计算一个特定坐标上面有多少金子。这个可以递推。

可以感受到,有用的 \(f(i)\) 数量很少很少。因为它只能包含质因子 \(2\)\(3\)\(5\)\(7\)

即一共远小于 \(280800\) 个有用的 \(f(i)\)。把这些 \(f(i)\) 拉出来,做一个数位 dp

然后再把这些数值从大到小排序,维护一个优先队列算答案即可。

「ZJOI 2019」 语言

对于每个点算一个包含它的路径组成的连通块大小。

那么就是这些路径端点组成的生成树大小。

考虑树上差分直接维护生成树大小,与建虚树类似,按 dfs 序排序,然后用深度算贡献。

线段树合并+树上差分可以解决。

「ZJOI 2019」 浙江省选

对于每个人考虑,我们排除掉完全压制和被完全压制的人。

检查其有无进入前 \(m'\) 的可能性。其实就是快速找到其左右两边最紧的各 \(m\) 个限制。最多不满足 \(m\) 个有无可能。

李超树可以算每个人能否是最厉害的,但不能算前 \(m\) 厉害的。好糟糕。

但是,我们可以把可以成为第一的那些直线给删除,然后找到他对剩下的直线在哪个区间有统治力。

这个可以用李超树求凸包然后二分完成。然后就可以继续计算下去。只用做 \(m\) 次类似的步骤即可。

悲,这个凸壳不能用李超树求。但可以直接求。呃呃。

注意的是,我们第 \(i\) 次要恰好找排名最少时为 \(i\) 的人,这样才能够保证正确性。