jiangly的博客

博客

The 3rd Universal Cup. Stage 24: Poland 题解

2025-01-19 01:15:52 By jiangly

A. Acronym

枚举每个单词判断即可。

B. Baggage

考虑两个包裹分别从 u 运到 v,中途没有同时运送两个包裹,则方案形如:

  • 包裹 1 ua1,空手 a1u,包裹 2 ub1,空手 b1a1,包裹 1 a1a2,空手 a2b1,包裹 2 b1b2,……,包裹 1 akv,空手 vbk,包裹 2 bkv

可以发现这样的方案可以重新排列成:

  • 包裹 1 ua1a2akv
  • 空手 vbkak1bk2a1u
  • 包裹 2 ub1b2bkv

因此代价不小于 2dis1(u,v)+dis0(v,u),其中 disc(x,y) 是从 xy,只能经过容量不少于 c 的边的最短距离。

2dis1(u,v)+dis0(v,u) 显然是一个合法方案,因此只需将 uv 连上距离为 2dis1(u,v)+dis0(v,u)、容量为 2 的边,然后求容量 等于 2 的最短路即可。

时间复杂度 O(n3)

C. Cows

二分答案,转化为判定是否能够在 x 分钟内吃完所有的草。

按照 i 从小到大的顺序,维护如下的状态:考虑下标在 [i,n] 中的牛,且满足下列状态之一

  • 存在不超过 2 个时间区间,牛 i1 会在这些时间区间内帮牛 i 吃草。有两种情况:
    • 如果在时间 t 吃完了所有了牛 i 的所有草,则牛 i 可以在 [t,x] 时间内帮牛 i+1 吃草。
    • 否则,设剩余的草的数量为 a,则牛 i+1 需要在 [xa,x] 时间内帮牛 i 吃草。
  • 存在一个时间区间 [l,r],牛 i 需要帮牛 i1 吃草。有两种情况:
    • 如果牛 i 自己能够在 l 时间之前吃完所有草,设吃完草的时间为 t,则牛 i 可以在 [t,l][r,x] 时间帮牛 i+1 吃草。
    • 否则,设在 l 时刻剩余的草的数量是 a,则牛 i+1 需要在 [la,l] 时间内帮牛 i 吃草。

如果最终牛 n 不能吃完所有的草则说明答案大于 x

时间复杂度 O(nlogH)

D. Diminishing Fractions

分数的分母显然不超过 M=lcm{1,2,,n},而分子最小是 1,因此可能的最小值是 1/M。我们考虑通分,在 mod 意义下构造 1,然后只需减去整数部分即可(因为已知分子是 1,可以直接用浮点数计算)。

\le n 的所有极大素数幂分别为 p_1^{e_1},p_2^{e_2},\ldots,p_k^{e_k},则 M=\prod_{i=1}^k p_i^{e_i}。现在我们想要找到 a_i\in [0,p_i^{e_i}) 满足 \left(\sum_{i=1}^k a_i(M/p_i^{e_i})\right)\bmod M=1

这可以通过 CRT 构造:我们希望 x\bmod p_i^{e_i}=1,所以令 a_iM/p_i^{e_i} 在模 p_i^{e_i} 意义下的逆元即可。

因为 \sum n 很大但 N=\max n 不大,我们在每组数据中分别进行求逆,则只需按照 n 从小到大的顺序维护 \prod_{j\ne i}p_j^{e_j}\bmod p_i^{e_i}。每次增加一个素数幂时,都可以在 O(k)=O(n/\log n) 的时间内完成维护。

总时间复杂度 O\left(\frac{N^2}{\log^2N}+\sum n\right)

E. Express Rotations

考虑一个指向序列开头的指针,初始在 a_1 之前。这样操作可以转化为指针循环向前移动、循环向后移动和删除指针之后的第一个数。

考虑设 \mathrm{dp}(v,i) 表示删除了所有 \ge v 的数,指针的位置在 i 的最小代价。我们可以认为只有需要删除一个数时需要移动指针,因此有用的状态一定满足 a_i=v,因此总状态数是 O(n) 的。

v+1v 的转移,首先从之前所有有用的位置转移到所有 a_i=v 的位置,这只需要先转移到前后相邻两个位置,然后再正反分别扫两遍更新。计算从位置 i 向后移动到位置 j 的代价,也就是计算 [i,j) 中所有 \ge v 的数的总和,可以用树状数组在 O(\log n) 时间内计算。

接下来考虑删除所有等于 v 的数。可以发现指针的移动要么是先往前再往后,要么是先往后再往前。如果是先往前再往后,可以认为所有数都是在往后的过程中被删除,因此直接用指针移动的代价减去所有 =v 的数的总和来更新即可。如果是先往后再往前,因为往后移动的过程中,删除一个数不需要代价,但往前移动的过程中需要先移动到数之前再删除,所以有 v 的代价。我们可以将少的代价在往后移动的过程中计算,即从 i 移动到 j 的代价是 [i,j) 中所有 >v 的数的总和减去 v。这会导致一个问题:移动的代价可能是负数,导致一直在环上绕圈。这是因为,我们只有在第一次删除一个数的时候会带来总代价的减少,但直接在环上转移忽略了这个限制。一个解决方案是使用单调队列,限制只能往后移动 \mathrm{cnt}_v-1 次。

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

F. Frogs

考虑计算 p=n 的答案。令 b_i=a_{i+1}-a_i(下标都是 \bmod n 意义下的),即青蛙 i 要追的青蛙和它坐标的差。如果 b_i\ge 0,则青蛙 i 会向右跳,否则会向左跳。考虑 b_i 的变化,当 b_i\ge 0b_{i+1}< 0 时会减去 2k,当 b_i< 0b_{i+1}\ge 0 时会加上 2k。可以发现,在有限轮之后,所有的 b_i 都会落入 [-2k,2k) 内。此后 \{b_i\} 一定会进入一个循环,我们希望判断在一个循环内,青蛙的坐标是否不变。注意到当所有 b_i\in[-2k,2k) 时,b_i 的符号(负数还是非负)只和上一个时刻 b_{i+1} 的符号有关,因此在循环中负数的个数是始终不变的,因此我们只需判断负数的个数是否等于非负数的个数。

我们只需判断是否有 n/2=\sum[b_i< 0]=\frac{1}{2k}\sum(b_i\bmod 2k-b_i)。注意到 \sum b_i=0,而 \sum (b_i\bmod 2k) 是常数,因此只需判断是否有 \sum(b_i\bmod 2k)=\sum((a_{i+1}-a_i)\bmod 2k)=nk 即可。

对于所有的 p 计算答案,也只需要在 p 增大的时候维护这个和。

时间复杂度 O(n)

G. Game MPO

将所有的 M 和 P、O 和 O 连边,则只需从所有大写字母开始 BFS 即可得到最终状态。

H. High Jump

最优策略可以表示成 a_1< a_2<\cdots< a_k,依次挑战高度 a_1,a_2,\ldots,a_k。分数的期望是 p_{a_1}a_1+p_{a_1}p_{a_2}(a_2-a_1)+p_{a_1}p_{a_2}p_{a_3}(a_3-a_2)+\cdots。令 a_0=0,这个式子也可以写成 f(i)=(f(i+1)+(a_{i+1}-a_i))p_{a_{i+1}},答案即为 f(0)

考虑从后往前 DP,则 \mathrm{dp}(i)=\max_{j>i}\{(\mathrm{dp}(j)+j-i)\cdot p_j\},可以用凸包优化转移。

时间复杂度 O(n)

I. Imbalanced Teams

显然最大值等于前 k 大的和减去前 k 小的和。在确定了选择的数的可重集后,只需乘上对应的组合数即可。注意如果两个队伍有相同的数,还需要计算分组的方案数,并且当所有数全相等时,两组是本质相同的,方案数需要除以 2

