IOI 2021 国家集训队作业:试题泛做记录

广告位,宣传水题 https://ioihw20.duck-ac.cn/problem/301

截至 \(\text{2020.12.7}\),已完成 \(81/150\)(看题解的算不清楚就不写了)

\(\rule[0pt]{14.3cm}{0.1em}\)

#\(173\)\(\text{Equal Numbers}\)\(\text{2020.10.12}\),自己做出)

题目大意:

给定正整数可重集 \(a_{1\ldots n}\),一次操作定义为:选择 \(i\in [1,n]\),令 \(a_i\) 乘上一个任意的正整数,对于所有 \(k\in [0,n]\),求出 \(k\) 次操作后可重集中至少有多少种不同的数。

\(n\leq 3\times 10^5,\ \ a_i\leq 10^6\)


题解:

如果一次操作后 \(a_i\) 没有变成原始集合中的某个数,那么显然我们可以令它变为原始集合中所有数的公倍数 \(S\),这样以后其他数也可以变成这个公倍数,这一定不劣于变成其他数。

于是我们有两种选择:

  1. 将某些数变成 \(S\),那么我们自然是选择出现次数最少的若干个数,将它们统一变成 \(S\)

  2. 不将任何数变成 \(S\),那么我们只能对那些存在一个真倍数在原始集合中的数进行操作,选择它们中出现次数最少的若干个数变成它们的某个倍数。

所以我们通过两个数组记录所有出现过的数的出现次数和作为其他数真因子出现的数的出现次数(直接利用倍数枚举可以找出这些数),当 \(k\)\(0\) 变到 \(n\) 时对每个数组维护一个指针表示当前的 \(k\) 足以将多少个数全部操作一遍。

时间复杂度为 \(O(A\log A+n)\),其中 \(A\) 为值域大小。

\(\rule[0pt]{14.3cm}{0.1em}\)

#\(177\)\(\text{Outer space invaders}\)\(\text{2020.10.12}\),瞄了眼题解)

题目大意:

\(n\) 个外星人,第 \(i\) 个外星人有权值 \(d_i\),需要在 \([a_i,b_i]\) 中某个时间被消灭,一次功率为 \(P\) 的攻击只能消灭权值不超过 \(P\) 的外星人,问消灭所有外星人的最小功率总和。

共询问 \(T\) 组数据。

\(T,n\leq 300,\ \ a_i,b_i,d_i\leq 10^4,\ \ \sum n^3\leq 2.5\times 10^8\)


题解:

查这题的时候顺便看到了正解用到了区间 DP,之后就不难想了。

\(dp(i,j)\) 表示消灭所有包含于 \([i,j]\) 的外星人的最小功率,我们找到这些外星人中权值最大的,枚举消灭它的时间 \(t\),那么与此同时所有包含 \(t\) 的外星人也会被同时消灭,只要分别递归计算 \(dp(i,t-1)\)\(dp(t+1,j)\) 即可。

注意区间要先离散化。

时间复杂度为 \(O(\sum n^3)\)

\(\rule[0pt]{14.3cm}{0.1em}\)

#\(209\)\(\text{Intrinsic Interval}\)\(\text{2020.10.12}\),模拟赛原题)

题目大意:

给定 \(1,\ldots,n\) 的排列 \(\pi_{1\ldots n}\),定义区间 \([l,r]\) 为连续段当且仅当排列中 \([l,r]\) 当中所有数排序后是公差为 \(1\) 的等差数列,现有 \(m\) 组询问,每次询问包含 \([l,r]\) 的最短连续段,可以证明这是唯一的。

\(n,m\leq 10^5\)


题解:

是原题,直接搬运我以前写的题解了。

结论 1:设 \(ans(l,r)\) 表示询问区间 \([l,r]\) 的答案,则 \(ans(l,r)=\bigcup\limits_{i=l}^{r-1}ans(i,i+1)\)

注意要特判 \(l=r\)

这个结论不证了,因为可以脑补,而且证起来又有点麻烦。

所以我们求出 \(ans(i,i+1)\) 即可。

结论 2:设 \(L_i,R_i\) 分别表示以 \(i\) 为右/左端点的连续区间的最远左/右端点,则 \(ans(i,i+1)=[\max(j|j\leq i,L_j\ge i+1),\min(j|j\ge i+1,R_j\leq i)]\)

道理和结论 1 差不多,也不证了。

于是问题又转化为求 \(L_i,R_i\),求完以后上面那个东西二分一下 \(j\),用 ST 表判定即可。

这个东西就要上线段树了,从左到右扫一遍 \(r\),对于每一个 \(r\),计算最左边的 \(l\),即为 \(L_r\),再反着做一遍,可以类似得到 \(R_l\),这里只讲前面一个了。

考虑 \([l,r]\) 是连续区间,等价于 \((\max(p_i|i\in [l,r])-\min(p_i|i\in [l,r]))-(r-l)=0\),当 \(r\) 固定时它是关于 \(l\) 的函数,设为 \(f(l)\),用线段树维护 \(f(l)\),考虑从 \(r\) 变成 \(r+1\)\(f(l)\) 的变化。

考虑每一项的变化即可,\(r\) 对于每个 \(f(l)\) 来说都增加了 \(1\),所以先将整个左边区间加 \(1\)

\(\max\)\(\min\) 类似,这里以 \(\max\) 为例。

用一个单调栈维护递减当前 \(p_i\),则如果 \(p_{r+1}>p_{top}\),那么要弹栈,并且 \(p_{top}\)\(p_{top}\) 前一个元素 \(+1\) 这一段的最大值变成了 \(p_{r+1}\),原本这一段的最大值是 \(p_{top}\),所以相当于整体加上一个 \(p_{r+1}-p_{top}\)

有很多对称的东西,类似处理即可。

时间复杂度 \(O(n\log n+m)\)

\(\rule[0pt]{14.3cm}{0.1em}\)

#\(297\)\(\text{Surveillance}\)\(\text{2020.10.13}\),自己做出)

题目大意:

给定若干环上区间,选择最少的区间覆盖整个环,或报告无解。

环长为 \(n\),区间数为 \(k\)

\(n,k\leq 10^6\)


题解:

国旗计划弱化版。

首先复制为两倍破环为链,然后直接倍增,令 \(f(i,j)\) 表示从 \(i\) 开始覆盖 \(2^j\) 个区间最右能到多少,其中 \(f(i,0)\) 可以从左到右扫一遍,求左端点在 \([1,i]\) 的区间右端点的最大值。

然后从每个左端点倍增跳一下就可以了。

时间复杂度为 \(O((n+k)\log n)\)

\(\rule[0pt]{14.3cm}{0.1em}\)

#\(238\)\(\text{Kebab House}\)\(\text{2020.10.13}\),自己做出)

题目大意:

你要依次制作 \(n\) 个烤肉串,第 \(i\) 个会花费 \(q_i\) 的时间,每个单位时间你可以走神或不走神,但两次相邻走神必须间隔大于 \(t\) 单位时间,烤第 \(i\) 个串的时候至少有 \(x_i\) 个单位时间没有走神,问走神的方案数,对 \(10^9+7\) 取模。

\(n\leq 1000,\ \ k\leq 100,\ \ q_i\leq 250\)


题解:

\(dp(i,j)\) 表示烤完前 \(i\) 个串,最后一次走神是第 \(i\) 串烤完前的倒数第 \(j\) 单位时间的方案数,特别地,\(dp(i,t)\) 表示最后 \(t\) 单位时间内都没有走神的方案数。

那么枚举一个 \(k\),从 \(dp(i-1,k)\) 转移到 \(dp(i,j)\),转移系数应当是对于第 \(i\) 个串中间的某个区间,走神次数不超过 \(q_i-x_i-1\)(或一些类似的东西)的方案数。

所以我们再来一次 DP,设 \(f(i,j,k)\) 表示长为 \(i\) 的区间,走神 \(j\) 次,最后一次走神是倒数第 \(k\) 单位时间(对于 \(k=t\) 同样特殊定义),如果 \(0<k<t\) 那么就是 \(f(i-1,j,k-1)\),否则枚举一下上次走神是什么时候。

时间复杂度为 \(O(nt^2+Q^2t)\),其中 \(Q\)\(q_i\) 的值域。

\(\rule[0pt]{14.3cm}{0.1em}\)

#\(123\)\(\text{Gem Island}\)\(\text{2020.10.13}\),看了题解)

题目大意:

岛上有 \(n\) 个居民,每个居民初始有一个宝石,每一天都会等概率选择一个宝石分裂成两个,问 \(d\) 天后宝石数量前 \(r\) 多的人的宝石数量和期望是多少。

\(n,d,r\leq 500\)


题解:

题目中这个分配方式,相当于将 \(d\) 个宝石分给 \(n\) 个人,最后每人多给一个。

我们设 \(f(i,j),g(i,j)\) 分别表示 \(j\) 个宝石分给 \(i\) 个人时,人带标号的方案数和前 \(r\) 大值之和,那么答案就是 \(\dfrac{g(n,d)}{f(n,d)}+r\)(最后加上每个人多给的一个宝石)。

枚举有多少人得到了至少一个宝石,可以得到转移方程:

\[f(i,j)=\sum\limits_{k=0}^{\min(i,j)} \binom i kf(k,j-k) \]

表示有 \(k\) 个人得到宝石,每人先分一个,剩余 \(j-k\) 个再递归计算。

同理有 \(g(i,j)\) 的转移:

\[g(i,j)=\sum\limits_{k=0}^{\min(i,j)} \binom i k(g(k,j-k)+\min(k,r)f(k,j-k)) \]

后面一项指的是每个人先分得的一个宝石的贡献。

利用 \(\text{long double}\) 计算,我也不知道为什么精度怎么算,反正过了。

时间复杂度为 \(O(n^3)\)

\(\rule[0pt]{14.3cm}{0.1em}\)

#\(121\)\(\text{Bipartite Blanket}\)\(\text{2020.10.14}\),自己做出)

题目大意:

给定左边 \(n\) 个点右边 \(m\) 个点的点带权二分图,求满足下列条件的点集数量:

  • 点权和不小于 \(t\)

  • 是某个匹配的子集。

\(n,m\leq 20,\ \ t\leq 4\times 10^8\)


题解:

主要结论:设左右部点分别为 \(L,R\),那么 \(S=A\cup B\ \ (A\subseteq L,\ B\subseteq R)\) 是某个匹配的子集当且仅当 \(A\) 是某个匹配的子集且 \(B\) 是某个匹配的子集。

具体证明可以把 \(A,B\) 所属的匹配画出来,在里面找增广路来证明,不过这个属于比较直觉的东西,就不具体说了。

我们只需要求出左右两部所有是某个匹配子集的点集求出来,再双指针一下就可以得到答案。

询问一个点集 \(S\) 是不是某个匹配的子集,相当于在它这一部只保留 \(S\) 时最大匹配为 \(|S|\),可以简单地利用 Hall 定理判定。

首先求出 \(f(S)\) 表示 \(|\bigcup\limits_{i\in S}N(i)|\ge|S|\) 是否成立,然后对它做一次 FWT 就可以得到每个点集是不是一个匹配的子集。

时间复杂度为 \(O(n2^n+m2^m)\)

\(\rule[0pt]{14.3cm}{0.1em}\)

#\(293\)\(\text{Weather Report}\)\(\text{2020.10.14}\),自己做出)

题目大意:

对接下来 \(n\) 天进行天气预报,每天的天气有四种可能,每种天气出现概率给定且不随天数变化。

现在要将 \(4^n\) 种可能的天气序列分别映射到一个 \(01\) 串,使得不存在两个映射得到的 \(01\) 串为前缀关系,求 \(01\) 串的最小期望长度。

\(n\leq 20\)


题解:

对于所有可能的天气序列对应的概率求一次 Huffman 树即可。

天气序列的数量有 \(4^n\) 种,无法一一处理,但是注意到一种天气序列出现的概率只和每种天气出现次数有关,所以不同的概率只有 \(\binom {n+3}{3}\) 种。

