难度标签:,,。
首先考虑怎样的序列是合法的。第一步,删除的一定是 个 ,接下来一定是 个 ......
我们将序列长度逐渐变短的过程画在数轴上,那么应该是从 开始,发现有 个 ,然后向左走 步。接下来发现 上值为 ,再向左走 步。合法当且仅当这样能走到 。
如果存在 个 ,就从 向左覆盖长度为 的线段的话,合法就相当于 都被覆盖了。
考虑最少需要多少步,才能变得合法。注意到每移动一步,至多多覆盖一个位置,所以设 是未覆盖位置,则至少需要 步。同时容易构造 步的方案。于是只需要每次修改之后维护未覆盖的位置个数即可。
考虑两个积木什么时候可以拼在一起:
先不考虑第一个情况的话,相当于当我们遇到了一个右侧接地、长度为 的积木,则他要接一个左侧空白长度为 的积木。注意到我们总可以将一个积木抽象为 的形式,两个积木 能拼起来当且仅当 。
于是,对于每块积木,连边 。同时,有一些积木是可以作为最左侧的,一些积木是可以作为最右侧的。这相当于要求我们从一个“左侧点”走一条欧拉路径走到一个“右侧点”(左右侧点是不交的)。注意到欧拉回路是不可行的,因为左右侧点不交。
再考虑第一种情况,相当于就是将整张图拆成若干 “从一个‘左侧点’走一条欧拉路径走到一个‘右侧点’”。这个形式不是很好,考虑建立一个虚点,向所有作为起点的“左侧点”连边,所有作为终点的“右侧点”向虚点连边。这样,答案就是一个欧拉回路。
意思是说,只要我们能给一些“左侧点”添加入度,“右侧点”添加出度,构成一张有欧拉回路的图,那么就合法了。当然,对于每个连通块,都至少要有一个点能和虚点相连(否则就会出现不经过虚点的欧拉回路)。
考虑逐个确定每条路径。注意到我们只关注当前最右侧的路径。最朴素的做法是每次暴力枚举一条路径,判断是否可行,这是 的。
不过,我们可以逐步确定,如果我们把一条路径抽象成一个 串,那么一条路径 能接在一条路径 右侧,当且仅当 的每个前缀中 的个数都 的这个前缀中 的个数。
于是,我们可以一个一个确定下一步走哪里。设 表示目前在转移第 条路径,目前转移了前 步, 的前 位记录完成转移后的状态,后面的位记录前驱状态的这些位,目前与上条线段的距离是 ( 多 )的方案数。
复杂度是 ,无法通过。我们考虑吃掉 这一维。关注到我们的要求只是对于每个前缀, 都不小于前驱而已。假设我们在这一位放了一个 ,那么在接下来的一段时间内,我们可能都是“安全的”,意思是说,我们做的事情不过是将前驱状态的 进行一些提前,再在最后加一些 而已。
所以,每次如果决定在当前这一位放一个 的话,就直接将 之后的最近的 抓过来用(把 的位置设为 ),如果没有 了就加一个 。这样就只要 了,可以通过。
考察了一个较为重要的构造。
首先,考虑哈密顿环的情形。观察一条边的贡献,设这条边两侧的点个数的 是 ,则这条边的贡献至多为 ,即至多在这条边来回这么多次。
实际上,答案是可以顶到上界的。注意到对答案的贡献与两侧点数的 相关。我们知道这个值一定 ,从而考虑重心。拿重心为根之后,每个点朝向根的子树都是较大的。
假设现在只有一个重心,则每次我们希望一条路径都能跨越重心。这是可行的,因为若将每棵子树都染色,则每种颜色个数 ,一定可以围成一个环,使得相邻颜色不同。构造方式,可以拿出 ,将 为偶数的倒序,隔个插入奇数中,容易证明这样恰好每次会跨越根。
再考虑哈密顿链的情况。如果有两个重心,可以得知中间的边至多经过 次,所以减掉一次中间的边的权值就可以了(剩下的一定有构造方案)。
如果只有一个重心,那么我们可以选择一条与根相连的,权值最小的边,减去即可。
在鸽了不知道多久之后回来了
中间写了一些,题解就懒得补了/emm。
首先如果钦定了每个点选第一个还是第二个,那么就可以直接每个 向所有 的 连边。
如何判断是否存在完美匹配?直接把 侧看作 , 侧看作 ,每个后缀权值 即可(当然也可以从 定理的角度得到)。接下来考虑贪心地使得尽量多的点选第一个数:
一开始默认他们都选第一个数,当某一刻的后缀权值 ,选出后缀中的某一个点,切换至“选第二个”。此处明显选择“第二个”最小的点,可以用堆维护。
考虑动态的怎么做。先把 个 和 个 按上述方法匹配好,则整个序列的权值是 (因为一定有一个人没匹配)。如果此时已经不存在合法解了,那以后一定不会有。对于新加入的二元组,我们枚举他选择第一个还是第二个。假设他选择了 ,那从 往前的所有前缀权值都会 ,也就是到了 及 以前的,第一个权值为 的位置 ,会出现权值为负数的问题。
同样的,只需要找到 的,选“第一个”的,且“第二个”尽量小的元素,切换一下即可。假设切换到 ,那 及 以前的第一个 处又会出现问题,只需要重复上述过程即可。注意到这样不会重复选择同一个元素。
于是可以预处理,每个 开始往前“跳”需要多少步,或者无解。然后每次只要找到 直接调用即可。
尝试手玩。和样例解释的图一样,可以描述为若干段斜率绝对值为 的斜线。