时间复杂度 O(n)

J. Just Zeros

考虑维护 f(S) 表示翻转的行的集合是 S 的情况下,还需要多少步能够将所有数变成 0。也就是翻转行后,每一列的 \min\{c,1+h-c\} 之和。通过 f(S) 可以在 O(2^h) 时间内计算答案。

如何在操作后维护 f(S)

  • P 和 K 操作都只会影响一列,可以对每个 S 重新计算该列的贡献。
  • R 操作只需将 f(S)f(S\oplus \{i\}) 交换。注意需要打一个第 i 行取反的标记,在另外两种操作中需要用到。

时间复杂度 O((w+q)2^h)

K. Kindergarten Square

通过两行的差可以求出 w,而 h 越大越好,然后判断是否满足条件即可。

L. Looping RPS

考虑对 s_i^\infty 建立 Trie,则三个人形成一个环当且仅当它们在同一个点的三个不同子树内。因此建立 Trie 后可以直接枚举 LCA 计算贡献。

建立 Trie 分为两步:排序,然后计算相邻串的 LCP 并建立笛卡尔树。

难点主要在于排序,直接按照 a+b< b+a 比较可能导致时间复杂度变为 \Omega(n|s|)。我们希望比较两个串的复杂度是 O(\min\{|a|,|b|\}),则总复杂度为 O(\sum|s_i|\log n)。不妨设 |a|\le |b|。如果 a 不是 b 的前缀则可以直接比较,否则我们需要求 bb[|a|:] 的 LCP,这可以通过预处理每个串的 Z 函数后 O(1) 得到。

时间复杂度 O(\sum |s_i|\log n)

The 3rd Universal Cup. Stage 15: Chengdu 题解

2024-11-07 19:41:12 By jiangly

A. Arrow a Row

一个串能通过操作得到的必要条件包括:

  • > 开头。
  • >>> 结尾
  • 至少有一个 -

而事实上上述条件也是充分的。如下是一个可能的构造:

  • 当目标串不以 ->>> 结尾时,重复操作 (n-4,5),这样可以视作删除了最后一个字符。最终目标串一定是以 ->>> 结尾。
  • 枚举 i1n-4,如果 s_i- 则不操作,否则令 ji 之后第一段连续的 - 的结尾位置,操作 (i,j-i+4)

操作次数显然不超过 n,时间复杂度也为 O(n)

B. Athlete Welcome Ceremony

先求出有 xaybzc 的好序列,然后做一个三维前缀和,即可在 O(1) 时间内回答询问。

\mathrm{dp}(x,y,z,\mathrm{ch}) 表示有 xaybzc,且以 \mathrm{ch} 结尾的好的前缀个数。因为前缀长度就是 x+y+z,枚举下一个字符即可 O(1) 转移。

时间复杂度 O(n^3+Q)

C. Chinese Chess

对状态集合(状态为 (位置,类型))进行搜索,枚举询问的格点,然后根据距离分成若干个子集。实现后可以发现,即使对于全部位置都可行的情况,也只需要 3 步即可确定类型。因此总的搜索节点数不超过 90^3,如果速度还是很慢,可以考虑打表 3 步的所有决策,这样只需要搜索 2 步以内的情况。搜索的时候可以顺便记录每个状态的决策。

实现时注意每种棋子的移动方式。

D. Closest Derangement

注意到当 p_i\ne i 时,\sum_{i=1}^{n}|p_i-i|\ge n

n 是偶数时,最小值可以取到 n,且只在排列 2,1,4,3,\ldots,n-1 取到。

n 是奇数时,根据奇偶性,最小值为 n+1。可以在排列 \ldots,2k+2,2k+3,2k+1,\ldots\ldots,2k+3,2k+1,2k+2,\ldots 取到(前后的部分和偶数时一样,相邻数两两对换)。这样的排列共 n-1 个,现在我们要找到 p_{q_1},p_{q_2},\ldots,p_{q_n} 的字典序第 k 小,只需快速实现比较两个排列,然后调用 nth_element 即可。

比较两个排列 p_1,p_2 只需找到最小的 i 使得 p_{1,q_i}\ne p_{2,q_i}。注意到对于任意两个不同的好的排列,对应不同的位置一定是一个区间加上边界的 O(1) 个零散点,只需在 q^{-1} 上 RMQ,然后暴力统计零散点即可。

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

E. Disrupting Communications

要求的是和 uv 的路径相交的连通块数。考虑用总的连通块数减去和 uv 的路径不相交的连通块数。

l=\mathrm{LCA}(u,v),则和 uv 的路径不相交的连通块有以下两种:

  • 完全在 l 的子树外部。
  • 完全在 l 的子树内部,且连通块的根不在 uv 的路径上。

f(x),g(x) 分别表示以 x 为根的连通块数和 x 子树内的连通块数,则转移如下: f(x)=\prod_{y\in \mathrm{ch}(x)}(1+f(y))\\ g(x)=f(x)+\prod_{y\in \mathrm{ch}(x)}g(y) 同理,令 f_o(x),g_o(x) 表示删除 x 的子树,且以 x 的父亲为根的树对应的答案。注意这里计算 f_o(x) 不能使用除法(可能会有除以 0 情况),而应该预处理前后缀乘积。

再令 \mathrm{sum}_f(x)x 到根的路径上的所有点 yf(y) 的和,则答案为 g(1)-g_o(l)-g(l)+\mathrm{sum}_f(u)+\mathrm{sum}_f(v)-2\mathrm{sum}_f(l)+f(l) 时间复杂度 O(n+q\log n)

F. Double 11

对于一个分组方案,设每组的个数和总和分别为 c_is_i。要在 \sum_{i=1}^mk_i\cdot s_i\le 1 的前提下最小化 \sum_{i=1}^m \frac{c_i}{k_i},一定有每组的 \frac{\mathrm{d}(c_i/k_i)}{\mathrm{d}(k_i\cdot s_i)} 是相等的,即 k_i 正比于 \sqrt{\frac{c_i}{s_i}}。令 S=\sum_{i=1}^m \sqrt{c_is_i},则 k_i=\frac{\sqrt{c_i/s_i}}{S}\sum_{i=1}^m \frac{c_i}{k_i}=\sum_{i=1}^m \sqrt{c_i s_i}S=S^2。因此题目所求的答案就是 S

注意到确定每个分组的大小之后,每个系数 \sqrt{c_i} 就确定了,因此一定是把较小的数分到较大的组。因此我们可以将数组排序,从而每一组一定是一个区间。

考虑排序后的三个区间 (c_1,s_1),(c_2,s_2),(c_3,s_3)s_1/c_1\le s_2/c_2\le s_3/c_3)。事实上我们有如下不等式: \sqrt{(c_1+c_2+c_3)(s_1+s_2+s_3)}+\sqrt{c_2s_2}\ge \sqrt{(c_1+c_2)(s_1+s_2)}+\sqrt{(c_2+c_3)(s_2+s_3)} 一个证明如下:

  • 移项,变为 \sqrt{(c_1+c_2+c_3)(s_1+s_2+s_3)}-\sqrt{(c_1+c_2)(s_1+s_2)}\ge \sqrt{(c_2+c_3)(s_2+s_3)}-\sqrt{c_2s_2}
  • c_1\gets c_1+c_2,s_1\gets s_1+s_2,这不会改变作为前提的不等关系,只需证 \sqrt{(c_1+c_3)(s_1+s_3)}-\sqrt{c_1s_1}\ge \sqrt{(c_2+c_3)(s_2+s_3)}-\sqrt{c_2s_2}
  • a_i=s_i/c_if_i(x)=\frac{\partial\sqrt{(c_i+x)(s_i+a_3x)}}{\partial x}=\frac{a_3(1+2x)+a_i}{2\sqrt{(1+x)(a_i+a_3x)}},则上述不等式等价于 \int_0^{c_3}f_1(x)\mathrm{d}x\ge \int_0^{c_3}f_2(x)\mathrm{d}x,只需证明对任意 x\ge 0 都有 f_1(x)\ge f_2(x)。再次求导会发现 \frac{\partial f_i(x)}{\partial a_i}(0,a_3) 上恒为负,因此命题得证。