于是问题转化成了有 \(m\) 种元素,第 \(i\) 种有 \(a_i\) 个的 Huffman 树,只需要在优先队列的每个元素维护一个重复数 \(a_i\),对于取出的堆顶,如果重复数 \(a_i\) 超过了 \(1\),那么先两两配对为 \(\lfloor\dfrac{a_i}{2}\rfloor\) 对,若多出一个则将其与堆中的下一个元素匹配。

时间复杂度不知道,但过了。

\(\rule[0pt]{14.3cm}{0.1em}\)

#\(146\)\(\text{Tile Cutting}\)\(\text{2020.10.15}\),自己做出)

题目大意:

在一个长宽为任意正整数的矩形上的四条边各选一个整点,顺次连接然后切割下来形成一个平行四边形,设面积为 \(S\) 的平行四边形有 \(c_S\) 种切割方法(旋转翻折不等价),有 \(q\) 次询问,每次询问 \(c_l,\ldots,c_r\) 的最大值和对应的 \(S\)

\(q\leq 500,\ \ l,r\leq 5\times 10^5\)


题解:

显然对边选择的顶点连线过矩形中心。

设矩形尺寸为 \(a\times b\),割出来的其中一个小三角形尺寸为 \(c\times d\),通过简单计算可以知道 \(S=ad+bc-2cd\),几何的理解就是 \(S=d(a-c)+c(b-d)\),即两个小矩形的面积和。

所以 \(c_S\) 就是将 \(S\) 分成两个数之和,每个数再分成两个数之积的方案数,那么 \(c_S=\sum\limits_{i=1}^{S-1}\sigma_0(i)\sigma_0(S-i)\),一次多项式乘法即可求出,打个表可以发现 \(c_{5\times 10^5}\) 远远不到 \(10^9\),因此单模数的 NTT 就已经足够。

最后再套个 ST 表求最大值。

时间复杂度为 \(O(L\log L+Q)\),其中 \(L\)\(l,r\) 值域。

\(\rule[0pt]{14.3cm}{0.1em}\)

#\(146\)\(\text{King’s Inspection}\)\(\text{2020.10.15}\),自己做出)

题目大意:

\(n\) 个点 \(n+k\) 条边的有向图中求解一条哈密尔顿回路,或报告无解。

\(n\leq 10^5,\ \ k\leq 20\)


题解:

设点 \(i\) 的入度为 \(in_i\),那么 \(\sum\limits_{i=1}^n in_i=n+k\),如果存在 \(in_i=0\) 那么显然无解,否则 \(in_i\ge 1\),那么至多有 \(k\) 个点满足 \(in_i>1\)

对于 \(in_i=1\) 的点,前驱确定,可以直接缩掉,只保留 \(in_i>1\) 的点,每个点的出边缩成从它出发不断走到 \(in_i=1\) 的点,这条链末尾的那个点的出边。

在新图上状压 DP,每个点记录前驱以输出方案。

时间复杂度为 \(O(n+2^k)\)

\(\rule[0pt]{14.3cm}{0.1em}\)

#\(294\)\(\text{Gangsters in Central City}\)\(\text{2020.10.15}\),自己做出)

题目大意:

给定 \(n\) 个点的根结点为 \(1\) 的有根树,接下来发生 \(q\) 个操作,每个操作形如有一个叶结点被敌人占领或有一个叶结点不再被敌人占领。

你需要选择一些树边切断,使得根结点到所有被敌人占领的点不连通,最小化割去的边数,同时在最小化割去边数的情况下最小化未被敌人占领但与根结点不连通的叶结点数量。

每次操作后你需要输出最小割去边数和最小的未被敌人占领但与根结点不连通的叶结点数量。

\(n,q\leq 10^5\)


题解:

前一问的答案是显然的,根结点的每个子树中最多割一条边,只要看这个子树里有没有被敌人占领的点即可。

而为了使后一问的答案尽可能小,对于根结点每个存在被敌人占领的点的子树,被切断的一定是所有被占领点的 \(\text{LCA}\) 到父亲的边。

一些点的 \(\text{LCA}\) 等于其中 DFS 序最大和最小点的 \(\text{LCA}\),我们用一个 set 维护每个子树中所有点的 DFS 序,即可实现插入,删除,查询 \(\text{LCA}\)

时间复杂度为 \(O((n+q)\log n)\)

\(\rule[0pt]{14.3cm}{0.1em}\)

#\(255\)\(\text{Money for Nothing}\)\(\text{2020.10.15}\),自己做出)

题目大意:

给定 \(n\) 个红点 \((a_i,b_i)\)\(m\) 个蓝点 \((c_i,d_i)\),求 \((a_i-c_j)\times (b_i-d_j)\ \ (a_i\ge c_j,\ b_i\ge d_j)\) 的最大值。

\(n,m\leq 5\times 10^5\)


题解:

第一个单调性:如果一个红点在另一个红点左下方,那么可以扔掉。

同样的单调性:如果一个蓝点在另一个蓝点右上方,那么可以扔掉。

所以红点集合和蓝点集合分别可以化简成一个 \(y\) 坐标随 \(x\) 坐标增加而单调减的点集,设红点对应的此集合从左到右为 \(c_1,\ldots,c_s\),蓝点对应的此集合从左到右为 \(d_1,\ldots,d_t\)

第二个单调性:对于每个红点 \(i\),设 \(f_i\) 表示使得 \((a_i-c_j)\times (b_j-d_j)\) 最小的 \(j\),那么 \(f_i\)\(i\) 单调不下降。

为证明这个结论,我们可以先证明一个基本结论:如果 \(x<y,\ \ u<v\),且 \((a_x-c_v)\times (b_x-d_v)> (a_x-c_u)\times (b_x-d_u)\),那么可以推出 \((a_y-c_v)\times (b_y-d_v)> (a_y-c_u)\times (b_y-d_u)\)

这是因为前者等价于 \(b_x(c_u-c_v)+a_x(d_u-d_v)<c_ud_u-c_vd_v\),而左边大于 \(b_y(c_u-c_v)+a_y(d_u-d_v)\),这又等价于我们要证明的的结论。

于是反复利用这个基本结论即可证明上述单调性。

所以最后用分治 DP 的处理方法做一下就可以了。

注意首先把 \(c_i\) 中所有不在任何 \(d_j\) 右上角的去掉,否则分治的时候不知道怎么缩小范围。

时间复杂度为 \(O((n+m)\log(n+m))\)

\(\rule[0pt]{14.3cm}{0.1em}\)

#\(122\)\(\text{Intellectual Property}\)\(\text{2020.10.16}\),自己做出)

题目大意:

给定 \(n\)\(9\times 9\) 数独谜题,其中某些地方没有填数,判断任意两个谜题是否本质相同,如果本质相同还需要输出转换的方法。

具体的得到等价谜题的操作包括:交换含有相同 \(3\times 3\) 方块的行或列,整体交换这样的三个行或列,交换谜题中两种数字,以及沿左上右下对角线翻转。

\(n\leq 20\)


题解:

有个显然的做法,暴搜每个数独可以操作得到的所有数独,哈希之后放到一个 map 里,查询时直接用一个数独在另一个数独的 map 里查询。

但是一个数独的等价数独有 \(2\times 6^8\times 9!\) 种,考虑减少这个个数。

首先,\(9!\) 很容易去掉,交换两种数字的操作可以放到最后进行,我们只需要设计一种对数字相对大小不敏感的哈希函数即可。

而剩下的 \(2\times 6^8\) 我们可以拆成 \(6^4\)\(2\times 6^4\),也就是放在 map 里的等价数独是只改变了行而没有改变列的,查询的时候相反,我们枚举另一个数独改变列的所有等价数独,都在 map 里查一遍,这样就可以通过本题了。

代码实现上有很多细节,比较难写。

时间复杂度为 \(O(Mn^2\log M)\),其中 \(M\)\(6^4\)

\(\rule[0pt]{14.3cm}{0.1em}\)

#\(170\)\(\text{String Theory}\)\(\text{2020.10.16}\),自己做出)

题目大意:

一个 \(k\) 级引用串的左右两端是 \(k\) 个引号,中间的部分是若干个 \(k-1\) 级引用和不包含引号的字符串的连接。

给定一个长度为 \(n\) 的引号串(给出每一段引号的个数 \(a_{1\ldots n}\)),求出它最多是几级引号串,或报告无解。

\(n,a_i\leq 100\)


题解:

首先我们将每一段引号拼在一起,变成连续 \(\sum\limits_{i=1}^n a_i\) 个引号。

接下来 DP,设 \(dp(i,l,r,k)\) 表示前 \(i\) 个引号匹配完成后,剩下左端未匹配的引号依次是 \(l,l+1,\ldots,r\) 级引号,最后的 \(k\) 是一个标记变量,值为 \(0\)\(1\),表示当前正在匹配的引号串的内部是否已经有一个一级引号(只有有了一级引号才能形成最终的引号串)。

转移大概是从 \(dp(i-l+1,l-1,r)\)\(dp(i-l,l+1,r)\) 转移到 \(dp(i,l,r)\),最后一维分一些情况讨论一下转移即可,注意只有最后才能将所有引号封口。

时间复杂度为 \(O(n^3A)\),其中 \(A\)\(a_i\) 的最大值。

\(\rule[0pt]{14.3cm}{0.1em}\)

#\(134\)\(\text{J}\)\(\text{2020.10.16}\),自己做出)

题目大意:

给定一个包含加,减,乘,平方,负号,折叠(求一个向量各分量之和)运算的包含 \(n\) 维向量和标量的长度为 \(|S|\) 的算式 \(S\)(标量加减向量时看作各分量一致的向量,向量乘法为对应分量相乘),保证次数不超过 \(10\),求值,对 \(10^9\) 取模。

对于 \(S\) 有如下约定:其中所有出现的向量只包括一个事先给定的 \(X\),标量为一个数或者 \(n\),运算优先级为从右到左,但可能有括号。

\(n,|S|\leq 10^5\)


题解:

只要求出 \(X\) 各分量的 \(k\) 次方和(\(k\leq 10\)),就可以快速求出折叠操作的值,对于其他运算其实都看成多项式的加减乘即可。

然后递归求值就做完了。

时间复杂度为 \(O((n+|S|)k)\),其中 \(k=10\) 为最大次数。

\(\rule[0pt]{14.3cm}{0.1em}\)

#\(175\)\(\text{Ice Igloos}\)\(\text{2020.10.16}\),自己做出)

题目大意:

给定 \(n\) 个圆心为坐标在 \([1,500]\) 中的整点,半径小于 \(1\) 的圆,任意两圆无公共点,接下来 \(q\) 次询问一条直线与多少圆相交(不存在相切情况)。

\(n,q\leq 10^5\)


题解:

暴力实现,如果斜率绝对值小于 \(1\) 就枚举圆心的横坐标,否则就枚举圆心的纵坐标,容易发现在这种方式下圆心的另一维坐标只会在直线的上下 \(2\) 单位范围内(可以把垂直或水平距离放成 \(\sqrt 2\))。

时间复杂度为 \(O(n+qX)\),其中 \(X\) 为坐标范围大小。

\(\rule[0pt]{14.3cm}{0.1em}\)

#\(153\)\(\text{Fygon 2.0}\)\(\text{2020.10.17}\),自己做出)

题目大意:

给定 \(m\) 层嵌套的 for 循环语句,每个循环包含循环变量和上下界,其中上下界是外层变量或 \(1\)\(n\),求关于 \(n\) 的渐进复杂度和最高次项系数(常数)。

\(m\leq 20\)


题解:

用一个 \(m\) 元组表示每一层循环变量的取值,容易发现一个 \(m\) 元组能否取到只和每个数的相对大小关系有关。

所以我们从下界到循环变量连一条有向边,从循环变量到上界连一条有向边,将强连通分量缩点,剩下的图中的点数就是复杂度(次数),而对这张图进行拓扑序计数,如果有 \(T\) 种拓扑序就有 \(T\) 种相对关系,每一种相对关系都是 \(\binom {n+m-1}{m}\)(其中 \(m\) 是复杂度次数)种,所以常数就是 \(\dfrac{T}{m!}\)

时间复杂度为 \(O(m\times 2^m)\)

