A. Box is Pull
如果同行或同列,则答案为两点之间的曼哈顿距离。
否则,先拉到同行,然后花两步换方向,再拉到同列,这样答案就是两点之间的曼哈顿距离再加二。
B. Belted Rooms
别问,问就是直接跑强连通分量(SCC)。如果一个SCC只有一个点,那么这个点不符合条件,否则这个SCC里所有点都符合条件。
C. ABBB
- 遍历字符串
- 如果当前字符无法和栈顶相消,就把当前元素入栈
- 否则就把栈顶取出来和当前元素相消。
D. Bouncing Boomerangs
- 从右到左遍历列
- 分别用3个数组记录访问过且值为(x)且尚未被使用的元素的位置
- 如果当前元素为2,那么只需要找到后面的一个尚未用过的值为1的元素与之匹配,这两个元素同行。如果找不到,就说明无解。
- 如果当前元素为3,那么只需要找到后面的任何一个尚未使用过的元素与之匹配,当前元素要比匹配元素高(行号小),且需要再匹配元素对应列同以高度的位置加点。如果找不到,就说明无解。然后,因为上一个操作只能用1来匹配,所以在这个操作中优先使用2或者3。
现在列与列的匹配关系已经确定了,现在就要确定每个元素的高度了。
首先,从左到右逐渐降低高度会是比较好的做法,因为左边的值为3的元素会要求比与之匹配的元素跟高。
记初始高度(行号)(r = 1)
- 从左到右遍历列,记列号为(c)
- 如果当前元素为0或当前列已被访问过,则不做处理
- 如果当前元素为1,则加一个点((r, c)), (r = r + 1)
- 如果当前元素为2,则加一个点((r, c))。然后找到与之匹配的列(c^prime),再加一个点((c^prime, r)), (r = r + 1)。
- 如果当前元素为3,则加一个点((r,c))。然后找到与之匹配的列(c^prime),加一个点((c^prime))。然后(r = r + 1),再加一个点加一个点((c^prime, r))。由于与之匹配的列的值可能为2或者3,所以这里会形成一条匹配链,以此处理匹配链上的列。
然后因为这样处理,每一列都至多让行号加一,所以最后(r le n)。
由此,这样构造可以满足题目给的所有条件。
E. Carrots for Rabbits
首先观察得到:对于长度为(x)的萝卜,将其分成(t)份,最优的做法就是将尽可能均分,即分成多个(lfloor frac{x}{t} floor)和(lfloor frac{x}{t} floor + 1), 可以(O(1))计算出结果,记结果为(cut(x, t))。且(cut(x, t) ge cut(x, t + 1)),因为最差也就是先将其分成(t)份,然后再找一份继续砍成两半。
现在有(k - n)可用次数,将一根萝卜分成(t)份会消耗(t)可用次数。
计算出一次可用次数都不用的答案。
假设对长度为(x)的萝卜已经使用了(t)次次数,那么在这个萝卜上多使用一次次数,对答案的贡献就是(cut(x, t) - cut(x, t + 1))。
然后依次使用每一个可用次数,每次贪心地使用,即每次对多用一个可用次数能使答案下降最多的萝卜使用。
用一个优先队列维护,复杂度为(O(klog n))。
F. Fruit Sequences
观察1:固定(r),(f(l,r))随着(l)的增加是非升的。
观察2:如果(s_r = 0),那么(f(l,r) = f(l, r - 1))。
观察3:如果(s_{r} = 1),那么(f(l,r))就是在(f(l, r - 1))的基础上,对某个后缀区间加1。
观察4:记(sum_r = sum_{i = 1}^{r} f(l, r)),(r^prime)为满足(s_{r - 1} = 0)且(r)到(r^prime)之间全为1的最大的(r^prime),那么从(r)到(r^prime)这段区间对答案地贡献为(sum_{k = 1}^{r^prime -r + 1} sum_{r + k - 1}),且(sum_{r + k} = sum_{r + k - 1} + r - L_k),在这之后(L_k = r + k)。
观察5:如果(s_r = 0), (sum_r = sum_{r - 1})。
这样,从左至右,如果(s_i)为0就根据观察5计算当前位置对答案的贡献,否则就扫描出连续的全1字段根据观察4计算该段对答案的贡献并更新(L_x)。