因此转移函数是 Monge 的,可以用 WQS 二分 + 决策单调栈在 O(n\log n\log\epsilon^{-1}) 的时间内求解。二分时需要注意精度问题,应当需要 long double。

G. Expanding Array

考虑序列中相邻的两个数 x,y。首先通过插入两个数的 XOR 可以得到序列 x,y,x\oplus y,x,y,也就是可以无限复制一对相邻的数,使得操作时不会将其消耗掉,因此我们可以把操作看成选中一对数 (x,y),将 (x,x\operatorname{op}y)(x\operatorname{op}y,y) 加入可能的相邻数的集合。不断重复这样的操作,最后就能得到所有可能出现的相邻数对,自然就能算出可能出现的不同数的个数。

接下来分析一下这样的数对的个数,序列中本身有 n-1 对相邻的数,可以看作是独立的。对于相邻的两个数 x,y,因为进行的都是位运算,所以运算得到的任何一个数都可以看作两个位的一个函数 f(x,y),其中 x,y,f(x,y)\in\{0,1\},且 f(0,0)=0,因此至多有 2^3=8 种可能。数对的数量自然不会超过 8^2\cdot n。事实上,打表可以发现这 8 种可能的数都是可以产生的,因此直接枚举然后去重即可。

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

H. Friendship is Magic

先考虑如何计算一个 f(x)。当分割点向右移时,显然左侧单调递增,右侧单调递减。考虑找到最后一个左侧小于右侧的位置。即把 x 划分为 l,m,r,其中 m 是一个数位,满足 10l+m\ge rl < m\cdot 10^{|r|}+r,则 f(x)=\min\{10l+m-r,m\cdot 10^{|r|}+r-l\}

现在考虑求 f(x) 的和,枚举 m,|r|,然后枚举 f(x) 取哪边,例如取 10l+m-r,则有限制 0\le l\le L\\ 0\le r\le R\\ 10l+m\ge r\\ l < m\cdot 10^{|r|}+r\\ 10l+m-r\le m\cdot 10^{|r|}+r-l (l,r) 放到平面上,则这些限制都是半平面,且斜率只有 0,\infty,10,1,\frac{11}{2} 这几种,通过分类讨论可以求出半平面交中所有点的 l,r 之和,进而计算出答案。也可以直接枚举 l 的奇偶性,使得斜率都是整数,然后找到半平面的所有交点并分段,每一段中固定 l 的答案都是关于 l 的二次函数,进而通过插值求总和。

时间复杂度 O(|\Sigma|\cdot \log _{|\Sigma|}n),其中 |\Sigma|=10,且常数较大,需要精细实现。

I. Good Partitions

k 是好的当且仅当对于任意 i=1,2,\ldots,n-1,如果 i 不是 k 的倍数,则 a_{i+1}\ge a_i

也就是说,令所有满足 a_{i+1}< a_ii 的 GCD 为 d,如果 d=0k=1,2,\ldots,n 都是好的,否则只有 d 的因子是好的。

单点修改会导致一些 i 被插入或删除,可以使用线段树维护 GCD,并且预处理每个数的因子个数来快速回答询问。

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

J. Grand Prix of Ballance

按照题意模拟即可。注意忽略掉非当轮比赛和消息和每位选手第二条及以后的消息。

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

K. Magical Set

\Omega(x) 表示 x 的质因子数量(计算重数)。设初始集合为 S,结束集合为 T,则总的操作次数不会超过 \sum_ {x\in S}\Omega(x)-\sum_{x\in T}\Omega(x) 而只要每次恰好除掉一个质因子,这个上界就是能够达到的。而事实上,只要 ST 存在一个完美匹配(x\in S 匹配 y\in T 当且仅当 y\mid x),就一定存在达到这个上界的操作序列。具体来说,我们可以通过如下方法构造这个操作序列:

  • 对于 x\in S,设 M(x) 是完美匹配中和 x 匹配的 T 中的数。如果对于任意 x\in SM(x)=x,则构造完成。否则找到 M(x)\ne x 的最小的 x,令 px/M(x) 的任意一个质因子,然后重复以下过程:

    • 如果 x/p\notin S,则将 x 变为 x/p,这就完成了一次操作。
    • 如果 x/p\in S,则说明 M(x/p)=x/pM(x)\ne x/p,我们可以交换 M(x)M(x/p),然后令 x/p 成为我们考虑的 x,重复这个过程。

      由于这个过程中 x 不断变小,因此一定会终止。

因此,问题变成了为 S 中的每个数 x 选择一个因子 y,使得这些因子互不相同,且最小化它们的 \Omega(y) 的和。我们找到每个数的所有因子,如果因子超过 n 个,我们事实上只需要保留 \Omega(y) 最小的 n 个(即使有 n-1 个被其他数选择,还会剩下一个),然后在 x_Sy_T 之间连一条边。

最终我们形成了一个左部 n 个点,右部不超过 n^2 个点,不超过 n^2 条边的二分图,要找一个左部完美匹配,使得右部选择的点的 \Omega(y) 之和最小。可以将右部的所有点按照 \Omega(y) 从小到大排列,然后用匈牙利算法寻找匹配。这个算法的正确性来自于拟阵。而只要在未找到匹配时,不初始化算法中的 vis 数组,算法的复杂度就是 O(|M|\cdot |E|),其中 |M| 是匹配大小,|E| 是边数。

时间复杂度 O(n\sqrt {A}+n^3)

L. Recover Statistics

只需构造 n=100 个数,前 50 个数为 a,第 5195 个数为 b,第 9699 个数为 c,第 100 个数为 c+1 即可。

M. Two Convex Holes

注意到多边形的投影实际上只是多边形进行了平移和缩放,进行一些坐标变换后可以转化为两个多边形分别做匀速直线运动。进一步可以转化成多边形 P_2 的速度为 0P_1 的速度为 (0,1)

我们可以将多边形的面积以所有顶点的 x 坐标分成 O(n) 段,则每一段中多边形的上下边界都是线段。进一步容斥成 (上边界 - 下边界),则只需要计算形如 \min\{ax+b+t,cx+d\} 的函数的积分。这个函数可以按照 t 分成三段,每段都是二次函数。因此面积可以表示成 O(n) 段的分段函数,每一段都是二次函数。再预处理一下每一段的前缀和,询问时只需二分出端点所在的段,然后加上边界部分即可。

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

The 3rd Universal Cup. Stage 10: West Lake 题解

2024-10-04 22:24:42 By jiangly

A. Italian Cuisine

假设最后切的块是 p_ip_j,其中菠萝在直线 p_ip_j 的左侧。

枚举 i,则 j 应该在满足菠萝在直线 p_ip_j 左侧的前提下尽可能大(我们认为 p_{n+i}=p_i,所以始终有 j> i)。这个 j 要满足的条件具有单调性,并且当 i 增大时,最大的 j 也不降,所以可以用双指针维护这个过程。

算面积时只需求每条边的叉积的和。

时间复杂度 O(n)

B. Generated String

考虑如果给的都是直接的串而不是一些子串的拼接怎么做。对所有串建立 Trie,则 st 的前缀当且仅当 ts 的子树中,在 DFS 序上就是 t 在一个区间内。对反串建立 Trie 就可以解决后缀。因此询问给定前缀后缀的串的个数实际上就是一个二维偏序,加上时间维度之后就是三维偏序,可以在 O(n\log^2 n) 时间内解决。