\(\rule[0pt]{14.3cm}{0.1em}\)

#\(278\)\(\text{Journey from Petersburg to Moscow}\)\(\text{2020.10.17}\),看了题解)

题目大意:

给定 \(n\) 个点 \(m\) 条边的无向带权图,定义一条路径长度为前 \(k\) 长边权的和(如果边数不到 \(k\),路径长就等于边权和),求 \(1\)\(n\) 最短路。

\(n,m,k\leq 3000\)


题解:

第一种选择是最短路(这是为了计算边数可能不到 \(k\) 的情况)。

其他的选择,我们枚举哪条是第 \(k\) 大边,设其边权为 \(W\),将所有边权更大的边的边权减少 \(W\) 后求最短路(边权更小的边的边权直接设为 \(0\)),用 \(dis_n+kW\) 更新答案,可以发现这等价于只选了不小于 \(W\) 的边计算贡献。

时间复杂度为 \(O(nm\log m)\)

\(\rule[0pt]{14.3cm}{0.1em}\)

#\(147\)\(\text{Traffic Blights}\)\(\text{2020.10.17}\),模拟赛原题)

题目大意:

\(n\) 个红绿灯,第 \(i\) 个灯在位置 \(x_i\),为 \(r_i\) 秒红灯和 \(g_i\) 秒绿灯交替变换(从红灯开始),现在随机选择一个时间点从位置 \(0\) 开始以 \(1\) 的速度前进,求每个灯是第一个遇到的红灯的概率以及一个红灯都没遇到的概率。

\(n\leq 500,\ \ r_i+g_i\leq 100\)


题解:

\(s_i=r_i+g_i\)

如果所有 \(s_i\) 两两互质,那么每个灯都独立,我们只需要算出之前的灯都绿的概率乘上这个灯红的概率即可算出这个灯是第一个红灯的概率。

如果有一些 \(s_i\) 不互质,但是不互质的 \(s_i\) 都相等,那么也差不多,我们考虑某个灯时,所有 \(s_i\) 与它不相等的灯和它独立,而考虑 \(s_i\) 相等的灯中,可以发现每盏灯的红灯时间都覆盖了出发时间 \(\bmod s_i\) 意义下的一段区间,我们暴力修改和查询区间中 \(1\) 的个数就可以计算这些灯的贡献了。

如果情况更加复杂,我们考虑简化它,取一个包含足够素因子的数 \(M\),使得所有 \(\dfrac{s_i}{\gcd(s_i,M)}\) 两两要么互质,要么为倍数关系,那我们就可以枚举出发时间 \(\bmod M\) 的余数,然后用上面的方法计算了(如果不互质的 \(s_i\) 都为倍数关系,那么我们只需要将短的补齐,覆盖长的 \(s_i\) 中的若干段时间即可)。

\(M=2^3\times 3^2\times 5\times 7=2520\) 即可做到这一点,因为此时 \(s_i\) 除去与 \(M\) 的最大公约数后不会有超过一个素因子。

时间复杂度为 \(O(MSn)\),其中 \(M=2520\)\(S\)\(r_i+g_i\) 的最大值。

\(\rule[0pt]{14.3cm}{0.1em}\)

#\(202\)\(\text{Clock Breaking}\)\(\text{2020.10.17}\),自己做出)

题目大意:

给定显示时分的电子钟连续 \(n\) 分钟的示数,每个格子有三种可能状态:正常,一直亮或一直灭,你需要求出每个格子的状态,或报告这个格子的状态无法确定,或报告无解。

电子钟的尺寸是 \(7\times 21\),数字显示见题面。

\(n\leq 100\)


题解:

首先看输入给定的示数中每个格子有没有亮或者暗过,如果又亮过又暗过,那么这个格子一定正常。

然后再枚举起始时间,根据正常的格子检验这个时间是否合法,如果合法,再通过这个事件倒过去检验在输入中一直亮或一直灭的格子究竟是坏了还是可能正常显示。

注意,如果有多个可能的起始时间,那么对于某个格子,只要对于其中一个时间,该格子是无法确定的,那么最终答案中该格子就无法确定。

时间复杂度为 \(O(TMn)\),其中 \(T=24\times 60=1440\) 为一天的分钟数,\(M=7\times 21=147\) 为电子钟尺寸。

\(\rule[0pt]{14.3cm}{0.1em}\)

#\(259\)\(\text{Jazz Journey}\)\(\text{2020.10.17}\),自己做出)

题目大意:

有一个持续 \(d\) 天的在 \(n\) 座城市中旅行的计划,第 \(i\ (i<d)\) 天要从城市 \(a_i\) 乘机直达城市 \(a_{i+1}\)

\(m\) 种机票,分成单程和往返两种,往返机票只有先按照一个方向经过后才能按反方向经过(第一次经过的方向给定),也可以当成单程票用,每种机票有一定费用,求完成旅行的最小开销。

\(n,m,d\leq 3\times 10^5\)


题解:

显然每对城市之间的旅行安排是独立的,我们首先将每天的计划按照出发和到达地点相同的分为一类,下面就讨论两个地点 \(a,b\) 之间的旅行安排。

设从 \(a\) 飞到 \(b\) 的一天记为 \(0\),从 \(b\) 飞到 \(a\) 的一天记为 \(1\)\(a\to b,\ \ b\to a\) 的单程票价分别为 \(A,B\),往返票价分别为 \(C,D\),为了避免过多分类讨论,令 \(A=min(A,C),B=min(B,D)\),然后再令 \(C=min(C,A+B),D=min(D,A+B)\)

我们找到 \(C,D\) 中较小的一个,显然使用这种票是最为划算的(比单程和另一种往返都划算),所以要尽可能多用,而这也就是把 \(0,1\) 一前一后尽可能多地两两匹配,用一个栈来模拟括号串的匹配即可。

还剩下的 \(0,1\) 还是尽量配对,用另一种往返票解决,有多出来的 \(0\)\(1\) 再使用单程票。

时间复杂度为 \(O((d+m)\log(d+m))\)

\(\rule[0pt]{14.3cm}{0.1em}\)

#\(298\)\(\text{The Great Wall}\)\(\text{2020.10.19}\),自己做出)

题目大意:

\(n\) 段墙,每段墙有三种代价 \(a_i<b_i<c_i\),选择两个不同的长度为 \(r\) 的区间,不属于任何一个区间的墙代价为 \(a_i\),属于恰好一个区间的墙代价为 \(b_i\),属于两个区间交的墙代价为 \(c_i\),求代价和第 \(k\) 小的方案的代价。

\(n\leq 3\times 10^4\)


题解:

二分答案 \(M\),判断是否有至少 \(k\) 个代价不超过 \(M\) 的方案。

我们首先可以将所有 \(a_i\) 提前算进答案,然后令新的 \(b_i\) 减去 \(a_i\),新的 \(c_i\) 减去 \(a_i+b_i\),接下来枚举靠左区间的左端点,考虑靠右区间:

  1. 两区间相交,那么代价为两区间并的 \(b_i\) 和加上交的 \(c_i\) 和,可以写成只与 \(x-1,y-1,x+r-1,y+r-1\) 四个位置的前缀和有关的一次式,我们已经知道 \(x,r\),用主席树维护 \(y\) 处对应的值即可快速查询 \(y\) 的数量。

  2. 两区间不相交,那么代价就是两个区间的 \(b_i\) 之和,同样用主席树维护长度为 \(r\) 的区间 \(b_i\) 和即可。

时间复杂度为 \(O(n\log^2 n)\)

\(\rule[0pt]{14.3cm}{0.1em}\)

#\(285\)\(\text{Integral Polygons}\)\(\text{2020.10.19}\),自己做出)

题目大意:

给定凸 \(n\) 边形,顶点为整点,求出有多少条对角线两端面积都为整数。

\(n\leq 2\times 10^5\)


题解:

由 Pick 定理可知,一个格点多边形面积为整数当且仅当所有边上的点数之和为偶数。

显而易见地,两点间线段上点数之和(端点只算一个)为偶数当且仅当它们两维坐标分别同奇偶。

因此一条对角线 \((x,y)\ (x<y)\) 满足要求,当且仅当 \(s_y+s_x+f(x,y)=0\),其中 \(s_x\) 是前 \(x\) 条边上的点数之和,\(f(x,y)\)\(x,y\) 之间线段上点数,\(+\) 为二进制加法(异或)。

考虑到对于确定的 \(y\)\(f(x,y)\) 只和 \(x\) 两维坐标的奇偶性有关(\(4\) 种情况),\(s_x\) 只有 \(0,1\) 两种需要的取值,所以只要用 \(8\) 个变量记录每一种 \(x\) 的数量即可。

注意输入的多边形面积必须是偶数,否则直接输出 \(0\)

\(\rule[0pt]{14.3cm}{0.1em}\)

#\(235\)\(\text{Single Cut of Failure}\)\(\text{2020.10.19}\),自己做出)

题目大意:

有一个 \(w\times h\) 矩形框,其中有 \(n\) 条线段,每条线段连接框上两点,求至少需要连多少条新线段,使得每条旧线段与至少一条新线段相交,保证旧线段端点两两不同且不在四个角上。

\(n\leq 10^6\)


题解:

显然答案不超过 \(2\),因为只要连两条对角线即可,所以只要判断答案是不是为 \(1\)

我们将旧线段所有端点逆时针离散化,将编号为 \(i\)\(i+1\) 的两点中间的一段框上区域称为第 \(i\) 段,我们枚举新线段的一端,那么对于每一条旧线段,对新线段另一端的限制就是一个区间,我们只需要将所有区间求交,看看是不是非空即可。

区间求交就是求左端点最大值和右端点最小值,用 set 来维护,同时在移动新线段的起始端时,如果跨过了某条旧线段的端点,那么那条旧线段所代表的区间会取反,一条旧线段最多取反两次(只有两个端点)。

注意由于是环上区间,第二次覆盖到环开头位置时需要将下标整体增加 \(n\)

时间复杂度为 \(O(n\log n)\),据说有线性做法。

\(\rule[0pt]{14.3cm}{0.1em}\)

#\(181\)\(\text{Graph}\)\(\text{2020.10.20}\),看了题解)

题目大意:

给定 \(n\) 个点 \(m\) 条边的有向图,添加至多 \(k\) 条边使得字典序最小的拓扑排序字典序最大。

\(n,m,k\leq 10^5\)


题解:

模拟求解最小字典序拓扑序的过程,但我们增加一个辅助队列 \(q2\),用来存想要放到之后加入拓扑序的编号较小的结点(以使得字典序变大),原队列成称为 \(q1\)

如果 \(q1\) 中取出最小值后仍有其他元素,并且 \(k\) 条边还没有用完,那么我们可以暂时将它存到 \(q2\) 中(因为可以先放 \(q1\) 中靠后的点,再通过加边的限制使得编号小的点排在后面)。

如果 \(q1\) 中已没有点,那么我们就只能从 \(q2\) 中取出最大点,将它放入当且拓扑序的末尾了,在构造加边方案时,从之前拓扑序的最后一个点像这个点加一条边即可保证求出来的一定是加边情况下新图字典序最小的拓扑序。

时间复杂度为 \(O(n\log n)\)\(n,m,k\) 同阶)。

\(\rule[0pt]{14.3cm}{0.1em}\)

#\(183\)\(\text{Hack Protection}\)\(\text{2020.10.20}\),自己做出)

题目大意:

给定长度为 \(n\) 的序列 \(a_{1\ldots n}\),求出有多少个区间的 xor 和等于 and 和。

\(n\leq 10^5,\ \ a_i\leq 2^{31}-1\)


题解:

\(s_i\) 表示前缀异或和。

对于每一位,某个区间的 xor 和等于 and 和当且仅当它全是 \(1\) 且长为奇数,或不全是 \(1\)\(1\) 有偶数个。

首先考虑不全是 \(1\) 的情况,此时一段区间 \([l,r]\) 中每一位的 \(1\) 都有偶数个,显然等价于 \(s_{l-1}=s_r\),要统计这样的 \(l\) 的个数,只要一个主席树就可以完成。

