唉,状态太差了,被打爆了。
A. Safety First
很棒的根号分治 DP,应该意识到的。
考虑一种 DP,设计 $f(i,j)$ 表示当前有 $i$ 个,总高度为 $j$,当前长度为 $k$,枚举前一个长度 $l$。状态转移方程为:
用前缀和优化即可做到 $\mathcal O(nm^2)$。但我们更好的实现方法是直接每次先从大到小枚举是否加入长度为 $l$ 的梯子,这样的话状态就只有 $\mathcal O(nm)$ (但是时间复杂度并没有什么区别)。
想到就没希望了,毕竟状态数就是 $\mathcal O(nm^2)$ 的了。$\sum a_i =k$ 一定的题目,给人一种相当熟悉的预感:显然,产生贡献的大于 $\sqrt m$ 的段数小于 $\sqrt{m}$ 个。但是我们发现单纯沿用上面的 DP 没法很好地利用这一点,因为我们没有记录当前是否对总长度产生贡献。
对于这种类型我们容易想到了另外一种 DP,设计 $f(i,j,k)$ 表示考虑当前有 $i$ 个,能够产生贡献的有 $j$ 个,当前总高度为 $k$,考虑两种转移:1. 新加一个;2. 把前面的全部 +1。
仔细观察两种算法的利弊,我们考虑把二者结合起来。对于前 $\ge\sqrt {m}$ 段,我们使用算法二,每次都加入长度 $\sqrt{m}$ 的产生贡献的段(而非 $1$),时间复杂度为 $\mathcal O(nm\sqrt{m})$;对于剩下的$\le \sqrt{m}$ 段,我们使用算法一,所以时间复杂度也为 $\mathcal O(nm\sqrt{m})$。
Code
1 |
|
B. Magical Palette
神秘智慧构造,被打爆了。需要一点思考。
I. Growing Tree
其实也并没有很难。
显然对于越浅的边,限制越小。我们于是尝试从深到浅进行考虑。容易发现,只要我们对一条边进行处理,那么这条边下面的子树看可以和其他部分不存在相同(因为可以加上一个任意的数),相当于去掉该边,得到两个互不相同的两部分。
对于节点 $x$,若它的两棵子树之间存在相同的(考虑子树内部相同的已经被处理掉了),那么我们需要决定更改两条边中的哪一条。这个不好考虑,于是直接尝试爆搜,分别搜更改两条边的情况。因为最多操作 $n$ 次,故状态数为 $\mathcal O(2^n)$,而每次采用归并的方式合并子树并找相同的,这一部分每一次总的复杂度为 $\mathcal O(n2^n)$,所以最终复杂度为 $\mathcal O(n4^n)$。
Code
1 |
|
D. Dot Product Game
容易转化为逆序对相关的问题,不说了。
E. Light Up the Grid
小水题,但是犯唐看错题了。
考虑按照什么样的顺序操作这 $m$ 个矩阵,但注意到 $m\le 16$(因为一共只有 $16$ 种矩阵状态),我们是可以直接状压 DP 的。不过我们需要提前预处理可能的操作的花费,在最短路上跑就行了。然后状压 $16$ 种状态已经达成了哪些,DP 预处理出,时间复杂度为 $\mathcal O(m^22^m)$。最后直接输出答案即可。
Code
1 |
|
G. Guess the Polygon
噢谢,还是很简单的交互。
设 $f(x)$ 为横坐标为 $x$ 对应的长度,相当与询问 $(x,f(x))$,求出 $\int f(x)$。容易发现 $f(x)$ 是一个线性并且按照每个顶点横坐标分段的函数。
容易发现,如果顶点横坐标 $x$ 互不相同,那么 $f(x)$ 显然是连续的; 否则 $f(x)$ 就可能存在断点。于是我们分两种情况讨论:
- 横坐标 $x$ 互不相同,因为 $f(x)$ 为连续的 $x-1$ 段函数,所以直接询问 $n-2$ 个断点即可。
- 存在横坐标 $x$ 相同,那么 $f(x)$ 最多有 $x-2$ 段,所以直接询问 $n-2$ 段的中点即可。
时间复杂度瓶颈为排序的 $\mathcal O(n\log n)$。
但需要注意的是对于分数的处理。注意到交互器返回的分数可能很大。一个处理方式是:对其去模,并将除法转为逆元,我们选取大于 $2\times 10^6$ 的质数作为模数:因为注意到面积的二倍一定是整数,其余乘上的分母一定会消掉。另一种是直接使用了 long double,据说精度也是够用的。
Code
1 |
|
H. Guide Map
出的挺不错的一题。
考虑初始的两棵树为 $T_1,T_2$(设 $T_1$ 为根)。容易发现,在 dfs 树上横叉边是不允许存在的。容易想到将 $T_1,T_2$ 分别求出可以随便选的边,再乘起来即可得到答案。
对于有根的 $T_1$,我们直接用树状数组进行统计即可。注意还有考虑每个点加上 $T_2$ 作为子树的贡献,统计一下即可。
但是对于 $T_2$,我们对所有点作为根求一遍。考虑换根,我们在 $x$ 上记录其对父亲的贡献就行了。时间复杂度为 $\mathcal O(n\log n)$。
注意特判 $|T_2|=1$ 的情况。
Code
1 |
|
M. Obliviate, Then Reincarnate
尼玛这题这么简单,我赛时到底在干嘛???
考虑转化为图,对于每个 $x\pmod n$ 的类建一个点。对于搬迁指令 $(a,b)$ 建边 $(a\pmod n,(a+b)\pmod n,b)$。容易发现能够抵达无穷个的条件是能够走到一个环上。那么很容易想到用 Tarjan 求出强连通分量后缩点得到 DAG,在拓扑序上求出即可。但注意到 我们需要保证走一遍之后 $x$ 的值发生变化(也就是环上的权值和不为 $0$)。时间复杂度为 $\mathcal O(n+m+q)$。
Code
1 |
|