现在变成给一个子串的拼接,唯一的区别就是没法直接建 Trie。只要我们能够把 Trie 建出来,后面的做法没有区别。事实上建立 Trie 也并不复杂,只需要将所有串按字典序排列,然后求出相邻两个的 LCP 长度,然后类似建虚树的方法,就能建出这些串的压缩 Trie。注意这里排序的时候,如果只是用后缀数组求 LCP 跳过一段,比较复杂度是 O(k+l),其中 k,l 分别是两个字符串的段数,则复杂度仍然可能达到 \Omega (n^2)。一个解决方法是,使用归并排序,并且递归过程中也计算相邻串的 LCP,然后在归并的过程中,利用已经计算的 LCP 避免重新从头开始比较。另一个解决方法是按照段数从小到大插入排序。在预处理后缀数组,支持 O(1) 求 LCP 的前提下,两种方法的复杂度都是 O(\sum k_i \log n)

总时间复杂度 O(n\log n+q\log ^2q+\sum k_i\log q)

C. Permutation

考虑分治,每次将数列分成两半,然后确定每个数在哪一半。之后递归处理两个区间。

由于这道题的交互器是非适应性的,即排列是预先确定的,所以可以采用随机化。考虑将所有数 shuffle,然后每次询问两个数 x,y,前一半是 x,后一半是 y(区间以外的部分随便用 xy 填充,不会有贡献)。答案有三种可能:

  • 答案是 0,说明 x 在后一半,y 在前一半。
  • 答案是 1,说明 x,y 在同一侧,但不知道是哪一侧。
  • 答案是 2,说明 x 在前一半,y 在后一半。

对于答案是 0,2 的情况,能够直接确定两个数。对于答案是 1 的情况,可以删掉 x,y 的其中一个,用另一个继续进行询问。

分析一下询问次数,因为排列随机,近似可以看成每个数均匀独立在左右之间随机。每次询问有 1/2 的概率确定 2 个数,1/2 的概率确定 1 个数,因此每次期望确定 3/2 个数,故期望询问次数约为 2n/3

因此总的询问次数大约为 \frac{2}{3}n\log n。加上一些剪枝(例如当一侧已经满时不继续询问)后,实测 n=1\,000 时大约需要 6\,000 次询问。

D. Collect the Coins

二分答案,可以在线性时间内判断能否满足。

考虑按照时间从前往后,维护每个时刻,两个机器人可能的位置集合。事实上,一定可以表示成其中一个机器人在 [l_1,r_1],另一个在 [l_2,r_2](不区分两个机器人)。

初始时两个区间都是 [1,10^9]。对每个事件进行模拟:

  • 当时间前进 t 时,两个区间都往两侧扩展 v\cdot t
  • 当在位置 c 出现一个硬币时:
    • 如果没有区间包含 c,则不可能。
    • 如果有一个区间包含 c,则对应区间变成 [c,c]
    • 如果两个区间都包含 c,则任何一个机器人都可以收集硬币,而另一个机器人可能的位置是 [l_1,r_1]\cup [l_2,r_2]。因为两个区间有交,因此结果还是一个区间。

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

E. Normal Friends

不妨设线段树大小为 n+1,且根的分割点为 n。这样做的好处是,对于区间 [1,x] 的翻转操作等价于找到 DFS 序第 x+1 个叶子,然后将其到根的路径上的所有左子树整体翻转(最高的变到最低的,依此类推),并且内部所有左右儿子交换。

这样的操作实际上可以用 LCT 来完成。首先考虑怎么找到这条链,分成两步,分别是找到 DFS 第 x+1 个叶子和对其进行 access 操作。

第一步需要在每条实链上用 splay 额外维护所有点的左/右子树(按照深度),以及哪些点有左/右儿子(当然是通过维护子树内有多少个点有左/右儿子)。这里我们假设每条实链的底端都是叶子。找 DFS 第 k 个叶子的步骤如下:

  • L= (所有左子树中叶子个数的和)。
  • 如果 k\le L,则在所有左子树中找到第 L 个叶子所在的子树,然后递归。
  • 如果 k=L+1,则第 k 个叶子就是这条链的底端。
  • 如果 k>L+1,则在所有右子树中找到(自底向上)第 L 个叶子所在的子树,然后递归找其中的第 k-L-1 个叶子。

找到叶子之后,我们需要进行 access 操作,具体步骤如下:

  • 我们不对每条链记录它的父亲(因为之后会有翻转操作,父亲没法维护),而是在找叶子的过程中,记录经过的路径,并且找到每条链切换时要接上的父亲。也就是找到链上第 k' 个有左/右子树的结点。
  • 自底向上,如果要把 x 接上 y,首先要将 y 和其目前的儿子 z 断开。在这同时需要将左/右儿子同时分成两部分,对应断开之后的两条链,并把 z 加入左/右儿子的列表(在这里更新 z 的子树叶子数)。
  • xy 所在链的左/右儿子列表中删除,将 yx 所在链的左/右儿子列表拼接,并将 x 接到 y 上。

经过上面的两个步骤我们得到了一条链,询问的答案就是链的左子树的个数。下一步就是将链的左子树翻转,这又分成两个部分:

  • 首先是将左儿子的列表整体翻转,这可以直接通过打翻转标记实现。
  • 对每个左/右儿子,将其子树镜像,这对应着交换它所在链的左/右儿子列表,并且镜像它的所有左/右儿子,同时维护的信息(有多少个点有左/右子树)也需要交换。这里我们采用对链整体打标记,在找叶子的过程中处理标记。

注意翻转左儿子列表的操作会较大影响树的形态,但是 LCT 的 access 次数的分析并不会失效(每次操作只会影响 O(\log n) 条轻边)。splay 的复杂度不再能沿用 LCT 的证明,但至少有上界 O(\log n),总复杂度不超过 O((n+q)\log ^2n),并且实际表现其实比较快。

F. Triangle

设三个串中字典序最大的为 x,其余两个为 y,z,则显然有 xy>zxz>y,因此只需要满足 yz>xzy>x。我们可以假设 yz\ge zy,这等价于 y^\infty\ge z^\infty,因此只是添加了一维偏序的限制。

现在要求 yz>x,而我们限制了 y\le x,因此 y 一定是 x 的一个前缀。我们可以枚举 x,y,总的枚举次数不会超过总串长。记 x 去掉前缀 y 后的串为 y^{-1}x,则 z 只需要满足以下两个条件:

  • z^\infty\le y^\infty
  • x\ge z>y^{-1}x

对于后者,可以直接对所有串后缀排序。

对于前者我们需要将所有串按照这个规则排序。注意这里直接比较 yzzy 的大小来排序,总的复杂度可以达到 \Omega(n^2)。一个复杂度正确的方法是,先判断两个串是否互为前缀,如果不是则可以直接比较,否则通过预处理的 z-函数/后缀数组,可以 O(1) 求出 LCP 然后比较。这样单次比较复杂度是 O(\min\{|y|,|z|\}) 而不是 O(|y|+|z|),总复杂度就是正确的 O(\sum|S_i|\log n)

处理完这两个限制之后,就变成了二维偏序,可以在 O(n\log n) 时间内解决。

需要注意的是,输入中会出现相同的串,所以我们需要记录每个串的出现次数,并且处理好三个串有相同的情况。

总时间复杂度 O(\sum |S_i|\log n)

G. Stop the Castle 2

将问题转化为放 m-k 个障碍,隔开尽可能多可以互相攻击的车。

只有在一行或者一列相邻的车才能互相攻击,这样的车只有 O(n) 对。在它们之间的任意位置摆放障碍就能防止它们互相攻击。设有 c 对能互相攻击的车之间能摆放障碍。