如果存在某些位全为 \(1\),那么我们设 \(las_i\) 表示当前状态下前一个第 \(i\) 位为 \(0\) 的数下标是多少,那么我们可以枚举有多少位是全为 \(1\) 的,可以通过 \(las_i\) 排序后的结果知道哪些位上全为 \(1\),并得到这些位全为 \(1\),其他位不全为 \(1\) 的区间范围,这些位满足 \(s_{l-1}\ne s_r\),其他位满足 \(s_{l-1}=s_r\),因此我们将每一位相等或不等关系压成一个二进制数,同样在主席树上查询。

时间复杂度为 \(O(n\log^2 n)\)

\(\rule[0pt]{14.3cm}{0.1em}\)

#\(291\)\(\text{Binary Code}\)\(\text{2020.10.20}\),自己做出)

题目大意:

给定 \(n\) 个长度和不超过 \(5\times 10^5\)\(01\) 串,每个串中最多有一个 \(?\),求一种将每个 \(?\) 换为 \(0\)\(1\) 的方案使得这些串两两不为前缀关系,或报告无解。

\(n\leq 5\times 10^5\)


题解:

首先将每个串中的 \(?\) 理解成 \(0\)\(1\) 分别都插到一棵字典树上,我们将此时字典树上插入过的一个字符串记为二元组 \((a,b)\)\(a\) 表示原来是第几个串,\(b\) 表示其中 \(?\) 填的是 \(0\) 还是 \(1\)

从每一个 \((a,b)\) 对应的点往根结点走,如果路过另一个点 \((c,d)\),就说明当 \(a\)\(?\)\(b\)\(c\)\(?\)\(d\) 不能并存(否则就是前缀关系了),这显然是 2-SAT 问题,跑个 Tarjan 就做完了。

稍微分析一下会发现,字符串不重复的情况下边数不会超过 \(O(n^{\frac{4}{3}})\),猜测也有可能可以证到 \(O(n)\)

但是字符串可能会重复,这时候我们加一个特判,如果同样的字符串出现了三次,那么必有至少两次是一样的,直接输出无解。

时间复杂度为 \(O(n+e)\)\(e\) 为 2-SAT 建出的边数。

\(\rule[0pt]{14.3cm}{0.1em}\)

#\(103\)\(\text{Boys and Girls}\)\(\text{2020.10.21}\),自己做出)

题目大意:

求长为 \(n\) 的由男生和女生组成的环,使得两边至少有一个男生的人数为 \(x\),两边至少有一个女生的人数为 \(y\),或报告无解。

\(n,x,y\leq 10^5\)


题解:

这题在 CF 上还 WA 着,OJ 上数据比较弱,等真正过了再写。

\(\rule[0pt]{14.3cm}{0.1em}\)

#\(239\)\(\text{Triangles}\)\(\text{2020.10.21}\),自己做出)

题目大意:

给定一个 \(r\)\(c\) 列点阵(图形见题面),有一些边存在,数三角形个数。

\(r\leq 3000,\ \ c\leq 6000\)


题解:

先数正着放的三角形数量,反着放的同理。

显然图中所有三角形都是等边三角形,我们枚举水平的那条边,判定两侧在它们那一行是否通过横向边联通,以及向上延申是否可以相交,可以得到一个复杂度三方的做法。

我们只需要用数据结构优化这一过程,考虑每一行时,对于每个点 \(i\),求出它往左最多可以延申(向正左和左上都能扩展才算)的位置 \(l_i\) 和往右最多可以延申(向正右和右上都能扩展才算)的位置 \(r_i\),那么一对点 \((x,y)\) 满足条件当且仅当 \(l_y\leq x< y\leq r_x\),这可以将 \(y\) 一维“离线”,从左往右扫 \(x\),用树状数组来维护当且所有满足 \(l_y\leq x\)\(y\),对 \([x+1,r_x]\) 区间求和来实现。

时间复杂度为 \(O(rc\log c)\)

\(\rule[0pt]{14.3cm}{0.1em}\)

#\(281\)\(\text{Balanced Diet}\)\(\text{2020.10.21}\),自己做出)

题目大意:

\(m\) 种糖,每种糖有一个权值 \(a_i\),对于一个吃了 \(n\) 颗糖的方案,称其是合法的当且仅当对于每一种糖 \(i\),设吃了 \(s_i\) 颗,满足 \(\dfrac{na_i}{\sum a_i}-1<s_i<\dfrac{na_i}{\sum a_i}+1\)

给定一个长度为 \(k\) 的吃糖序列,保证每个前缀均合法,求最多还能吃多少颗糖,使得仍然保持每个前缀均合法,或报告可以无限吃下去。

\(m,k,\sum a_i\leq 10^5\)


题解:

贪心,设 \(t_i\) 表示当前情况下满足 \(\dfrac{na_i}{\sum a_i}-1<s_i\) 的最大的 \(n\),每次选择 \(t_i\) 最小的位置,吃一颗对应的糖,直到 \(t_i\) 比当前总糖数还少,用优先队列来实现。

证明一下,其实这种决策的不劣性是显然的(即使去吃别的糖,也必须在 \(t_i\) 颗内再吃一次这种糖),所以只要证明可行性,事实上这种方案一定是可行的,因为我们有 \(\sum\limits_{i=1}^m \dfrac{a_i}{\sum a_i}=1\),所以一定存在一种糖使得 \(s_i\leq \dfrac{na_i}{\sum a_i}\),那么吃一种这颗糖是不会超过最大限制的,因为此时 \(s_i+1\leq \dfrac{na_i}{\sum a_i}+1<\dfrac{(n+1)a_i}{\sum a_i}+1\)

最后要判定是否可以无限吃下去,在数据范围中已经明示,不难猜想当吃到 \(\sum a_i\) 颗糖时即可无限吃下去,可以感性理解为吃了这么多糖以后每种糖的 \(s_i\)\(n\) 的关系被卡死,一定和初始状态是一样的。

时间复杂度为 \(O((\sum a_i)\log m+k)\)

\(\rule[0pt]{14.3cm}{0.1em}\)

#\(227\)\(\text{Branch Assignment}\)\(\text{2020.10.22}\),自己做出)

题目大意:

给定 \(n\) 个点 \(m\) 条边的有向带权图,定义 \(i,j\) 两个点联络代价为从 \(i\) 途径 \(b+1\) 走到 \(j\) 的最短路长,将 \(1,\ldots,b\) 号点分成 \(s\) 个集合,使得同一个集合内两两联络代价和之和最小。

\(n\leq 5000,\ \ m\leq 5\times 10^4\)


题解:

\(i\)\(n\) 的最短路为 \(b_i\)\(n\)\(i\) 的最短路为 \(c_i\),令 \(a_i=b_i+c_i\),对于分出的大小为 \(k\) 的集合,可知其中每个点 \(i\) 对联络代价和的贡献都是 \((k-1)(b_i+c_i)=(k-1)a_i\)

我们将所有点按照 \(a_i\) 从小到大排序,通过一番胡乱推导或感性理解会发现:最优方案中每个集合一定都是一个区间,且靠后的区间长度更短。

简单说明一下,后者比较显然,如果后面的集合更大,那么只要把一部分分给较小的靠前的集合,答案会变小;而前者是后者的推论,如果有个集合不是区间,那么将不连通的部分与另一个有相邻元素的集合的相邻部分交换一下,会更优。

这样以后可以 DP,直接 DP 不优化的是 \(O(n^3)\),听说可以四边形不等式,不过这里我采用了 wqs 二分,然后基本就是个裸题,不多赘述。

时间复杂度为 \(O(n^2\log n)\)

\(\rule[0pt]{14.3cm}{0.1em}\)

#\(135\)\(\text{Chain & Co.}\)\(\text{2020.10.22}\),自己做出)

题目大意:

给定三维立体中 \(n\) 个相同尺寸的正方形框,两两边线无交点,求能否分成两个子集 \(A,B\),使得对于任意 \(x\in A,y\in B\)\(x,y\) 不能分离(即不能把 \(y\) 脱离 \(x\) 独立拉出来)。

多组数据。

\(\sum n\leq 10^6\)


题解:

将正方形框分成三类:分别是平行于 \(xy,yz,zx\) 平面的。

显然对于同一类正方形框,由于边界不相交,所以要么是异面,要么是在同一平面上但相离,那么它们不能分属 \(A,B\) 两个集合,只能属于同一个集合。

所以只要枚举一下,将三类点分成两个集合,剩下的就是要判定三类点中每两类点是不是两两不能分离的(随便从两类点中各选出一个都不能分离)。

如果固定了另一个框的方向,那么对于一个确定的框来说,满足另一个框与它不能分离的那个框的某个特征点(如左下角点)的轨迹是一个可以求出的长方体,我们枚举一类点,将所有这样的长方体取交,再判定另一类点是否都在这个交集中即可。

时间复杂度为 \(O(\sum n)\)

\(\rule[0pt]{14.3cm}{0.1em}\)

#\(241\)\(\text{Lonely Mountain}\)\(\text{2020.10.22}\),自己做出)

题目大意:

给定三维多面体在 \(xz,yz\) 两面上的投影(分别是包含 \(n_x,n_y\) 个端点的折线段),保证两方向轮廓线都是向上宽度递减的底部 \(z\) 坐标为 \(0\) 的连通区域,求多面体最小体积,或报告无解。

\(n_x,n_y\leq 10^5\)


题解:

如果两维投影最大高度相等,那么有解,否则无解。

首先考虑两维宽度都随高度线性递减的情况,即两维投影都是梯形(或退化成三角形),此时设六面体下底面为 \(a\times b\),上底面为 \(c\times d\),通过积分或者割补可以知道体积为 \(\dfrac{(a-c)(b-d)}{3}+\dfrac{ad+bc}{2}\)

如果两维投影是更复杂的折线,我们只需沿着所有拐点的 \(z\) 坐标将折线下方的区域切分成若干个梯形或三角形的并,对于每一段梯形和三角形做一次上面的事情即可(注意上面的面积结论当这个梯形的双底被分割成好几段不连续区间的时候也是成立的,所以有多峰的情况并不影响答案)。

在同一段内,宽度随高度递减,其递减速率可以通过一条从下到上的扫描线算出,扫描时记录当前与扫描线相交的所有折线段的斜率总和,那么这个斜率总和就是宽度随高度递减的速率。

时间复杂度为 \(O((n_x+n_y)\log(n_x+n_y))\)

\(\rule[0pt]{14.3cm}{0.1em}\)

#\(253\)\(\text{Fragmentation}\)\(\text{2020.10.23}\),自己做出)

题目大意:

给定序列 \(a_{1\ldots n}\),求一种分段方法,使得在不改变同一段内数的顺序的情况下可以将序列排序。

\(n\leq 10^5\)


题解:

一段连续的相同的数显然可以缩起来,缩完之后离散化一下,设得到的新序列为 \(b_{1\ldots m}\)

可以发现 \(i\)\(i+1\) 两个数处于同一段中的情况最多只会出现一次(否则两个包含 \(i\ \ i+1\) 的段无法排序),所以答案其实取决于存在 \(i,i+1\) 处于同一段的 \(i\) 的数量。

于是我们令 \(dp(j)\) 表示当 \(b_j,b_{j-1}\) 这两个数处于同一段(前提是 \(b_j=b_{j-1}+1\))时,序列里不超过 \(b_{j-1}\) 的数中最多有多少对 \((k,k+1)\) 处于同一段,我们按照 \(b_j\) 从小到大更新,为了方便转移,我们对状态稍作修改,\(dp(j)\) 可以是 \(b_j,b_{j-1}\) 处于一段,也可以是不处于一段(要看哪个答案更小),这时 \(j\) 的取值就不需要满足 \(b_j=b_{j-1}+1\) 了。

第一种转移是 \(b_j,b_{j-1}\) 不在同一段,\(dp(y)\to dp(j)\),这里 \(y\) 就是任意的,只要 \(b_y<b_j\) 即可。