对于只有 的情况,首先容易给出一个无解的充分条件:若 则必然无解,因为甚至塞不进两条不交的,长度为 的斜线。判完这种情况之后,容易发现就一定能构造一组解了:直接无脑在每个时间段(两条横线之间)随便塞两条斜线就一定可行,只不过可能等待时间很长。
则现在只需要最小化等待时间了,注意到每个时间段看起来非常独立,你可以对每个时间段中任意平移,对合法性没有影响。于是考虑一层一层转移。
如果我们已经得到了上层往这层转移的两个端点 ,其中 是往下走, 是往上走,那么只需再确定两个接口 ,计算 和 即为转移代价。这个问题相当于:在环上有 四个点,顺序任意,且只能顺时针移动,要求 和 的距离和尽量小。
经过一些讨论容易发现在 相对顺序不变的时候,距离是不变的。且 重合或 重合都一定不会漏掉最优解。意思是,当我们选择将向下的斜线一直无缝衔接,只调整向上的斜线,不会漏掉最优解。
于是现在的问题中就只剩下一根向上的斜线了,容易将问题转化为:记录当前斜线的端点(需要满足不和向下的斜线相交,这是模意义下的一个区间),然后转移到下一个点,花费两者之间有向距离。经过对这些限制区间的加减,可以把问题变成:
给定 个区间 ,你可以一开始选定一个变量 ,第 次需要满足 ,你每次可以将 ,求最小操作次数。
可以直接设 表示前 层后 的最小花费,那么:
展开 得到 或 ,改成维护 的最小值即可。使用线段树来优化转移,以下是我没想到的部分:
考虑当前区间是 ,那对于 ,相当于 的部分都可以直接转移, 的部分要 ,于是是一个前缀 和后缀 赋值到当前位置。要对区间内每个 都进行这个操作。有两种思考方式:
注意到这实际上就是有向地移动所花费的代价,于是对于任意到达 的过程,要么是原本就在 ,要么从 来,所以只需要对 这一个位置进行修改即可。
另一种想法是考虑对 两者的转移的差异,只有 这一个点从 变成不 。这相当于只要把 处的答案和 原本的答案 即可,而在以后,如果 一直同时出现,则没必要再修改 ;如果 某一刻不同时出现了,那么必然使用 更新了 。
所以就可以直接线段树维护了,时间复杂度 。
贪心真是太困难了。
首先假设默认都选择 ,然后调整,将 。
假设现在已经选出了 个选 , 个选 ,如果不能通过交换变得更优,那么:
也就是 。如果我们选定了 ,那么一定将 最大的选作 。于是首先将所有数按照 从大到小排序, 一定在一个前缀中选, 在对应的后缀里选。
因此设 表示前缀里选 个 ,后缀里选 个 的最大 。然后枚举分界点即可。时间复杂度 。
首先,一定是一些 11
之间乱换,然后 10
从通过若干个 11
移动到一个 01
上去。
于是,最后一定会形如若干链,从 10
开始,经过若干 11
,以 01
结束。记 10
,01
,11
分别有 个(显然 )。一定有 条链,可以枚举有多少个 中的插入链中,然后剩下的 中部分直接全排列就行了。
至于 条链排列起来,花费 个 中元素,可以直接 。还有一些系数,比如把 分别匹配,有一个 的系数之类的。复杂度可以是 , 或 。
首先有简单的 背包。注意到对于 和 的补集,他们应该恰好在中位数的左右,因此上述背包的方案数是对称的!因此就只关心拼出过哪些数,而不关心有多少种方案了。只需要 bitset
优化即可做到 。
完全不会做/ll
观察最终形态,最后的排列顺序一定是按照 从小到大。如果一个点 被染色了,那他会染到什么样的点呢?
首先,若 ,或 ,那么 一定会染到 (因为互相穿过)。事实证明,找到 的, 最小的 作为 ; 的, 最大的 作为 , 会染黑 中的所有点(还是按 排序)。
具体方式可以通过讨论一个 内点的 的相对关系。于是问题就变成了,要选择一些区间覆盖 。同时,注意到将这些区间按照 的 排序后,左右端点分别单调,所以可以通过前缀和来维护,做到线性 。
orz cxy!