有的障碍可以阻挡两对车互相攻击(行列各一对),显然我们需要让这样的障碍尽可能多。假设我们能摆放 x 个障碍,每个障碍都能阻挡互不相同的两对车,那么放 m-k 个障碍就能阻挡 \min\{c,m-k+\min\{m-k,x\}\} 对互相攻击的车。

把互相攻击的车看成点,如果一个障碍能阻挡两对车,就在对应的两个点之间连边,会形成一个二分图。x 就是这张图的最大匹配。可以用 Dinic 算法或 Hopcroft-Karp 算法在 O(m\sqrt n) 的时间中求解。

H. Intersection of Paths

如果 k=1,则所求的就是树的直径。当 k 任意时,要求的其实就是只考虑两侧点数都不少于 k 的边时树的直径。

注意所有询问互不相关,因此我们可以将询问按照 k 从大到小的顺序重新排列。当 k 减小时,会陆续加入边,这些边形成一个连通块,如果询问没有修改时,可以直接维护这个连通块的直径。当询问有修改

时有不同的做法,这里介绍其中的两个:

  • 由于树的边权几乎不变,我们将询问中修改的边删除,分成两个连通块,分别求出两个连通块的直径,然后合并即可(整棵树的直径端点一定在这两条直径的端点中)。需要支持加点和求子树的直径,在按 DFS 序建立的线段树上合并直径即可。需要 O(1) LCA。
  • 直接使用修改边权的动态直径做法。直径等于在欧拉序上依次选 3 个点(可以相同)u,v,w\mathrm{dep}_u-2\mathrm{dep}_v+\mathrm{dep}_w 的最大值。修改边权对欧拉序上深度的影响就是区间加。用线段树维护这个式子每一段的最大值即可。

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

I. Find Yourself

首先注意到,任意的树都是能够确定的:

  • 因为树是二分图,所以我们可以黑白染色,先确定怪物所在点的颜色,不妨设和根相同(否则走一步)。
  • 假设怪物目前在 x 的子树中且与 x 颜色相同的一个结点(初始 x 为根)。如果 x 是叶子则游戏结束。否则,重复以下过程,直到 x 只剩下一棵子树:
    • 询问 x,如果怪物在 x,那么游戏结束。否则,怪物只能走到 x 的子树中,与 x 颜色不同的结点。此时询问 x 的一棵子树,如果怪物不在子树中,就可以删除这棵子树,否则可以删除所有其他子树。此时怪物又可能位于 x 的子树中,未被删除的,和 x 颜色相同的任意结点。
  • 当只剩下一棵子树 y 时,询问 x,如果怪物在 x,那么游戏结束。否则令 x\gets y,重复以上过程。

接下来考虑有环的情况。首先要注意到,如果图 H 是不能确定的,则任意包含子图 H 的图都是不能确定的。结合样例和打表观察,可以发现,以下的图都是不能确定的:

  • 大小不为 4 的环。
  • 四元环,每个点都都和其他点有边。
  • 四元环,相邻两个点分别连有长度为 2 的链。
  • 四元环,相邻三个点依次连有长度为 2,1,2 的链。

此时可以看出,能确定的图的每一个点双都应该是四元环,或是多条长度为 2、起点终点相同的路径并起来的“纺锤”图。为了进一步地简化图的结构,我们还可以观察到如下性质:

  • 如果存在两个二度点 a,b,它们的邻居相同,则可以删除其中的一个和其邻边,而不改变答案
    • 证明:设原图为 Ga,b 的邻居都是 c,d,删掉 b 和其邻边之后的图为 G'。显然如果 G 可以确定,则 G' 可以确定。反过来,如果 G' 可以确定,则使用相同的策略,可以在某一次询问后,确定怪物在 a,b 其中的一个,然后怪物走一步之后只可能在 c,d,因此再询问一下 c 即可确定怪物的位置。

经过上述变换之后,可以发现,能确定的图的每个点双都只能是四元环,且四元环不能有两个点都连有长度为 2 的链,也不能四个点都和其他点有边。

事实上,上述必要条件也是充分的。

  • 证明:满足上述条件的图,一定存在一个点,将这个点作为根时,每个四元环除了根以外的三个点中,至多有两个点连接了一个或多个叶子,另一个点没有和环外的点连边。设环上的点按顺序为 a,b,c,d,其中 a 是根。我们可以先利用树的做法,将问题缩小到在 a 的这个子树内确定怪物的位置。讨论两种情况:

    • b,d 分别连有叶子 b',d'(可能多于一个)。先询问 a,如果不在 a,则下一步只可能在 b,d,再询问 b 即可确定。
    • b,c 分别连有叶子 b',c'(可能多于一个)。先询问 a,如果不在 a,则下一步只可能在 b,d,c'。再询问 b,如果不在 b,则下一步只可能在 a,c,再询问 a 即可确定。

      因此满足上述条件的图都能够确定。

图的变换和判断上述条件都可以在 O(n+m) 时间内完成,因此整个题可以在 O(n+m) 时间内解决。

J. Sheriruth

如果一个点有两条出边 u,v,则 u,v 会互相连边。如果 uv 还有出边,会和 u,v 整个连成一个团。以此类推,u,v 可以到达的点都会形成一个团。不断合并这些团,最后整张图的每个连通块只有以下几种可能:

  • 内向树。
  • 内向基环树。
  • 一个团,还有若干内向树,每棵树的根连向了团中的若干个点。

内向树的情况只需要判断祖先后代关系。内向基环树的情况还需要判断点在环上。

大小为 s 的团的方案数就是 \sum_{i=0}^{s-2}(s-2)^{\underline i}。如果是从树根走到团上,要讨论走上来的点是否直接是 v,如果是则只有 1 种方案。这个式子只需要对每个团单独计算,大小总和不超过 n

总时间复杂度 O((n+m+q)\log n)\log n 在于排序和二分判断是否有某一条边,也可以做到线性。

K. Palindromic Polygon

首先将点复制一遍,变成 2n 个点的序列。相当于可以选一个子序列 i_1< i_2< \cdots< i_k,要求 i_k-i_1< n,且 f_{i_1},f_{i_2},\ldots,f_{i_k} 是回文序列,最大化凸包的面积。

考虑从两侧向中间 DP,设 f(l,r) 是当前回文序列中对应位置是 l,r 的最大面积。转移需要枚举 i,j,满足 l< i\le j< r,f_i=f_j,然后转移到 f(i,j)。这样做时间复杂度是 O(n^4)

注意到如果 (l,i)(j,r) 之间都有等于 f_i 的点,那么把这两个点选上,面积一定不会变小(相当于凸包上多了两个三角形),因此有用的转移都满足 i 是区间中第一个等于 f_i 的点或 j 是区间中最后一个等于 f_i 的点。这样对于每个区间有用的转移减少到了 O(r-l) 个,时间复杂度 O(n^3)

L. Cosmic Travel

考虑查 l=r 时如何查询。对所有 a_i 建立 Trie,然后从根开始,如果 l 的对应位为 1 则交换了两棵子树,然后如果 k\le (左子树大小),递归左子树,否则递归右子树。

查询一个区间 [l,r] 时,类似线段树的方式,按对应位分成两个区间,分别递归。我们只需要在 [l,r] 恰好是一个完整的区间时快速回答。即对于每棵子树,对每个 1\le k\le (子树大小),预处理对 j\in [0,2^d)a_i\oplus j 的第 k 小的和,其中 d 是子树的位数。需要预处理的值,每个深度是 O(n) 个,因此总共只有 O(n\log C) 个。每个需要预处理的值都可以通过其孩子的值在 O(1) 时间内得到。

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

M. The Quest for El Dorado

考虑 Dijkstra,将每个点的距离定义为 (i,x),即最早在第 i 轮才能到达,并且第 i 轮至少走了 x 的距离。显然我们希望 i 尽可能小,并且 i 相同的情况下 x 尽可能小。