第二种转移是把 \(b_j,b_{j-1}\) 放在一段里,\(dp(y)+1\to dp(j)\),这里 \(y\) 也没有什么限制,但是有一条规则:如果 \(y=j-1\),并且 \(b_y,b_{y-1}\) 也在同一段中,那么就意味着 \(b_{j-2},b_{j-1},b_j\) 都在同一段中,当且仅当 \(b_{j-1}\) 在整个序列中只出现过这一次时才能这么转移(否则会漏掉别的地方的 \(b_{j-1}\))。

具体实现时为了输出方案,还要对每个状态记录前驱状态,再额外记录一个 \(dn(j)\) 表示 \(dp(j)\) 这个状态中是否把 \(b_j,b_{j-1}\) 放在了一段。

时间复杂度为 \(O(n\log n)\)

\(\rule[0pt]{14.3cm}{0.1em}\)

#\(246\)\(\text{Digital Addition}\)\(\text{2020.10.23}\),自己做出)

题目大意:

给定一个电子钟字体书写的两数加法竖式(两个加数以及和分别写在三行),三个数位数都为 \(w\)(可能有前导零),但是由于显示出了问题,下一行的数的最上方一条线会重叠显示在上一行的数的中间那条线上,右边一列的数的最左边一条线会重叠显示在左边一列的数的最右边那条线上,求一种可能的竖式或报告无解。

\(w\leq 100\)


题解:

由于 \(w\) 非常小,随便做做就可以。

\(dp(i,j,k,l)\) 表示最后 \(i\) 位,第 \(i\) 位上三个数分别是 \(j,k,l\) 时是否可行,如果可行还需要记录前驱状态。

转移时只需要暴力枚举(总共的 \((j,k,l)\) 也不超过 \(200\) 组),可以根据每一列的横向线来除掉一些无用状态,此后就是模拟相邻两列六个数的状态,是否和给定的示数相等即可。

实现方法就不具体写了。

时间复杂度为 \(O(D^4\times w)\),其中进制数 \(D=10\)

\(\rule[0pt]{14.3cm}{0.1em}\)

#\(262\)\(\text{Laminar Family}\)\(\text{2020.10.23}\),自己做出)

题目大意:

给定一棵 \(n\) 个点的无根树和树上的 \(m\) 条路径,求是否存在两条路径相交而不为包含关系。

\(n,m\leq 10^5\)


题解:

两条路径相交,那么它们的最浅点(称为路径的 LCA)显然必须是祖先-后代关系。

将路径的相交分成两种,一种是 LCA 相同,另一种是 LCA 不同,只需分别判定这两类的所有相交是否都是包含关系即可。

第一类:LCA 相同:

我们只需要枚举 \(x\),对以 \(x\) 为 LCA 的路径按照长度从小到大排序,判定是否相邻两条路径都是包含关系,如果是那么就说明它们两两都是包含关系。

第二类:LCA 不同:

我们考虑对于每条路径(设其 LCA 为 \(u\)),求出 LCA 是 \(u\) 后代的路径中有多少条与它相交,又有多少条是它的子路径,然后看看是不是都相等就可以了。

  1. 相交:对于每条路径,给其 LCA 的权值加上 \(1\),那么求出与一条路径相交的 LCA 为后代的路径有多少条与它相交,就是一个链上求和,预处理一下到根的前缀和即可。

  2. 包含:对于路径 \((u,v)\),如果 \(u,v\) 不是祖先-后代关系,那么这条路径不可能是一条 LCA 深度更小路径的子路径(因为在其 LCA 处分成两支),否则,设 \(u\)\(v\) 的祖先,那么它是所有满足 LCA 为 \(u\) 祖先,一支在 \(v\) 子树内的路径的子路径,对此我们将每条路径记录在其 LCA 上,然后进行一次线段树合并,遇到上述路径 \((u,v)\) 时在 \(u\) 的树上给 \(v\) 的所有后代做一个区间加,查询时只要查一条路径两端点处在 LCA 所对应线段树上的值即可,注意用标记永久化减小空间。

时间复杂度为 \(O((n+m)\log n)\)

\(\rule[0pt]{14.3cm}{0.1em}\)

#\(178\)\(\text{ASCII Puzzle}\)\(\text{2020.10.23}\),自己做出)

题目大意:

完成一个 \(n^2\) 块拼图的 \(nh\times nw\) 拼图谜题(给定拼图碎片的规则见题面)。

\(n\leq 4,\ \ 3\leq w,h\leq 5\)


题解:

首先特判 \(n=1\) 的情况,剩余的情况都会有四个角落。

首先找到拼图所在“平凡块”的四角,然后可以求出对应的四条边是否是光滑的。

如果有两条边都是光滑的,那么一定放在对应的角落上,如果有一条边是光滑的那么一定放在对应的边上,剩下的就放中间。

同一条边上的拼图顺序和内部拼图顺序暴搜即可。

时间复杂度为 \(O(n^2wh\times T)\)\(T\) 是最大的情况数,在 \(n=4\)\(T=2^4\times 4!=384\)

\(\rule[0pt]{14.3cm}{0.1em}\)

#\(141\)\(\text{Tarot Sham Boast}\)\(\text{2020.10.24}\),自己做出)

题目大意:

随机一个字符集为 \(\{R,S,P\}\) 的长为 \(n\) 的字符串 \(T\),给定 \(s\) 个模式串 \(S_{1\ldots s}\),按照它们在 \(T\) 中作为子串出现的概率排序(如果概率相同按照输入顺序排序)。

\(n\leq 10^6,\ \ s\leq 10,\ \ |S_i|\leq 10^5\)


题解:

根据歌唱王国的结论,模式串 \(S\) 在随机文本串中第一次出现的位置期望为 \(\sum\limits_{b\in B} |\Sigma|^b\),其中 \(B\)\(S\)\(Border\) 长度集合。

据此不难猜想:本题中按每个长度是不是模式串的 Border 得到每个串对应的一个新的 \(01\) 串,这些 \(01\) 串的字典序排序结果就是答案(也就是两个模式串最长的不同长度的 Border,如果其中一个更长,那么对应模式串出现的概率就更低)。

但是我们要注意有些 Border 是没有用的,用一个简单的容斥来理解,我们统计一个串出现的概率时用它在每个位置出现的概率减去多个位置同时出现的概率,而 \(S_i\) 的一个 Border 长度 \(x\) 如果满足 \(2|S_i|-x>n\),那么以 \(x\) 为公共前后缀时两个 \(S_i\) 放不进长度为 \(n\)\(T\) 中,所以这个 Border 是无用的,要去掉。

根据上述感性理解,用 KMP 求一下 Border 就做完了。

过题之后找了下题解,具体证明我看不懂:http://www.csc.kth.se/~austrin/icpc/tarotshamproof.pdf

时间复杂度为 \(O(s\sum |S_i|)\)

\(\rule[0pt]{14.3cm}{0.1em}\)

#\(286\)\(\text{Kitchen Knobs}\)\(\text{2020.10.24}\),自己做出)

题目大意:

顺序给定 \(n\) 个包含 \(7\) 个一位数的轮盘,每个轮盘有一个初始指针,定义其示数为从初始指针开始顺时针读取一周得到的七位数,每一次操作可以将一个区间中所有轮盘的初始指针朝同一方向转动一个固定的角度,求至少多少次操作可以使所有轮盘都显示其可能的最大示数。

\(n\leq 500\)


题解:

如果一个轮盘上所有数都一样,那么直接删除它,这对答案没有任何影响。

否则,一个轮盘的最大示数对应的指针位置是唯一的(否则可以证明 \(1,\ldots,7\) 都是它的 Border 长度,从而每一位相等),我们求出这个指针位置和初始位置的差值,即为需要转动的格数。

于是问题转化成了:将一个初始全 \(0\) 的序列最少做几次区间加法,可以得到给定序列?

对给定序列差分,可以进一步转化成:将一个初始全 \(0\) 的序列每次选择两个数一加一减一个相同的值(或只修改一个数),最少几次可以得到给定序列?

注意,上述操作都是在 \(\bmod 7\) 意义下的,值域也都是 \([0,6]\)

如果一次操作中改变了 \(a,b\) 两位置上的数(\(a<b\)),另一次操作改变了 \(b,c\) 两位置上的数(\(b<c\)),那么我们可以将它用一次对 \(a,c\) 的操作和一次对 \(b,c\) 的操作来等效,所以存在一个最优方案,使得不存在一个 \(b\) 既和前面的数同时操作过,又和后面的数同时操作过。

如果一个 \(b\) 只和前面的某些数(记为 \(S\))同时操作过,那么 \(b\) 当然就等于 \(S\) 中所有元素的和的相反数,也就是 \(\{b\}\cup S\) 的元素和为 \(0\),一个子集和为 \(0\) 对应着一个 \(b\) 可以通过之前的操作变为给定的数。

所以问题进一步转化为:最多可以从给定序列中分出多少和为 \(0\) 的子集?

我们首先证明,假设 \(a+b=0\),那么一定存在一个最优方案,使得每个 \(a\) 都与 \(b\) 组成一个子集,或每个 \(b\) 都与 \(a\) 组成一个子集。这是因为假设结论不成立,那么有一个 \(a\) 与另一些数 \(S_1\) 组合,有一个 \(b\) 与另一些数 \(S_2\) 组合,可以换成 \(a,b\) 组合,\(S_1,S_2\) 组合。

于是本来有 \(6\) 种数(\(1,2,3,4,5,6\)),通过这样的两两匹配只会剩下三种(\(1,6\) 中较多的那种,\(2,5\) 中较多的那种,\(3,4\) 中较多的那种)。

然后就可以 DP 了,设 \(dp(i,j,k)\) 表示当三种数分别有 \(i,j,k\) 个时最少操作数,那么 \(dp(i-a,j-b,k-c)+a+b+c-1\to dp(i,j,k)\),其中 \(a\) 个第一种数,\(b\) 个第二种数,以及 \(c\) 个第三种数的和为 \(0\)

由于 \(7x\equiv 0\),所以 \(a,b,c\leq 6\)(除了 \(a=7,b=c=0\) 及两种对称情况外),由于 \(7\) 是素数,所以与小于它的所有数互素,一旦确定 \(a,b\) 也就确定了 \(c\),所以这样的 \((a,b)\)\(49\) 对,复杂度可以接受。

时间复杂度为 \(O(n^3P^2)\)\(P=7\) 为模数。

\(\rule[0pt]{14.3cm}{0.1em}\)

#\(154\)\(\text{Evolution in Parallel}\)\(\text{2020.10.25}\),自己做出)

题目大意:

给定字符串 \(S\)\(n\) 个字符串 \(T_1,\ldots,T_n\),求所有 \(T_i\) 是否都是 \(S\) 的子序列,并且将 \(T_i\) 划分为 \(2\) 个集合,使得同一个集合内的字符串两两是子序列关系。

\(n\leq 4000,\ \ |S|,|T_i|\leq 4000\)


题解:

先把存在 \(T_i\) 不是 \(S\) 子序列的情况判掉。

然后 DP,将 \(T_i\) 按长度从小到大排序,设 \(dp(i,j)\) 表示将 \(T_1,\ldots,T_i\) 分成两列,最后一个串分别是 \(T_i\)\(T_j\) 时是否可行,如果可行那么还要记录前驱。

暴力转移,如果 \(dp(i,j)\) 可行且 \(T_j\)\(T_{i+1}\) 的子序列,那么 \(dp(i+1,i)\) 也可行;如果 \(T_i\)\(T_{i+1}\) 的子序列,那么 \(dp(i,j)\) 可以转移到 \(dp(i+1,j)\)

这里我也没想到怎么优化,随便优化一下常数就过了。

时间复杂度为 \(O(n^3)\)

\(\rule[0pt]{14.3cm}{0.1em}\)

#\(190\)\(\text{Landscape Improved}\)\(\text{2020.10.25}\),自己做出)

题目大意:

\(w\) 堆石块从左到右排列,第 \(i\) 堆包含 \(h_i\) 个石块,你需要添加不超过 \(n\) 个石块,满足每个新加的石块的左下和右下都需要有一个石块,使得最高的石堆高度最大。

\(w\leq 10^5,\ \ n\leq 10^{18}\)


题解:

