背单词

给你个字符串,你需要将他们按照某种方式排序。排序后,第个字符串的权值定义为:

  1. 如果存在使得的后缀,则权值为
  2. 否则,如果个字符串中不存在)使得的后缀,那么权值为
  3. 否则,求出最大的使得的后缀。那么权值为

一种排序方案的权值是所有字符串的权值之和。

要求你最小化排序方案的权值并输出。

Trie DFS 贪心 交换法

首先把所有字符串倒过来,后缀变前缀。

容易使用交换法证明,一定不存在第一种情况的权值。即,我们会把一个串的前缀排在它前面。

个串建 Trie,然后把关键点拿出来再建一棵有根树。那么排序方案就是这棵树的拓扑序。而且容易发现,一个串的权值就是它和它的父节点在拓扑序上的距离。现在我们要最小化这个距离。

考虑子树拓扑序合并。仍然使用交换法可以证明,我们把子树按大小排序,按从大到小的顺序把拓扑序拼起来即可。时间复杂度

代码

幸运数字

给出一棵个点带点权的树,次询问,求路径上点权集合中的子集异或和的最大值(即任意选元素异或起来的最大值)。

线性基 倍增

容易想到线性基。线性基的合并是的。考虑倍增(因为树剖 + 线段树更慢),则一次询问的复杂度。总复杂度

代码

萌萌哒

给出一个长度为的大数表示数的最高位。有个限制条件),表示。问满足条件的数有多少个。

倍增 并查集

这是一道倍增思想的好题。

定义表示。那么对于一个限制条件,我们可以将其拆分成对形如的条件。那么我们直接用并查集把并起来。

另一方面,如果,则。因此我们可以枚举,如果它不是代表元,那么我们找到它的代表元,然后把两者的两个儿子对应着合并。我们从大到小枚举,最后就可以得到单个元素之间的相等关系,那么就很容易计算答案了。

并查集有个,总大小是的,因此复杂度

代码

美味

给出一个长度为的整数序列,有次询问形如,求

权值线段树 扫描线

考虑怎么做。我们可以将权值排序。每次查询,我们从高到底枚举每一位,看答案的这一位能不能是。那么我们可选的数的区间就会不断缩小,到最后只剩下单独的数,就是答案。

考虑怎么做。相当于,我们的区间往左平移了个单位。和上一个问题没啥区别。

考虑原问题。把询问离线,按照右端点分类。每次我们加入一个数,处理的询问。这时我们就需要判断,中是否存在某个数,位于值域区间中。考虑建立权值线段树。那么我们的问题就转化为,是否在值域区间中是否存在某个下标在中。由于当前加入的下标是的,那么我们直接求出下标最大值即可。

时间复杂度

代码

妖怪

给出个函数。设。求最小值。

三分 调参 凸包

是一个凸的函数。三分即可。时间复杂度。然而要调参,显然不是正解。

。考虑一条斜率为且过的直线,容易发现这条直线的纵截距是,横截距是。换言之表示的就是的横纵截距之和。

那么我们枚举斜率。则使得最大的一定是上凸壳上的点。因此我们求出个点的凸壳。考虑凸壳上编号为的点,那么为最大值的就是一段区间。这时我们要求的就是这个区间里的最小值。可以简单地使用均值不等式求解。

时间复杂度

三分代码

围棋

给出一个的网格,每个格子可以填WBX三种字符。给定次询问。

每次询问给出一个的网格,每个格子是WBX三种字符。问在所有种方案里,有多少种方案包含了这个的网格(出现过)。

轮廓线 DP

我们可以把的网格当成两个字符串。不妨考虑计算不合法的方案数。

考虑轮廓线 DP。设表示当前的格子是,且匹配到第一个串的位置是(即上的字符匹配第一个串长度为的前缀),匹配到第二个串的位置是是轮廓线的二进制状态,表示轮廓线上的这个格子是否能匹配第一个串。

当我们从转移到的时候,我们枚举上面填的字符。然后就可以使用 KMP 求出新的。如果能匹配第一个串,而,相当于出现了一个的网格,这种转移就不能进行。其他情况都可以转移。在求出了新的后,从转移到即可。

转移到比较简单。

代码