对于每条边 (v,c,l),如果 a_i=cx+l\le b_i,那么新的距离是 (i,x+l)

否则,我们需要找到最小的 j>i,满足 a_j=cb_j\ge l,新的距离就是 (j,l)。找这个 j 可以用线段树或者二分 RMQ。

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

The 3rd Universal Cup. Stage 9: Xi'an 题解

2024-09-10 21:31:13 By jiangly

A. An Easy Geometry Problem

A_i'=A_i-i\cdot \frac{k}{2},则对于 ir 是好的半径当且仅当 A'_{i+r}-A'_{i-r}=b

用线段树或树状数组维护正反两个方向的哈希值,询问时二分长度然后比较哈希值即可。

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

B. Counting Multisets

考虑 p(S) 是奇数的条件,设 \mathrm{cnt}(x)xS 中的出现次数,则 p(S)=\frac{n!}{\prod_x \mathrm{cnt}(x)!}。根据 Lucas 定理,p(S) 是奇数当且仅当所有 \mathrm{cnt}(x) 在二进制下相加没有进位。因此,合法的可重集就是对于 n 的二进制中每个 2^i,任意选择一个 x 重复 2^i 次。

现在还要解决 \mathrm{OR}_{x\in S}x=y 的条件。可以通过容斥将条件改写为 \forall x\in S,\mathrm{bin}(x)\subset \mathrm{bin}(y)x 的二进制中的 1y 的子集)。

因此,对于固定的 y,只需要计算对于每个 2^i\in \mathrm{bin}(n),2^j\in \mathrm{bin}(y),可以选或不选 2^{i+j},总和等于 x 的方案数。这可以通过数位 DP 解决,即 f(i,j) 表示确定最低 i 位,目前进位为 j 的方案数,时间复杂度 O(\log x\log n\cdot \mathrm{pcnt}(y))

总时间复杂度 O(2^{\mathrm{pcnt}(y)}\mathrm{pcnt}(y)\log x\log n)

C. Counting Strings

(复读官方题解)

首先把条件改写成 \gcd(r,r-l)=1。建出 SAM,对于每个 r-l,假设保留所有 \gcd(r,r-l)=1r 对应的结点,这样的串的个数就是这些结点到根的路径的并中深度为 r-l 的点数。如果我们把这些结点按 DFS 序排序,则容易维护这些路径的并。

考虑通过搜索枚举 r-l 包含质因子的集合来优化这个算法。在加入一个素数 p 时,要删除所有 p\mid rr 对应的结点,这样的删除对路径并的变化是删除一条链,可以用链表维护前驱后继,求两次 LCA 就能找到这条路径。回溯时撤销修改即可。为了统计答案,我们维护每个深度的点数,修改的影响是区间加,查询是单点求值,可以用 O(1) 修改 O(\sqrt n) 查询的分块维护。

接下来只需要分析这样搜索时需要修改的次数 F(n)。实测在 n=10^5 时,修改的次数不超过 2\cdot 10^7。具体的分析是,修改次数等于 \sum_{x=1}^{n-1}[\mu(x)\ne 0]\frac{n}{\mathrm{maxp}(x)},其中 \mathrm{maxp}(x)x 的最大素因子。

时间复杂度 O(F(n)+n\sqrt n)

D. Bracket Sequence

考虑 DP 计算一个给定字符串 s 的方案数。f(i,j) 表示 S[0:i] 中等于 \mathbb{()}^\infty[0:j] 的子序列的方案数,则答案就是 f(|s|,2k)

K=\max \{k\}。对于第 1 类区间询问,我们可以把这个 DP 写成 v\cdot M_lM_{l+1}\cdots M_r,其中 M_is_i 的转移矩阵。由于矩阵的特殊性质,可以在 O(K^2) 的时间内计算一个矩阵乘上 M_i,因此只需要预处理 M_1M_2\cdots M_i(M_1M_2\cdots M_i)^{-1},就可以在 O(K) 时间内回答一个询问。

对于第 2 类区间询问,首先可以添加一个 DP 状态,表示还没有进入子串,同时预处理 M_1M_2\cdots M_i 的前缀和即可。

总时间复杂度 O(nK^2+qK)

E. Dominating Point

S(u)=\{v\mid (u,v)\in E\lor u=v\}。点 u 是支配点当且仅当不存在 v\ne u 满足 S(u)\subset S(v)

把所有点按度数从大到小排序,依次检查是否存在这样的 v。显然我们只需要检查已经确定是支配点的 v,而找到三个支配点后就可以直接返回,因此对于每个 u 只需检查 O(1) 个点,每次检查 O(n)

总时间复杂度 O(n^2)

F. An Easy Counting Problem

因为 p 是素数,由 Lucas 定理可知组合数是 p 进制下每一位组合数的乘积。0\le b\le a< p 的组合数分布可以 O(p^2) 暴力计算。

求出一位的组合数分布后,我们要计算其在 i,j\to i\cdot j\bmod p 卷积意义下的 k 次幂。通过找一个原根并将下标取离散对数的变换,我们可以将其转化为普通的循环卷积,可以用 FFT 优化。

时间复杂度 O(p^2+p\log p\log k)

G. An Easy Math Problem

我们加上 \gcd(p,q)=1 的限制,不同的 (p,q) 就对应了不同的 r。考虑计算这样的 (p,q) 的方案数。显然方案数是积性的,即每个素数独立,且 p^k 的方案数是 2k+1(1,1),(p^i,1),(1,p^i))。分解 n 之后直接计算即可。

可以预处理素数来加速分解,时间复杂度 O(\sqrt N+q\frac{\sqrt N}{\log N})

H. Elimination Series Once More

我们对每个 i,和每个 j=1,2,\ldots,n,来计算 i 能不能赢下第 j 轮,也就是能不能让 a_i 变成其所在的大小为 2^j 的子树的最大值。

只需要判断两个条件:

  • 所在子树中大于 a_i 的不超过 k 个。每次最多只能把一个换出去。
  • a_i\ge 2^j。这是为了保证有足够多小的数放进子树。

这个条件可以在归并排序的过程中快速判断,时间复杂度 O(n2^n)

I. Max GCD

我们枚举 \gcd=d,看是否能用 d 的倍数满足条件。显然对于固定的 ji 应该越大越好,k 在满足 k-j\ge j-i 的前提下越小越好。

考虑从大到小枚举 j,找到对应的 iki 可以直接找到,但 k 并不单调。然而如果 i 更小的时候 k 更大,这样的三元组一定是不优的,因此仍然是只需要让 k 单调下降。令 A=\max\{a_i\}d(A)1A 中约数个数的最大值,则可以在 O(nd(A)) 的时间中找到所有的三元组。

询问就是简单的二维偏序,为了平衡复杂度,可以使用 O(1) 修改、O(\sqrt n) 查询的分块,总时间复杂度 O(nd(A)+q\sqrt n)

J. Graph Changing

考虑在 G_1 中,两点有边当且仅当 |u,v|\ge k,如果 u,v 可达,则最短路径长度一定不超过 3u\to 1\to n\to v)。因此如果 k>3G_2 开始就是空图。

k=3 时,显然当 n 足够大时 G_2 开始也是空图。

k=2 时,显然当 n 足够大时 G_{i+1}G_i 的反图。

k=1 时,显然 G_1 开始就是完全图。

因此只需要预处理 n 小的情况(例如 n< 10),特判 k=1,2,3,剩余的情况分类讨论答案是 1,2,3 即可。

K. Penguins in Refrigerator

先求方案数,考虑从大到小插入数。首先大于 M/2 的数相对顺序不改变,对于不超过 M/2 的每个数 a_i,找到左右第一个大于 M-a_i 的数,则 a_i 只能插入到这个区间中。注意到这些区间形成一棵树形结构,因此方案数就是每个数插入的方案数相乘。