二分答案 \(m\),枚举添加后高度为 \(m\) 的石堆 \(i\),从 \(i\) 向两边搜至少要将石块添加到哪里才能使得每个新加的石块的左下和右下都有一个石块,这个可以用 ST 表维护 \(h_i+i\)\(h_i-i\) 的最小值来求出。

时间复杂度为 \(O(w\log w\log \sqrt n)\)

\(\rule[0pt]{14.3cm}{0.1em}\)

#\(270\)\(\text{Pork barrel}\)\(\text{2020.10.25}\),自己做出)

题目大意:

给定 \(n\) 个点 \(m\) 条边的无向带权图,\(q\) 次询问仅保留权值在一个区间中的边时,连通块数最少的最小生成森林的边权和。

多组数据。

\(\sum n\leq 10^5,\ \ \sum m\leq 5\times 10^5,\ \ \sum q\leq 10^6\)


题解:

类似须臾幻境,不过我们会发现选取的边是边权尽量偏小的边,所以我们需要按照边权从大到小倒着做。

用个 LCT 维护当且的 MST,由于询问的权值和权值区间是同一个权值,所以直接求权值 MST。

最后用主席树维护每个时刻的答案。

时间复杂度为 \(O((m+q)\log n+n)\)

\(\rule[0pt]{14.3cm}{0.1em}\)

#\(277\)\(\text{Tours}\)\(\text{2020.10.25}\),自己做出)

题目大意:

给定 \(n\) 个点 \(m\) 条边的无向图,求出所有可能的 \(k\),使得给每条边一个 \([1,k]\) 的整数权值,能够使得每个长度不小于 \(3\) 的简单环上每种权值出现次数相等。

\(n,m\leq 2000\)


题解:

相交的不同的环可以异或出新的区间,我们发现任意多个环相加减(相异或)得到的必须仍然是每个权值出现次数一致的边集,也容易证明只要 \(k\) 是所有这样边集的公因数就满足条件。

而两条边永远同时出现或不出现在这样的边集,当且仅当覆盖它们的环的集合完全一致。

所以我们求出一个 DFS 树,每条非树边随机赋一个权值,然后一条树边的权值等于跨过它的所有非树边的权值异或,最后数除了 \(0\) 之外所有权值等价类大小的 \(\gcd\),它的所有因数就是答案。

时间复杂度为 \(O(m\log n)\)

\(\rule[0pt]{14.3cm}{0.1em}\)

#\(247\)\(\text{The Imp}\)\(\text{2020.10.26}\),自己做出)

题目大意:

\(n\) 个物品,第 \(i\) 个物品价值为 \(v_i\),价格为 \(c_i\),但是你每买下一个物品,小鬼都有可能把它变成价值为 \(0\) 的灰尘,不过最多 \(k\) 个商品会被变成灰尘,如果你买到一个物品且没有变成灰尘,那么你必须带着它离开。

求出你和小鬼都最优决策的情况下,你能赚到多少钱(赚到的钱数即得到的物品的价值减去买过的所有物品的价格之和)。

\(n\leq 1.5\times 10^5,\ \ k\leq 9\)


题解:

贪心,可以证明存在一种最优决策,买的顺序是按价值从小到大的,这是因为如果前后两个买的物品前一个价值更大,那么交换一下不会更劣。

接下来直接做不好设计状态,所以考虑二分答案 \(m\),这样限制就变成了:任意前 \(i\) 个买的物品价格和加上 \(m\) 不能大于第 \(i\) 个物品的价值。

于是和状态有关的变量就只有:考虑前多少个物品,选了多少个物品,满足条件下的总价格和,于是令 \(dp(i,j)\) 表示从前 \(i\) 个物品中选 \(j\) 个,满足二分条件的情况下价格和最小是多少。

那么 \(dp(i,j)\to dp(i+1,j)\),并且在满足 \(dp(i,j)+c_{i+1}+m\leq v_{i+1}\) 时有 \(dp(i,j)+c_{i+1}\to dp(i+1,j+1)\),最后检验是否 \(dp(n,k)\) 不是初始的无穷大即可。

时间复杂度为 \(O(nk\log (\sum v_i))\)

\(\rule[0pt]{14.3cm}{0.1em}\)

#\(233\)\(\text{Rubik's Rectangle}\)\(\text{2020.10.26}\),自己做出)

题目大意:

一个 \(n\times m\) 的矩阵,其中 \(1\)\(n\times m\) 中所有数都恰好出现一次,每次操作可以翻转一行或一列的数的顺序,需要把最终矩阵通过不超过 \(10nm\) 操作变成按照先行后列排好序的状态,或报告无解。

\(n,m\leq 100\)


题解:

这题似乎对玩过魔方的人比较友好。

一个显然的观察是:一个数字只能出现在最多四个位置上(因为行列只有最多两种情况),所以我们看一下所有这样四个位置上的数和最后四个数一不一样,如果有不一样那么直接无解。

接下来考虑一种情形:第一行和最后一行,第一列和最后一列都已经拼好,现在要拼中间区域,对于中间区域中某四个中心对称的格子来说,在复原它们的相对位置时就不能改变任何其他行列的状态(可以进行两行和两列的操作,并且每行每列都要操作偶数次)。

画几张图理解一下,发现我们能做的基本操作类型是 \(ABAB\),其中 \(A,B\) 分别是一行和一列,这个操作的效果其实是对四块中的三块做了一个三轮换。

(如果对魔方比较熟悉就会很快发现这个结论,因为这个结构其实就是调顶棱位置时候的操作)

但是这里没有很严格的什么次数限制,所以我们先把左上角那个数通过若干次操作归位,再看看剩下三个数能不能转一次归位。

而对于第一行和最后一行,第一列和最后一列的数,我们还可以加上对一列或一行的操作,此时一定可以归位。

时间复杂度为 \(O(nm)\)

\(\rule[0pt]{14.3cm}{0.1em}\)

#\(287\)\(\text{Subway}\)\(\text{2020.10.26}\),自己做出)

题目大意:

\(n\) 个站点和连接它们的 \(m\) 条线路(若干条边组成的链),线路总长为 \(L\),问从一个站 \(A\) 到另一个站 \(B\) 至少需要坐上几条不同的线,以及在此情况下最多可以坐几站路(一条线不能正反都坐)。

\(n\leq 3\times 10^5,\ \ m\leq 10^5,\ \ L\leq 10^6\)


题解:

对于每个站点建一个顶点,再对于每条线路拆成正反两条,分别对于线路上每一个站点新建一个顶点,并且按照线路顺序连接(边权为 \(0\)),线路上每个顶点再和对应站点一开始建的那个点互相连边,令走过去的权值为 \(0\),走回来的权值为 \(1\)

那么第一问的答案就是两个点之间的最短路。

第二问是最长路,不能直接做,不过我们只要提取第一问源点出发的最短路 DAG,在这个 DAG 上拓扑排序求最长路即可。

时间复杂度为 \(O(L\log L)\)

\(\rule[0pt]{14.3cm}{0.1em}\)

#\(138\)\(\text{Distribution in Metagonia}\)\(\text{2020.10.26}\),自己做出)

题目大意:

给定 \(n\),拆成若干个互不为倍数关系的 \(2^i3^j\) 之和。

一个测试点有 \(T\) 组数据。

\(n\leq 10^18,\ \ T\leq 1000\)


题解:

设求解过程为 \(Solve(n)\)

首先,如果 \(2\mid n\)\(3\mid n\),直接把这个 \(2\)\(3\) 提出,接着 \(Solve(n/2)\)\(Solve(n/3)\)

如果 \(2,3\) 都不是 \(n\) 的因数,那么显然 \(n\) 的分拆中一定又会有 \(2^p\),又会有 \(3^q\),根据直觉和题面没有写无解判定的情况来看,应该是不可能无解的,所以我们只要找到一个 \(2^p\),使得 \(3\mid (n-2^p)\),这样剩余的数里都会有 \(3\),即 \(2^p\) 不是它们的倍数,在此基础上我们令 \(p\) 最大,也能满足 \(2^p\) 不是其他 \(2^i3^j\) 的倍数。

因为 \(3\) 不是 \(n\) 的因数,所以 \(n\equiv 1\bmod 3\)\(n\equiv 2\bmod 3\),设 \(p_0=\lfloor\log n\rfloor\),那么 \(2^{p_0}\equiv n\)\(2^{p_0-1}\equiv n\) 必有一个成立。

时间复杂度为 \(O(T\log n)\)

\(\rule[0pt]{14.3cm}{0.1em}\)

#\(194\)\(\text{Export Estimate}\)\(\text{2020.10.27}\),自己做出)

题目大意:

给定 \(n\) 个点 \(m\) 条边的带权无向图,\(q\) 次询问,每次给定 \(k\),询问只保留边权不小于 \(k\) 的边时按照下列原则缩点后剩余图的点数和边数:

  • \(1\)\(n\) 枚举 \(i\)

  • 如果 \(i\) 当前的度数恰好为 \(2\) 并且不存在到自己的自环,那么删除它和这两条边,并在这两条边的另外两个端点之间连边。

\(n,m,q\leq 3\times 10^5\)


题解:

从大到小加边,就变成了动态维护当前图缩点后的点数和边数。

只看二度点,那么二度点构成的连通块只有链或者环,如果是链的话那么最后会全缩掉,如果是环的话最后会剩一个点。

用并查集维护连通性,对于每个连通块维护其中是否存在度数超过 \(2\) 的点,如果不存在则再维护一下这个连通块是不是环。

如果连一条边后变成了环,那么会少缩掉一个点两条边,如果连一条边后本来是环变成了存在三度点,那么破环成链。

在这过程中顺便维护点数和边数的变化情况,具体细节由于我也忘了所以就不写了。

时间复杂度为 \(O(n\log n)\),这里把 \(n,m,q\) 都当成一个量级了。

\(\rule[0pt]{14.3cm}{0.1em}\)

#\(230\)\(\text{Metal Processing Plant}\)\(\text{2020.10.27}\),自己做出)

题目大意:

\(n\) 个点,给出任意两点之间距离(不一定满足三角形不等式),将它们分成两个点集 \(A,B\),使得两者内部最远点对距离之和最小。

\(n\leq 200\)


题解:

将所有距离从大到小排序为 \(d_1,\ldots,d_{\frac{n(n-1)}{2}}\),枚举两个最远距离中较大的那个 \(d_i\)(不妨设为 \(A\) 中的最远距离),那么 \(d_1,\ldots,d_{i-1}\) 这些边的两个端点必须分别在两边,在它们之间连边,如果不是二分图那么说明无解,否则每个二分图连通块的两部必须分属两个集合。

接下来考虑另一个最远距离(\(B\) 中的最远距离)最小是多少,考虑二分答案 \(d_j\),那么 \(d_{i+1},\ldots,d_{j-1}\) 这些距离不能同时属于 \(B\),这时不是二分图关系,而是 2-SAT 判定,我们将前面说的那个二分图的每个连通块的两部看出两个点,根据二分答案得到的这些关系建出 2-SAT 图判定是否有解,即可判定二分的答案是否可行。

由于只有二分图某个连通块的两部变化时二分答案那一部分的情况才会变化,所以只有二分图发生改变时才重新进行二分答案,而二分图改变最多 \(n-1\) 次,所以第二个过程最多只会做 \(n\) 次。

时间复杂度为 \(O(n^3\log n)\)

\(\rule[0pt]{14.3cm}{0.1em}\)

#\(191\)\(\text{Frightful Formula}\)\(\text{2020.10.28}\),自己做出)

题目大意:

有一个 \(n\times n\) 矩阵 \(F_{n\times n}\),给定第一行和第一列的数,其余某个位置 \((i,j)\) 上的数 \(F_{i,j}=aF_{i-1,j}+bF_{i,j-1}+c\),求 \(F_{n,n}\) 的值,对 \(10^6+3\) 取模。

\(n\leq 2\times 10^5\)


题解:

一开始遇到一个式子不太会算到 E 群问了一下,结果被讲了一些听不懂的东西,最后我这个做法似乎是一个不太本质的做法......

可以发现整个式子里面 \(c\) 的贡献和另外两个东西的贡献可以拆开,另外两个东西很好算,枚举从第一行或第一列中哪个位置转移,乘上一个类似 \(\binom {i+j}{i} a^ib^j\) 的式子就可以了。

\(c\) 是不太好算的,我是手算了一个 \(5\times 5\) 的表格,令 \(C_{i,j}\) 表示从 \((0,0)\) 走到 \((i,j)\) 时的 \(c\) 前的系数,转移是 \(C_{i,j}=aC_{i-1,j}+bC_{i,j-1}+1\),然后发现似乎 \(C_{i,j}=C_{i-1,j}+C_{i,j-1}-C_{i-1,j-1}+\binom {i+j}{i} a^ib^j\),尝试用组合意义来解释,最后那个 \(\binom {i+j}{i} a^ib^j\) 就是从 \((0,0)\) 一直按照 \(a,b\) 的规则走到 \((i,j)\),然后再变成 \(c\) 的贡献,而前面那个其实是一个前缀和的形式(这一段凭印象写的,如果错了请指出)。

所以 \(c\) 的系数就是 \(\sum\limits_{i=0}^{n-2}\sum\limits_{j=0}^{n-2} \binom {i+j}{i} a^ib^j\)

\(Sum_i=\sum\limits_{j=0}^{n-2} \binom {i+j}{j} b^j\),根据组合恒等式列出 \(Sum_i\)\(Sum_{i-1}\) 间的方程,可以解得:

\[Sum_i=\dfrac{\binom {i+n-2}{n-2} b^{n-1}-Sum_{i-1}}{b-1} \]

如果 \(a\ne 1\) 或者 \(b\ne 1\) 都可以按照这个递推,如果 \(a=b=1\) 那么上面这个式子是经典恒等式,值为 \(\sum\limits_{i=1}^{n-1} \binom {n-1} i ^2\)

时间复杂度为 \(O(n\log n)\)

\(\rule[0pt]{14.3cm}{0.1em}\)

#\(261\)\(\text{First of Her Name}\)\(\text{2020.10.28}\),自己做出)

题目大意:

给定 \(n\) 个点的字典树,字符集为 \(\Sigma\),有 \(q\) 次询问,每次询问有几个结点代表的串(从根结点走到这个点的串)以 \(T\) 为后缀(按照原题意是以 \(T\) 翻转过来为后缀)。

\(n\leq 2\times 10^6,\ \ \sum |T|\leq 2\times 10^6,\ \ |\Sigma|=26\)


题解:

是个爱怎么做就怎么做的字符串题。

首先尝试树上 SA,将询问串放在一起或者询问时二分,然后被 cyj 大毒瘤卡常了。

然后尝试广义 SAM,顺着 \(T\) 走到对应点数一下大小,就过了。

时间复杂度为 \(O(n+\sum |T|)\)

\(\rule[0pt]{14.3cm}{0.1em}\)

#\(110\)\(\text{Heavy Chain Clusterization}\)\(\text{2020.11.01}\),自己做出)

题目大意:

给定 \(n\) 个字符串 \(S_1,\ldots S_n\),将它们分成最少的组,使得同一个组内长度为 \(k\) 的前缀都相同或长度为 \(k\) 的后缀都相同。

\(n\leq 5000,\ \ k\leq |S_i|\leq 550\)


题解:

将每个串的长度为 \(k\) 的前后缀分别哈希,离散化后在前后缀之间连边,答案就是最小点覆盖,也就是最大匹配,跑一次 dinic 就求出来了。

时间复杂度为 \(O(\sum |S_i|+n\sqrt n)\)

\(\rule[0pt]{14.3cm}{0.1em}\)

#\(243\)\(\text{Kingdom Trip}\)\(\text{2020.11.01}\),自己做出)

题目大意:

给定二维平面中 \(n\) 个点 \(p_1,\ldots,p_n\),选择其中一个子序列,使得对于不属于这个子序列的每个 \(p_i\),它到它在子序列中的前驱后继连线段的距离不超过 \(d\),求子序列至少包含几个点。

\(n\leq 2000\)


题解:

只要求出所有 \(trans(i,j)\) 表示是否 \(\forall k\in [i+1,j-1]\) 都到 \(p_ip_j\) 距离小于 \(d\),这个求完之后再 \(n^2\) DP 一下就行了。

枚举 \(i\),从前到后扫描 \(k\),如果 \(|p_ip_k|\leq d\) 那么没有限制,否则 \(k\) 就对 \(p_ip_j\) 的角度有一个区间范围的限制,维护前面所有这些区间的交,看看 \(p_j\) 相对 \(p_i\) 是不是落在这个区间里,就完成了判定。

时间复杂度为 \(O(n^2)\)

\(\rule[0pt]{14.3cm}{0.1em}\)

#\(111\)\(\text{Hidden Supervisors}\)\(\text{2020.11.01}\),自己做出)

题目大意:

有一个 \(n\) 个点的以 \(1\) 为根的有根树,某些点的父结点未定,确定这些点的父结点使得整个树的最大匹配数最大。

\(n\leq 10^5\)


题解:

先求出每个连通块的最大匹配(为了记录每个点在不在最大匹配中,最好采用贪心法求最大匹配),再记录一下这个连通块的最大匹配是否一定包含根结点。

如果一个连通块的最大匹配包含根结点,那么直接把这个根结点连到 \(1\) 的下面(因为接到其他点下面也不能匹配,没有用),然后用一个队列维护当前与 \(1\) 连通的点中没有匹配的点的数量,再用一个优先队列维护不与 \(1\) 连通的连通块中未匹配点数最多的那个。

每次取出优先队列中的队首,将根结点挂在与 \(1\) 连通的一个没有匹配的点下面(这样形成了一组匹配),如果不存在这样的点那么只好随便找一个点连(比如直接当成 \(1\) 的儿子),因为我们是按照未匹配点数从大到小加的,所以尽量保证了当前能够存在一个没匹配的点,所以这个贪心是最优的。

时间复杂度为 \(O(n\log n)\)

\(\rule[0pt]{14.3cm}{0.1em}\)

#\(125\)\(\text{Baggage}\)\(\text{2020.11.01}\),自己做出)

题目大意:

有一个长为 \(2\times n\) 的序列,形如 \(\text{BABA...BA}\),每次操作可以选择连续两个字符(不能选到空位),放到另一处连续的两个空位中(第一个位置前面都是空位),然后这两个字符原来的位置会变成空位。

你需要用最少的操作次数使得序列变成 \(\text{AA...AABB...BB}\),起始位置任意但必须连续。

\(n\leq 100\)


题解:

构造题,没有什么技巧和算法可言。

首先有端猜测答案就是 \(n\)

题目里送了两组样例,一个是 \(5\),一个是 \(8\),以此为基础推一下 \(n=9\)\(n=12\),那么模 \(4\)\(1\)\(0\) 的就基本解决了。

\(4\)\(3\) 的可以手玩一下 \(n=3\)(需要用到 \(-3\) 这个位置,脑洞有点大),然后尝试推一下 \(n=7\),基本就出来了。

\(4\)\(2\) 的手玩 \(n=6\),不过我脑子不太好,看了下 CF 里的数据才知道怎么搞。

具体每一类的做法不太好说清楚,就不讲了。

时间复杂度为 \(O(n)\)

\(\rule[0pt]{14.3cm}{0.1em}\)

#\(201\)\(\text{Cumulative Code}\)\(\text{2020.11.01}\),以前见过)

题目大意:

有一个 \(k\) 层的满二叉树,结点从上到下从左到右编号,有 \(q\) 个询问,每次给定 \(a,d,m\),求出二叉树的 Prufer 序列 \(p_1,\ldots,p_{2^k-3}\) 中的以下元素和:\(\sum\limits_{i=1}^m p_{a+(i-1)d}\)

\(k\leq 30,\ \ q\leq 300\)


题解:

类似根号分治的一种分块思路,将树分成上 \(15\) 层和下面的部分,询问时暴搜上 \(15\) 层,下面的部分通过预处理解决。

具体来说,递归问题分成两个种类,分别是根结点有父亲的子树和根结点无父亲的子树,前者 Prufer 序列的删点顺序是左右中,后者是左中右,在前 \(15\) 层暴力模拟和递归即可。

当层数超过 \(15\) 时做一些预处理,我们提前处理好设根结点编号为 \(a\) 时深度为 \(k-15\) 的子树的 Prufer 序列(其中的值都是 \(a\) 的线性函数),并在每个询问时预处理公差为 \(d\) 的前缀部分和,递归时将根结点的 \(a\) 带入就可以算出这个子树里的和。

时间复杂度为 \(O(q2^{\frac{k}{2}})\)

\(\rule[0pt]{14.3cm}{0.1em}\)

#\(217\)\(\text{Easy Reading}\)\(\text{2020.11.01}\),自己做出)

题目大意:

给定长度为 \(l\) 的字符串 \(S\) 和一个 \(n\times m\) 矩阵,矩阵中每个格子有黑有白,求出一个 \(S\) 的子串使得根据它可以画出矩阵或报告无解,画的规则如下:

  1. 首先画笔落在任意一个格子上

  2. 然后从左到右遍历这个子串,遇到 \(u,d,l,r\) 时画笔就向上/下/左/右移动一格。

  3. 画笔经过的位置都是黑的,其他位置都是白的。

\(l\leq 10^5,\ \ n\times m\leq 10^5\)


题解:

首先把 \(S\) 中所有的 \(u,d,l,r\) 提取出来,对矩阵进行二维哈希,这个哈希要支持平移,所以只要确定两个数 \(x,y\),令黑色格子 \((i,j)\) 的哈希值为 \(x^iy^j\bmod P\) 就可以了。

接下来进行双指针,维护一个画出来恰好格子数和矩阵中格子数一样的区间,动态维护 hash 值(可以用一个 multiset 来维护横纵坐标最小值实现在判定时支持平移,再用一个 map 维护每个位置上画了几次,如果减到 \(0\) 次就会变成白色)。

时间复杂度为 \(O(l\log l+n\times m)\)

\(\rule[0pt]{14.3cm}{0.1em}\)

#\(218\)\(\text{Lunar Landscape}\)\(\text{2020.11.01}\),自己做出)

题目大意:

给定二维平面上 \(n\) 个边平行于坐标轴或对角线平行于坐标轴的整点正方形,坐标范围在 \([-1500,1500]\),求面积并。

\(n\leq 2\times 10^5\)


题解:

先处理边平行坐标轴的正方形,二维差分最后前缀和回来就可以了。

对角线平行坐标轴的正方形是一样的,另一个角度的二维差分。

最后每个格子可以统计出四个结果,分别是左上角左下角右上角右下角有没有被覆盖,如果有超过 \(2\) 个角被覆盖那么就是完全覆盖,如果有 \(2\) 个角被覆盖且不是对角,那么就是被覆盖了 \(0.75\) 个格子,如果只有一个角被覆盖,那就就是被覆盖了 \(0.5\) 个格子。

时间复杂度为 \(O(n+X^2)\),其中 \(X=3000\) 是坐标范围。

\(\rule[0pt]{14.3cm}{0.1em}\)

#\(101\)\(\text{Correcting Curiosity}\)\(\text{2020.11.06}\),自己做出)

题目大意:

给定两个字符串 \(S,T\),求出一个替换命令 \(a\to b\),其中 \(a,b\) 是字符串,使得从左到右寻找 \(S\)\(a\) 作为子串的若干次不相交的出现,每一次分别替换成 \(b\),最后能得到 \(T\),求出 \(|a|+|b|\) 最小的一组 \((a,b)\)

\(|S|,|T|\leq 2000\)


题解:

\(S\) 的每个子串哈希,离散化后用 vector 存储每个哈希值的子串按照题目所述规则从左到右的每一次需要替换的位置。

然后枚举 \(S\) 的子串 \(a\),根据 \(|T|-|S|=size\times \Delta len\),其中 \(size\) 是替换发生的次数,\(\Delta len\) 表示 \(|b|-|a|\),可以算出 \(\Delta len\),也就是可以算出对应的 \(b\),根据 \(a,b\)\(S,T\) 分成几段,分别用哈希值检验每一段是不是都相等,同时如果每一次发生替换时 \(a\) 对应的 \(T\) 中的串也相等(都是 \(b\)),就说明 \((a,b)\) 是一组可行解。