再求字典序最小的方案数。大于 M/2 的数相对顺序不改变,可以连一条链。对于不超过,对于不超过 M/2 的每个数 a_i,找到左右第一个大于 M-a_i 的数,只需要它们之间的相对顺序不改变即可(因为其他的顺序关系都通过链确定了)。之后用堆维护,求字典序最小的拓扑排序即可。

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

L. Prism Palace

所求的就是随机旋转一个角度,有一条边在 y 轴上的投影是整个凸包的概率。对于相邻的两个内角 a,b,这条边满足条件的角度范围是 \max\{0,\pi-a-b\}。对这些角度求和然后除以 2\pi 即可。时间复杂度 O(n)

M. Random Variables

考虑对每个 k 计算每种数出现次数不超过 k 的方案数。其等于 n![x^n]\left(\sum_{i=0}^k\frac{x^i}{i!}\right)^m 注意由于模数不一定是素数,所以不一定有阶乘逆元,但 EGF 的卷积只需要乘上组合数。

考虑容斥,即把 \sum_{i=0}^k\frac{x^i}{i!} 写成 e^x-\sum_{i=k+1}^\infty \frac{x^i}{i!}。如果能够预处理所有 \left(\sum_{i=k}^\infty \frac{x^i}{i!}\right)^m,就能够在 O(n^2\log n) 时间内计算答案(因为 mk\le n)。

这里 m 的范围是 \frac{n}{k},按照 k 从大到小预处理,每次只需给内部的式子加上一项,展开后是 O(m) 项已知的式子求和。因此可以在 O\left(\sum_{k=1}^n \frac{n^3}{k^2}\right)=O(n^3) 时间内预处理所有的值。对于每组数据,还要对 0\le i\le n 计算 m\choose i,可以通过快速幂计算 (1+x)^m\bmod x^{n+1}O(n^2\log m) 的时间内计算。因此总复杂度是 O(N^3+\sum n^2(\log n+\log m))

对于整数 B,我们只预处理 k\ge B 的值,复杂度是 O\left(\frac{n^3}{B}\right)。对于 k< B,我们要计算的是一个短多项式的幂,可以通过 ODE(f'g=mg'f)来计算,注意 EGF 的求导就是移位,所以不需要除法,复杂度是 O(nk)。总时间复杂度 O\left(\frac{N^3}{B}+\sum n B^2+\sum n^2(\log n+\log m)\right)

官方题解里有 O(\sum n^2\log n) 的做法。

N. Python Program

外层循环直接模拟,内层循环用等差数列求和。

时间复杂度 O(|a-b|)

The 3rd Universal Cup. Stage 7: Warsaw 题解

2024-08-25 21:10:44 By jiangly

A. Bus Analysis

不妨将价格除以 2,变为 13,最后将答案乘 2 即可。

先考虑对于给定的 t_1,t_2,\ldots,t_n,如何计算最小代价。

\mathrm{dp}(i,j) 表示用 j 的代价覆盖了前 i 个点,最多还能覆盖多长的距离。设覆盖前 i 个点的最小代价为 x,则只有 f(i,x),f(i,x+1),f(i,x+2) 的值有用。这是因为在如果前 i 个点花费了至少 x+3 的代价,一定不比“花费 x 的代价覆盖前 i 个点,然后再买一张 3 元的票”优。

于是,在 DP 的过程中我们只需要记录 x,f(i,x),f(i,x+1),f(i,x+2) 这些值。现在变为计数问题,只需要将这些值记在状态里面。并且注意到,我们只需要求代价的和,所以不需要将 x 计入状态,只需在代价变大时统计进答案。

时间复杂度 O(n\cdot 75^3)。实际上,状态数的常数非常小,有用的三元组 (a,b,c) 都满足 0\le a\le a+20\le b\le b+20\le c\le 75

B. Missing Boundaries

首先,对于已经确定两个端点的区间,它们一定不能相交。

对于已经确定一个端点的区间,确定的端点一定不能包含在已经确定的区间里面,且互不相同。

剩下的区间可以任意填,我们可以计算出最小和最大的可能区间数量,判断输入的区间数量是否在范围内即可。

最大的区间数量就是(L- 两端点确定的区间的长度和 - 一个端点确定的区间个数)。

最小的区间数量就是相邻且差大于 1 的右端点和左端点的对数(包括开头和结尾)。

时间复杂度 O(N\log N)

C. Price Combo

考虑最终方案中每个物品是在商店 A 购买还是商店 B 购买。注意到如果 a_i>a_jb_i< b_j,那么在商店 A 购买物品 i 、商店 B 购买物品 j 一定是不优的(交换之后一定不劣)。因此,假设我们把一个物品看做点 (a_i,b_i),那么一定存在一条右上到左下的折线,折线上以及左上方的物品在商店 A 购买,折线右下方的物品在商店 B 购买。我们对这条折线进行 DP。

不妨设 a_i,b_i 互不相同。我们考虑从右上到左下确定折线,当折线向左的时候,加入折线上方的 a_i 产生的贡献;折线向下的时候,加入折线右方的 b_i 产生的贡献。注意因为是买一送一,因此只有第 1,3,5,\ldots 个会产生贡献。

显然我们只需要将 (a_i,b_i) 作为折线的关键点。为了方便起见,我们可以加入 (+\infty,+\infty),(-\infty,-\infty)

\mathrm{dp}(i,p,q) 是折线走到了 (a_i,b_i),选择的 a 个数奇偶性是 pb 个数奇偶性是 q 的最小代价。那么假设 (a_i,b_i)(a_j,b_j) 转移来(a_i< a_j,b_i< b_j),则需要加上的贡献是 a_i< a_k< a_jb_k>b_j)和 b_i< b_k< b_ja_k>a_i),以及 a_i 的贡献。

考虑按照 a_i 从大到小扫描线,用线段树维护转移。线段树以 b 作为下标,维护 DP 值加上 a_k 的贡献的最小值。对于 a_k 的贡献,只需在扫描线时在线段树上做前缀加(b_j< b_k)。注意这里的加法标记实际上是(0 位置加上的值,1 位置加上的值,加的数的个数)三元组。对于 b_k 的贡献,考虑直接在线段树上维护,即每个结点维护 \mathrm{dp}(j) 加上小于 b_jb 的贡献后的最小值,以及 b 的贡献。这里 b 的贡献本质上和 a_k 的加法标记一样。合并时,DP 值应当是左区间的 DP 值以及(右区间的 DP 值加上左区间 b 的贡献)的较小值。这样,要求 \mathrm{dp}(i),只需要在线段树上查询后缀 (b_i,+\infty)

时间复杂度 O(N\log N)

D. Data Determination

不妨设 a_1\le a_2\le \cdots\le a_n

k 是奇数时,需要存在 i,满足 a_i=m,i-1\ge\frac{k-1}{2},n-i\ge\frac{k-1}{2}

k 是偶数时,需要存在 i< j,满足 a_i+a_j=2m,i-1\ge \frac{k}{2} -1,n-j\ge\frac{k}{2}-1。注意对于相同的 (a_i,a_j)ij 离得越近越好,这样的 (i,j) 只有 O(n) 对。

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

E. Express Eviction

解法 1

最小割。注意到存在路径当且仅当不存在左下区域到右上区域、每个格子都有居民、且相邻格子行列差都不超过 2 的路径。我们认为左下边界和左下区域是相邻的,右上边界和右上区域是相邻的。

因此我们可以对每个有居民的格子建两个点 (a_u,b_u),如果它是左下边界则连边 (S,a_u,+\infty),右上边界则连边 (b_u,T,+\infty),同时连边 (a_u,b_u,1) 代表可以花费 1 的代价删除这个格子。对于行列差都不超过 2 的每对格子 u,v,连边 (b_u,a_v,+\infty)。这个图的最小割即为答案。