时间复杂度为 \(O(|S|^2)\)

\(\rule[0pt]{14.3cm}{0.1em}\)

#\(167\)\(\text{Interactive Sort}\)\(\text{2020.11.10}\)

题目大意:

\(1,\ldots,n\) 中的奇数和偶数分成两组并打乱顺序,得到 \(o,e\) 两数组,每次交互可以询问 \(o_i\)\(e_j\) 的大小关系,你需要用不超过 \(3\times 10^5\) 个问题求出 \(o,e\) 两数组,数据随机生成。

\(n\leq 10^4\)


题解:

首先用 \(e_1\) 和每一个 \(o_i\) 问一次,可以把 \(o_i\) 分出两份并求出 \(e_1\),然后再是 \(e_2\),两个数问完相当于把 \(o_i\) 分成三份,依此类推。

问每一个 \(e_i\) 时,首先在当前分出的每一段 \(o_i\) 中二分找到它可能输入哪一段(或两段),然后将这一段或两段中的 \(o_i\) 都问一遍,就可以找到确切位置并多分一份 \(o_i\) 出来了。

在随机数据情况下,询问 \(O(n\log n)\) 次。

\(\rule[0pt]{14.3cm}{0.1em}\)

#\(109\)\(\text{Knapsack Cryptosystem}\)\(\text{2020.11.11}\)

题目大意:

有一个未知数组 \(a_{1\ldots n}\),满足 \(\sum\limits_{i=1}^{k-1} a_i< a_k\),且 \(\sum\limits_{i=1}^n a_i< q=2^64\),并有一个奇数 \(r\),令 \(b_i=r\times a_i\),对于一个 \(n\)\(0,1\)\(S\),定义其加密结果为 \(\sum\limits_{S_i=1} b_i \bmod q\),请你对给定的加密结果解密。

\(n\leq 64\)


题解:

看上去是 Not P 的,考虑进行数据分治,复杂度有机会摊成 \(O(2^{\frac{n}{3}})\)

  1. \(n\leq 42\),直接折半搜索,复杂度 \(O(2^{\frac{n}{2}})\)

  2. \(42<n\leq 64\),考虑到 \(q>\sum\limits_{i=1}^n a_i>2^{n-1}\times a_1\),所以其实 \(a_1\leq 2^{64-n}\),那么我们可以考虑枚举 \(a_1\),当 \(a_1\) 确定时我们可以再考虑确定 \(r\),根据 \(a_1\)\(b_1\) 我们可以确定 \(r\) 的某些位(准确地来说,是去掉 \(a_1,b_1\) 的公共后缀 \(0\) 后剩余的位数),剩下 \(r\) 中未确定的位再暴力枚举就可以了,因为这个未确定位数就等于 \(a_1\) 后缀 \(0\) 的个数,求和后不影响 \(O(2^{64-n})\) 的复杂度。

二者综合,可以得到一个复杂度不高于 \(O(2^{\frac{n}{3}})\) 的做法。

\(\rule[0pt]{14.3cm}{0.1em}\)

#\(226\)\(\text{Maze Reduction}\)\(\text{2020.11.11}\)

题目大意:

给定 \(n\) 个结点的无向图,每个点的所有相关边形成一个有向环(即可以区分正逆和距离),如果从两个不同的结点出发,无论如何行动都无法辨别出自己从哪里出发,则称它们等效相同,按此标准求出所有等价类。

\(n\leq 100\)


题解:

数据比较厉害,为了搞掉一些卡常毒瘤数据,所以我先特判了一下,如果所有点度数相同,直接返回所有点都等价。

可以设计一种简单的 DP,假想我们可能在两个不同的房间,并且上一步分别从某个房间走来,那么需要知道的信息还有:上一步分别是从各自的顺时针第几个边走进来的,初步可以想到 \(dp(i,j,k,l)\) 表示分别在 \(i,k\),分别是从第 \(j,l\) 条边走进来,能否分辨。但是考虑到 \(dp(i,j,k,l)\)\(dp(i,j+x,k,l+x)\) 其实等价,所以可以省掉一维,只用 \(dp(i,j,k)\),而令 \(l=1\)

但是这样不太好转移,我们不妨加一个步数的限制,即 \(dp(i,j,k,x)\) 表示在上述的 \((i,j,k)\) 状态下,走 \(x\) 步以内能否分辨,这样我们便能从 \(x-1\) 的状态转移过来了。

这里的 \(x\) 上限我设成了 \(50\),基本应该是没有问题的。

时间复杂度为 \(O(nm^2\times X)\),其中 \(m\) 是边数,\(X=50\) 是步数上限,这种写法非常卡。

\(\rule[0pt]{14.3cm}{0.1em}\)

#\(106\)\(\text{Binary vs Decimal}\)\(\text{2020.11.11}\)

题目大意:

求出第 \(n\) 小的满足其十进制表示是其二进制表示的后缀的数。

\(n\leq 10^4\)


题解:

写个高精度,然后搞个 \(\text{priority_queue}\) 暴搜即可,每次取出一个满足条件的数就在前面加 \(0\)\(1\) 都试试,可以发现答案不会超过 \(200\) 位。

时间复杂度不明。

\(\rule[0pt]{14.3cm}{0.1em}\)

#\(159\)\(\text{Mole Tunnels}\)\(\text{2020.11.11}\)

题目大意:

给定 \(n\) 个点的完全二叉树,每个点有最多能容纳鼹鼠的上限,现在依次来了 \(m\) 只鼹鼠,每个鼹鼠有个初始位置,对于每个 \(i\leq m\) 求出:给前 \(i\) 个鼹鼠分别安排到一个点,不超过每个点容纳上限时,所有鼹鼠移动距离和的最小值。

\(n,m\leq 10^5\)


题解:

用模拟费用流来考虑,然后可以用可回退贪心来解决。

每次给新来的鼹鼠找一个最近的可以容纳的点然后塞进去,随后将这条路径上边权取反即可。

可以用一个类似 DP 数组一样的东西维护每个点子树内最近的可以容纳鼹鼠的点,由于是完全二叉树,所以询问可以暴力跳祖先。

时间复杂度为 \(O(m\log n)\)

\(\rule[0pt]{14.3cm}{0.1em}\)

#\(251\)\(\text{Can't stop playing}\)\(\text{2020.11.11}\)

题目大意:

依次给定 \(n\) 个长度为 \(2\) 的非负整数幂次的方块,你可以依次选择将它们放在当前序列的最左边或最右边,每当两个相邻方块长度相同时就会合成一个长度是两倍的大方块,求是否可以使得最终结果合成一块。

\(nL\leq 5\times 10^8\),其中 \(L\) 是方块总长,不超过 \(2^13\)


题解:

如果想要最后合成一块,那么任何时候游戏序列必须是单峰的(否则位于谷中的方块永远无法和两边合并),所以抓过状态数不过 \(2^{26}\) 种,然后我们又发现合成操作不影响长度总和,所以假设前 \(i\) 个方块长度和为 \(S_i\),那么我们只需要记录当前序列前面递增那一部分的长度和 \(S\),用 \(S_i-S\) 就得到了后面那部分递减的长度和,因此状态数又降到了 \(2^{13}\)

然后分几类转移即可,特别注意递增部分或递减部分为空的情况,同时如果 \(S_n\) 不是 \(2\) 的幂次那么答案显然是否。

时间复杂度为 \(O(nL)\)

\(\rule[0pt]{14.3cm}{0.1em}\)

#\(169\)\(\text{Virus synthesis}\)\(\text{2020.11.11}\)

题目大意:

给定由 \(\texttt{A,C,G,T}\) 构成的长度为 \(n\) 的字符串,问最少用几步可以由空串构造出来,每一步可以:

  1. 在开头或末尾加一个字符;

  2. 将当前串翻转并接在当前串的前面或后面。

\(n\leq 3\times 10^7\)


题解:

考虑最后一次翻转,形成的一定是一个回文串,所以我们不妨对字符串的所有本质不同回文串进行 DP。

在 PAM 上,设回文串 \(S\) 的最长回文真后缀为 \(S_1\),最长的长度不超过一半的回文串为 \(S_2\),那么 \(S\) 要么由 \(S_1\) 加字符得到,要么由 \(S_2\) 加字符并翻转拼接得到,而求这两个东西是 PAM 标配,所以可以直接 DP 出结果。

枚举一下最后一次翻转形成的回文串并看一下后面还要几次操作,就可以得到答案。

时间复杂度为 \(O(n)\)

\(\rule[0pt]{14.3cm}{0.1em}\)

#\(127\)\(\text{Lost Logic}\)\(\text{2020.11.11}\)

题目大意:

给定三个长度为 \(n\)\(0,1\) 串,构造一组条件数不超过 \(500\) 的 2-SAT 条件使得三个串是唯一的三组解,或报告无解。

\(n\leq 50\)


题解:

如果某一位上三个串都是 \(0\) 或者都是 \(1\),那么这一位相当于没用,直接令它为 \(0\)\(1\) 即可。

否则,这一位一定是两个一样,另外一个不同,那么我们就把它划进这两个一样的串构成的一个等价类里,于是会有三个等价类(在 \(1,2\) 中一样,在 \(1,3\) 中一样,在 \(2,3\) 中一样),于是我们令每个等价类中的情况唯一。

最后我们还要判定一下,如果每一位都取那个两个相同的数字,得到的串是否属于一开始的三个串,如果不属于那么无解(无法构造条件使它不满足),否则刚才已经构造出了合法解。

时间复杂度为 \(O(n)\)

\(\rule[0pt]{14.3cm}{0.1em}\)

#\(143\)\(\text{Jump}\)\(\text{2020.11.11}\)

题目大意:

你要猜一个长度为偶数 \(n\)\(0,1\)\(S\),每次询问可以给出一个长度为 \(n\)\(0,1\)\(T\),如果 \(S\)\(T\) 中对应相同的位数恰好为 \(n\)\(\dfrac{n}{2}\) 的话就会返回这个值,否则会返回 \(0\),用不超过 \(n+500\) 次操作得到 \(S\)

\(n\leq 1000\)


题解:

考虑如果已经得到一个能问出 \(\dfrac{n}{2}\)\(T\),如何得到答案。

如果将 \(T\) 中的 \(i,j\) 两位分别反转,得到 \(T'\),询问 \(T'\),如果得到 \(0\),说明 \(T\) 里面这两位和 \(S\) 都相同或都不同,如果得到 \(\dfrac{n}{2}\) 就说明这两位有一位相同而另一位不同,令 \(i=1\),问 \(n-1\) 次就可以知道:当第 \(1\) 位与 \(S\) 相同或不同时,每一位与 \(S\) 相同或不同。

于是候选的 \(S\) 只剩两个,都问一次就知道答案了。

问题在于如何找出这个 \(T\),然而这个问题的答案是显然的:随机问,似乎是因为 \(\lim\limits_{n\to \infty} \dfrac{\binom n {\frac{n}{2}}}{2^n}=\sqrt n\),所以只要大概 \(50\) 次以内就可以得到这个 \(T\)

询问次数大约为 \(n+\sqrt n\)

\(\rule[0pt]{14.3cm}{0.1em}\)

#\(210\)\(\text{Sensor Network}\)\(\text{2020.11.12}\)

题目大意:

给定 \(n\) 个平面上的点,两点距离 \(\leq d\) 就连边,求最大团。

\(n\leq 100\)


题解:

解法一:当成普通图,random_shuffle 贪心加点或者搞点暴搜,可以通过。

解法二:靠谱多项式复杂度解法:

枚举两个点,令它们的距离 \(d_0\) 是团中最大距离,那么团中剩余的点的范围就是以它们连线段为公共底边的两个等边三角形,可以发现一个三角形内的点两两都有连边,所以要求这个图的最大团,不妨取反图求独立集,这样只有分属两个三角形的点可能有边,也就是一个二分图,做一遍最大匹配即可。

时间复杂度可做到 \(O(n^4)\) 左右。

posted @ 2020-10-13 23:11  ix35  阅读(2973)  评论(6编辑  收藏  举报