时间复杂度 O(\mathrm{Maxflow}(HW,HW))

解法 2

最短路。考虑普通的最短路在什么时候会得不到最优解。

.#....
....#.
...#..
###...
###..#
###...

如这个例子,只需删除第三行的第四个格子。我们注意到这样的路径实际上是经过了一个格子相对的两个角,但我们的状态中并没有记录经过的格子,所以导致重复计算代价。

考虑所有经过两次的格子,如果一个有居民的格子 u 的两次经过在另一个格子 v 的两次经过之间,我们不如额外花费 1 的代价直接穿过格子 v。因此可以假设没有这样的两个格子 (u,v)。在这个前提下,我们可以发现路径上的每一个点至多在两个格子的两次经过之间(路径的两侧各一个),通过在状态中记录这两个格子,我们可以做到 O(H^3W^3) 的时间复杂度。

进一步地,假设我们依次经过了格子 u,v,那么下一步一定是从 v 走到格子 u 的对角。并且如果在下一次经过 u 之前我们花费了额外的代价,也是不如直接穿过 u 的。因此我们只需要记录一个之前经过的格子,并加一种额外的转移,即当前位置是 x,经过了 v,对于 v 的每个对角相邻的点 w,如果 x 可以不花费额外代价到达 w,则可以直接转移到位置 w,经过了 x。转移可以通过从每个点 BFS 预处理。

时间复杂度 O(H^2W^2)

F. Fibonacci Fusion

不妨设 a_1\le a_2\le \cdots\le a_n

枚举 j,则 a_j< a_i+a_j\le 2a_j,满足这样条件的斐波那契数只有至多两个,假设我们能求出这两个斐波那契数,就只需要求某个数的出现次数。

由于 a_i 非常大,对应的斐波那契数也非常大,所以我们计算斐波那契数对大素数取模的值(避免碰撞),同时需要估算对应的数的下标。

因为 F_n=\frac{1}{\sqrt5}\left(\left(\frac{1+\sqrt5}{2}\right)^n-\left(\frac{1-\sqrt5}{2}\right)^n\right)\approx \frac{1}{\sqrt 5}\left(\frac{1+\sqrt5}{2}\right)^n ,所以可以用 n\approx \log_{\frac{1+\sqrt 5}{2}}{\sqrt 5a_i} 来估算。

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

G. Game of Geniuses

答案等于 \max_i\min_j a_{ij}

设答案为 x,答案大于等于 x 是平凡的,先手可以删除除最小值等于 x 的行以外的其余行。

要证明答案小于等于 x,我们只需要证明每轮后,后手都能保证每行都有小于等于 x 的数。不妨设先手删除了第一行,则后手找到剩余 n-1 行中各一个小于等于 x 的数,标记其所在列,然后删除未被标记的列即可。

时间复杂度 O(n^2)

H. Henry the Plumber

因为每个水管都必须立即转弯,所以答案至少是 2

而答案不超过 4,因为可以分别连平行于 z 轴的水管,到同一个 z 之后垂直于 z 轴连接起来(如果两点连线平行于 z 轴则直接连)。

分类讨论:

  • 如果 (x_1,y_1,z_1)-(x_2,y_2,z_2) 垂直于 (p_1,q_1,0)(p_2,q_2,0),则答案为 2
  • 否则答案至少为 3。答案为 3 当且仅当存在一个中间点 P,和 (x_i,y_i,z_i) 的连线垂直于 (p_i,q_i,0)。即 P 在经过 (x_i,y_i,z_i) 且垂直于 (p_i,q_i,0) 的平面上。
  • 如果这两个平面平行,则答案为 4
  • 否则找到这两个平面的交,设为 (x_0,y_0,z)(一条平行于 z 轴的直线)。现在要确定 z 的值,使得 P 的夹角为直角,即 (x_0-x_1,y_0-y_1,z-z_1)(x_0-x_2,y_0-y_2,z-z_2) 的点积为 0
  • 如果 (x_0,y_0) 和某个 (x_i,y_i) 重合,则满足条件的 P 就是 (x_i,y_i,z_{j}),如果 z_1\ne z_2 则答案为 3,否则答案为 4(因为水管长度不能为 0)。
  • 否则,条件是一个关于 z 的二次方程,只需判断判别式是否大于等于 0。大于等于 0 则答案为 3,否则答案为 4

时间复杂度 O(1)

I. ICPC Inference

枚举获得金银铜牌的队伍。铜牌一定是通过了一个题目,且罚时尽量大。金牌一定是通过了尽量多的题目,且罚时尽可能小。

我们可以将分数设为 M\cdot \mathrm{num}-\mathrm{penalty},其中 M 是一个非常大的数。则分数越大的人排名越高。

考虑银牌可能的分数,因为铜牌只通过一个题,银牌分数应当在不小于铜牌的前提下尽可能小,因此有用的分数只有通过一个题的情况以及通过两个题且罚时最大。设这些可能的分数是 s_1< s_2< \ldots< s_k,则满足 s_i<\mathrm{bronze}\le\mathrm{gold}< s_{i+1} 的金铜牌是不合法的(当然还有小于 s_1 和大于 s_k 的情况)。

我们可以在 O(\log N) 的时间里面对每一个区间计算答案,但是区间的数量可以是 O(N^2) 的。注意到罚时 K=20 比较小,而可能的罚时都形如 t_i+K\cdot c0\le c< i),因此可能的罚时可以写成 O(N) 个段,每个段以 K 为周期。对于跨段的区间我们可以 O(\log N) 计算。而对于段内我们可以抽象成 O(K) 个以下询问:

  • 有多少对 (\mathrm{bronze},\mathrm{gold}) 满足 \mathrm{bronze}\bmod K=il\le \mathrm{bronze}\le r\mathrm{gold}-\mathrm{bronze}\le j

这样的 (\mathrm{bronze},\mathrm{gold}) 也只有 O(NK) 对,预处理之后可以 O(\log N) 回答询问。

注意金银铜牌必须互不相同,因此需要做一些容斥。

时间复杂度 O(NK\log N)

J. Juliet Unifies Ones

数据范围很小,所以做法很多。

一个线性的做法是分成三段,分别是 0,1,0,设 \mathrm{dp}(i,j) 表示考虑 i 个字符,目前在第 j 段,至少要删几个字符。

K. Routing K-Codes

如果 K(b)=\left\lfloor\frac{K(a)}{2}\right\rfloor 则我们将边定向为 a\to b。因为所有 K(x) 互不相同,因此每个点的出度都不超过 1,入度不超过 2,且图中不存在环,因此只可能是内向二叉树。因此如果 m\ne n-1 则无解。

假设确定了根,则根的值为 01(度数小于 2 则为 0,等于 2 则为 1),深度不超过 3231,每个孩子的值是 2K(x)2K(x)+1。最小的代价和可以通过 DP 求出。使用换根 DP 即可求出每个点作为根的答案。

时间复杂度 O(n+m)

L. Random Numbers

注意到长度为 k 的区间的和的期望是 k\cdot \frac{n+1}{2},因此当 k 距离 \frac{n}{2} 较近时才有较大的概率存在合法区间。当 k 较小的时候,因为总的组合数量不多,因此也有一定的概率存在合法区间。

因此只需设置常数 B,枚举所有长度在 [1,B]\left[\frac{n}{2}-B,\frac{n}{2}+B\right] 中的区间检查即可。

时间复杂度 O(nB)。例如 B500 可以通过此题。

M. Mathematics Championships

答案等于前 2^i0\le i\le k)大数和的最大值。排序后即可计算。

时间复杂度 O(n2^n)

jiangly Avatar