34 min read 6967 words Updated May 03, 2026 Created May 03, 2026
##210856724##211191108##211192375##211194246##211291004##211296415##211298131##211323975##211396680##211401150##211560140##211566195##211609810##221821611##222076413##223847308##225039544##865##define

CF 比赛题解合集

[TOC]

$\downarrow 2023.09.04$

CF1952, CF1954

1952

A. Ntarsis' Set

有一个集合,初始状态里面有数字 $1$$2$$3$$4$$5$、......、$10^{1000}$

现在给你一个长度为 $n$ 数组 $a (1\leq a_i \leq 10^9 )$,要进行 $k$ 次操作,每次操作将当前集合中第 $a_1$ 小、第 $a_2$ 小、......、第 $a_n$ 小的数同时移除。

请问 $k$ 次操作之后,最小的数是多少。

顺难则逆。

考虑如果已知删除后在集合中的位置,可以很简单的找到删除前的位置。

所以已知初始的位置,也可以很简单的找到删除后的位置,$O(n + k)$ 即可。

void work() {
    int n, k; cin >> n >> k;

    for (int i = 1; i <= n; ++i) cin >> a[i];

    lint i = 1, cur = 1, pre = 0;
    while (k--) {
        cur += pre;
        while (i <= n && a[i] <= cur)
            ++cur, ++i, ++pre;
    }

    cout << cur << '\n';
}

B. Imbalanced Arrays

对于一个给定的长度为 $n$ 的数组 $A$,定义一个长度为 $n$ 的数组 $B$ 是不平衡的当且仅当以下全部条件满足:

  • $-n \leq B_{i} \leq n$$B_{i} \ne 0$。即每个数在 $[-n,n]$ 内且不为 $0$

  • $\forall i,j \in [1,n], B_{i} + B_{j} \neq 0$。即数组内不存在一对相反数。

  • $\forall i \in [1,n], \sum_{j = 1}^{n} [ \left (B_{i} + B_{j} \right) > 0] = A_{i}$。即对于任意的 $i$,数组中与 $B_{i}$ 和大于 $0$ 的数的个数恰好为 $A_{i}$注意:这里需要计算本身。也即 $i$$j$ 可以相等。

请构造长度为 $n$ 的不平衡序列。

两种方法,其一可以参见 hfjh

考虑递归的构造序列,如果当前存在 $A_i = 0$ 或者 $A_i = n$,那么其对应所填的数必定为 $-n$ 或者 $n$

由于相反数不可能同时出现,所以两个不能同时存在,否则无解。

递归的构造即可。

代码链接:https://codeforces.com/contest/1852/problem/B

C. Ina of the Mountain

  • 给定一个长度为 $n$ 的序列 $a$ 和正整数 $k$

  • 每次可以选择一个区间 $[l,r]$$\forall i \in [l,r],a_{i} = a_{i} -1$

  • 如果 $a_{i} = 0$,则将 $a_{i}$ 变为 $k$

求让序列全部为 $k$ 的最小操作次数。

多组测试数据,$1 \leq n \leq 2 \times 10^{5}$

先不考虑 $\bmod k$ 的情况,则构造差分序列 $d$,答案即为:

$$\sum_{i} [d_i \gt 0]d_i $$

那么考虑每次 $0 \to k$ 的变换,相当于在原序列上加了 $k$,然后求上式。

考虑变成差分序列上加减。也就是有地方 $+k$,有地方 $-k$,使得上式最小。

所以考虑正负平衡一下即可。

代码链接:https://codeforces.com/contest/1852/submission/221761642

能考场切自是极好。

D. Miriany and Matchstick

你有一个 $2\times n$ 的矩阵,第一行给定(字符串 $s$),你需要在第二行的位置填上 $A$$B$

你需要构造矩阵的第二行,使得该矩阵相邻的格子不同的个数恰好为 $k$

考虑很 naive 的 DP $f_{i, 0/1, k}$ 表示填完前 $i$ 个数,恰好为 $k$ 是否可行。

打表可以发现,$k$ 可行的集合至多为两个区间。

证明:每一次转移可以是 $+1$ 或者 $+2$,同时又是前面的两个区间并过来的,所以空缺只会是 $0/1$ 个。

所以可以压成 $f_{i, 0/1}$ 即可 /kel

$$f_{i, 0} = (f_{i - 1, 0} \cup (f_{i - 1, 1} + 1)) + (s_i \ne s_{i - 1}) \\ f_{i, 1} = ((f_{i - 1, 0} + 1) \cup f_{i - 1, 1}) + (s_i \ne s_{i - 1}) $$

所以可以用 bitset 对吧。

最后贪心的构造即可。

E. Rivalries

Ntarsis 有一个长为 $n$ 的数组 $a$

定义一个子数组 $a_l \cdots a_r$ 的权重为:

  • 在整个数组 $a$ 中,只出现在该子数组 $a_l \cdots a_r$中的最大元素 $x$
  • 若不存在这样的 $x$,权重为 $0$

称数组 $b$$a$ 数组匹配,当且仅当满足:

  • $2$ 者长度相等。
  • 数组 $a$ 中的每个子数组的权重都与数组 $b$ 对应的子数组的权重相等。
  • $b$ 中的数都为正数。

最大化 $b$ 的权值和。

$1 \le n,t \le 10^5$

考虑几个 hints

  • 对于每一个值,只有最左边和最右边的两个之外的区间可以做出贡献。

  • 将最左和最右记成二元组,如果存在 $a_i \gt a_j$ 并且 $i$ 完全被 $j$ 覆盖,那么 $j$ 将无法做出任何贡献。

  • 为了不改变权重,我们只可能增加上面所说的 $j$ 区间。

  • 并且至多会有一个区间会加上某一个数。

1954

A. Dual

$t$$1\le t\le 500$)组数据,对于每组数据给出一个长度为 $n$$1\le n\le 20$)的序列 $a$$-20\le a_i\le 20$)。

可以进行 $k$$0\le k\le 31$)次操作,每次操作任选一组 $i,j$$1\le i,j\le n$),把 $a_i\leftarrow a_i+a_j$,最后使得整个序列单调不减。

对于每组数据,第一行输出 $k$,之后 $k$ 行输出执行操作的 $i,j$

超级分讨。

考虑到全部变成正的,或者全部变成负的,然后前缀/后缀和即可,这需要 $19$ 次。

首先找到绝对值最大的那个数。

如果异号的个数 $\le 12$,那么直接加上即可。

反之,则同好的个数 $\le 7$,那么找到最大的正数,做 $5$ 次自加操作,然后加上去即可。

代码链接:Submission #221821611 - Codeforces

B. Earn or Unlock

有一长度为 $n$ 的一副牌,每张牌上都有一个数字,设第 $i$ 张牌上的数字为 $a_i$。初始时,你手里只有第一张牌。对于每一张牌,你有两种选择:

  • 如果剩余的牌数量 $< a_i$,则将牌摸完,否则继续往下摸 $a_i$ 张牌。摸牌完成后,这张牌会被丢弃。

  • 获得 $a_i$ 的分数,并丢弃这张牌。

求你能获得的最大分数。

对于所有数据,保证 $1 \le n \le 10 ^ 5$$0 \le a_i \le n$

考虑如果可以摸完 $k$ 张牌,由于摸一张牌的代价为 $1$,所以得分为:

$$- k + 1 + \sum_{i = 1}^k a_i $$

所以判断哪些地方可以摸到即可。

考虑一个 naive$O(n^2)$ DP。

有:

$$f_i |= f_{i - a_i} \text{~ then ~} f_i = 0 $$

于是可以考虑用 bitset 优化。

所以总的复杂度为 $O(\frac {n^2} w)$

代码:https://codeforces.com/contest/1854/submission/221792387

C. Expected Destruction

给定大小为 $n$ 的正整数集合 $S$$S$ 中的每个数在 $1\sim m$ 之间。

每一秒进行如下操作:

  1. $S$ 中等概率随机选择一个数 $x$
  2. $x$$S$ 中删去。
  3. $x + 1\leq m$$x + 1\notin S$,则将 $x + 1$ 加入 $S$

$S$ 变成空集的期望时间,对 $10 ^ 9 + 7$ 取模。

$1\leq n\leq m \leq 500$$1\leq S_1 < S_2 < \cdots < S_n \leq m$

1843

Div. 3 果然简单,虽然但是,我还是有 1 道题没有想出来。

A.Sasha and Array Coloring

排序双指针向内即可。

https://codeforces.com/contest/1843/submission/210855587

B.Long Long

好啊,就是这道题没想出来。

Virtual Contest 上完成了一半。

考虑把符号相同(0 与任何数符号相同)的合并。

因为放在一起操作显然最优。

bool sgn_eq(int x, int y) {
    return (x * y) >= 0;
}

然后你就得到了一个 ... + - + - ... 正负交替的序列。

那么,很明显,正数与负数的个数相差不超过一,也就是说花费 1 的代价将负数转化为正数的行为是不可取的(我就死在这上面,如此弱智的东西……),于是记录所有负数的个数即可。

有可能溢出,要精细实现

https://codeforces.com/contest/1843/submission/211085413


也可以直接合并负数序列(忽略 0 的情况)

https://codeforces.com/contest/1843/submission/211082437

C.Sum in Binary Tree

会手写堆的人都会写……

Submission #210856724 - Codeforces

D.Apple Tree

弱智题……记录一下每一个节点有多少个叶子节点。输出相乘的结果即可。

https://codeforces.com/contest/1843/submission/210857337

E.Tracking Segments

其实可以改一下题目,变为:

对于每一条线段,求出其变成 beautiful segment 的时间,如果不会变,则输出 -1,顺便强制在线一波。这样代码难度递增。

我首先想到的是一个在线做法。

只要在这个区间内修改了严格大于一半的点,那么一个区间就变得 美丽

那么什么最早是什么时候?

定义序列 $t_i$ 表示第 $i$ 个点变成 $1$ 的时间,如果没有修改则 $t_i = \inf$

对于区间 $[l, r]$,设 $k = \lfloor \frac {l - r + 1} 2 \rfloor + 1$,则对于序列 $t$ 的区间 $[l, r]$$k$ 小即为所求。

如果为 $\inf$ 则不会变得 美丽

但是显然这太过于复杂。

考虑离线处理每一个线段,并且二分答案。

明显答案具有单调性,如果在 $t$ 时变得 美丽,则之后一直会很 美丽

我说的不是我们

我们只加入前 $mid$ 个点,然后用一个前缀和一一判断有没有 美丽 的线段即可。

如果是 美丽 的,则满足在这个区间内有 $\ge k$ 个点变成了 $1$

https://codeforces.com/contest/1843/submission/211083551

F.Omsk Metro

自己做的时候胡的性质:

对于一个路径 $p$,定义其最大子段和$mx_p$最小子段和$mn_p$

那么可以拼凑出来的区间为 $[mx_p, mn_p]$

感性证明一下:

这里不妨把一条路径拍扁成一条链,设为 $[l, r]$

我们考虑加入一个点 $r$ 对于一条路径 $[l, r]$ 的影响。

$suf_x$ 为以 $x$ 为右端点,可以凑出来的权值的集合。

考虑递推,有 $suf_x = \{0, w(x)\} \cup (suf_{x - 1} + w(x))$

于是对于区间 $[l, r]$$S = \bigcup_{l \le x \le r} suf_x$

其实不难发现,$suf_x$ 的上下界每一次最多只会变化 $1$,也就是说,如果可以凑出 $x (x \ge 0)$,那么一定可以凑出 $[0, x]$。负数的情况同理。

所以我们考虑求出最大的,和最小的子段和即可 $O(1)$ 判断……

实现上也就是树链剖分加上基本的求区间最大子段和的思路即可。

1834

Virtual Contest 做了 5 道题,非常不错。

A.Unit Array

秒切题,判断个数,然后判断一下奇偶即可。

提交:https://codeforces.com/contest/1834/submission/211190220

B.Maximum Strength

题目描述

每一种材料的力量由一个十进制整数表示。

对于一个武器,由两种材料构成。假如第一种材料的力量为 $X = \overline{x_1x_2 \dots x_n}$,第二种材料的力量为 $Y = \overline{y_1y_2 \dots y_n}$,那么这个武器的力量为 $\sum_{i = 1}^n |x_i - y_i|$,也就是 $|x_1 - y_1| + |x_2 - y_2| + \dots + |x_n - y_n|$

如果两个数字长度不一样,则要将短的数字用前导零补成相同长度

现在,你拥有无数个力量在 $[L, R]$ 中的材料。你想要选出两个材料做出一个力量最大的武器。请你求出你设计出的武器力量的最大值。

题解

找到第一个不同的地方,其他地方全部填 $|9 - 0|$ 即可。

大数填 0,小数填 9,这样一定满足在区间内。

提交:Submission #211191108 - Codeforces

C.Game with Reversing

题目描述

你有两个长度为 $n$ 的序列 $S, T$

你将不断重复以下步骤直到两个序列相等:

  1. $S$ 或者 $T$任意选择一个数字,然后修改为另一个数字。如果此时序列相等,则结束操作,否则进入操作 $2$

  2. 任意反转一个序列。如果此时序列相等,则结束操作,否则重复操作 1。

注意:操作 $1$ 和操作 2 都计入操作次数中。

你需要输出最小化的操作次数。

解题

正序和逆序分别讨论一下,取 $\min$ 即可。

$icnt$ 表示正序不同的个数,$rcnt$ 表示逆序不同的个数。

那么 $ans = \min(2 \times icnt - icnt \% 2, 2 \times rcnt - (rcnt - 1) \% 2)$

提交:https://codeforces.com/contest/1834/submission/211198802

D.Survey in Class

对于每一个学生的学习集合,答案是 $2 \times \max(|S_1| - |S_1 \cap S_2|)$

$O(n \log n)$

考虑使用树状数组维护线段,从左向右扫一遍。

$O(n)$

考虑两条线段的关系,三种:

  • 左边

  • 相交

  • 右边

对于每一个 $S_1$,我们需要最小化 $|S_1 \cap S_2|$,所以对于三种情况,我们维护三个线段:

  • 右端点最左

  • 最短

  • 左端点最右

分别判断即可。

提交:Submission #211192375 - Codeforces

E.MEX of LCM

我考场上的做法

考虑只有 $O(n^2)$ 个取值,那么 $mex$ 一定 $\le n^2$。所以我们限制了答案的上界,设为 $U$

实际上有更紧的上界,根据:CF1834E MEX of LCM 题解 - LCTTTTTTTTTTT - 洛谷博客$U$ 可以 $= 4256233$

考虑对于一个固定的右端点,其左端点与其匹配的 $lcm$ 是单调的,并且不同的数量在 $O(\log U)$

考虑每一次变化 $lcm$ 至少 $\times 2$

所以考虑用一个 set 维护。

同时,再用一个 set 维护所有出现过的 lcm (考虑是 $O(n \log U)$ 个,空间没问题)

所以总复杂度为 $O(n \log V \log U \log \log U)$

提交:Submission #211194246 - Codeforces

还有的思路

考虑每一个左端点,可以二分找 lcm 的分界,当值大于上界的时候退出。

用桶或者什么东西操作一下即可。

复杂度为 $O(n \log U \log n)$

然而还有玄学优化,参考:出错了 - 洛谷,在 题解界面@Xy_top 的即可。

$\downarrow 2023.09.06$

1830

B. The BOSS Can Count Pairs

多组数据。

每组数据给你一个 $n$ 和两个序列 $a,b$

求有多少个数对 $(i,j)$ 满足 $1 \le i < j \le n$$a_i \times a_j = b_i + b_j$

对于每一个 $i$ 看作用 $a_i \times x - b_i = y$ 这条线来切所有的点。

注意到当 $a_i$ 很大的时候的简单的,我们只需要用一个桶记录一下 $(x, y)$ 的个数即可,然后可以 $O(\frac n {a_i})$ 求出。

此时设一个阈值 $B$,当 $a_i \gt B$ 的时候认为是很大的,所以上面的复杂度可以看作 $O(\frac n B)$

问题在于当 $a_i$ 很小的时候,注意到其实可以 $O(B)$ 预处理出 $\forall k \in [1, B]$ $k \times a_i - b_i$ 的值。

这样就可以 $O(1)$ 查询了。

两者稍微平衡一下,令 $B = \sqrt {2n}$ 于是可以 $O(n \sqrt {n})$ 解决本题。

代码链接: https://codeforces.com/contest/1830/submission/222008847

C. Hyperregular Bracket Strings

给定一个数 $n$$k$ 个区间 $\left[l_i,r_i\right]\in [1,n]$

我们定义,对于一个长度为 $n$ 的,仅由 () 组成的合法括号序列,如果它的每一个区间 $\left[l_i,r_i\right]$ 内的子串都是合法括号序列,那么这个括号序列是好的

好的括号序列的数量,答案对 $998244353$ 取模。

相交和包含的情况很 naive,重点在于如何处理。

类比 $2023.09.05$ izumi,采用一个随机化异或的做法。

每一个区间附上一个神秘的权值,差分前缀一次。

如果异或权值相同,意味着需要形成一个合法括号,这预处理卡特兰数即可。

rapper 的讲解见:hfjh

代码链接:https://codeforces.com/contest/1830/submission/222007540

D. Mex Tree

给定一棵 $n$ 个结点的树,点有点权,点权为 0 或 1。你需要给一种指定点权的方案,使得每一条路径的点权 $\operatorname{mex}$ 之和最大。

$n\le 2\times 10^5$,多组数据。

如果考虑跨越多种数的正贡献,发现很难。于是考虑块内的负贡献。

正难则反!!!!!!!!!!!!!!!!!!!!!!!哦

对于每一个连通块,考虑树形背包。

$$\begin{aligned} f_{x, i, 0} &\leftarrow \min(f_{x, i, 0} + f_{j, k, 1}, f_{x, i - k, 0} + f_{j, k, 0} + (i - k) \times k) \\ f_{x, i, 1} &\leftarrow \min(f_{x, i, 1} + f_{j, k, 0}, f_{x, i - k, 1} + f_{j, k, 1} + 2 \times (i - k) \times k ) \end{aligned} $$

关键结论是连通块的大小一定不会很大,否则减少的贡献太多了。

有证明在 $n \le 2e5$ 小不会超过 $258$

代码:https://codeforces.com/contest/1830/submission/222027041

E. Bully Sort

对于一个非升序的排列 $\{p_i\}$,定义一次操作为按顺序执行以下步骤:

  1. $p_i$ 为排列中最大的满足 $p_i\neq i$ 的数。

  2. $p_j$ 为排列中最小的满足 $i 的数。

  3. 交换 $p_i$$p_j$

可以证明在排列非升序的前提下总能找到满足条件的 $i$$j$

定义一个排列的权值为将其升序排序所需的操作次数,可以证明总能在有限次操作内将其升序排序,注意如果排列本身就是升序的那么其权值为零。

现在给定一个排列和若干次修改操作,求出每次修改后排列的权值,每个修改操作为交换排列中指定的两个数。

注意修改是永久的。

发现排序方式和冒泡排序很像,于是考虑与逆序对之间的关系。

发现每次交换 $(i, j)$ 使得逆序对的个数减少 $2(j - i) - 1$

发现 $2(j - i)$ 这个东西很好,考虑交换会影响什么改变 $2(j - i)$

发现 $\sum_{i = 1}^n |p_i - i|$ 符合要求。

发现两者最后都为 $0$

发现操作次数等于 $\sum_{i = 1}^n |p_i - i|$ 与逆序对个数之差。

于是动态维护逆序对即可。

发现分块很优秀,$O(n \sqrt{n \log n})$,虽然是正常的 $O(n \log^2 n)$ 的树套树的四倍时间……

代码:https://codeforces.com/contest/1830/submission/222012835

1836

A.Destroyer

开个桶记录个数,看满不满足单调不上升即可。

B.Astrophysicists

辛辛苦苦写了这么久的文章就没了????烦死了。

自己做 Virtual Contest 的时候这道题打表打了半天(20min)才搞定……

题目大意

$n$ 个人,$k$ 个金币,每个金币价值 $g$ 个银币。

良心公司要把这 $k$ 个金币作为工资分给这 $n$ 个人,但是没有办法平均分配,良心老板想出了分配规则:

  • 由你设定每个人分配的银币数 $x_i$

  • 你需要保证 $\sum_{i = 1}^n x_i = k \times g$

  • 老板会把银币数转化为金币发放,所以想出了以下规则:

    • $r = x \mod g$,如果 $r \ge \lceil \frac g2 \rceil$,那么公司会额外花费 $g - r$ 个银币以凑出完整的金币(此时花费了 $x + g - r$ 个银币)。

    • 反之,会吞掉这 $r$ 个银币以凑出完整的金币(此时花费了 $x - r$ 个银币)。

假定最终公司的花费为 $p$ 个银币。你需要最小化 $p$,并输出 $k \times g - p$

解题思路

如果开始没有思路,那么打表是一个很好的方法。

首先我们可以很轻易的得到一个 $O(nkg)$ 的 DP 算法。

$f_{x, i}$ 表示处理到第 $x$ 个人,一共分配了 $i$ 个银币公司省下的最多银币。

有转移方程:

$$f_{x, i} = \max_{0 \le j \le i} f_{x - 1, i - j} + w(j) $$

其中:

$$r = j \mod g $$

$$w(j) = \begin{cases} r - g &, r \ge \lceil \frac g2 \rceil \\ r &, r \lt \lceil \frac g2 \rceil \end{cases} $$

运行后输出 DP 数组,结合 $m = \lceil \frac g2 \rceil - 1$可以很轻易的发现规律:

最终的数组分为两个部分:

  • 第一个部分为 $[0, nm]$,下标与数值一一对应。

  • 第二部分为 $[-\lfloor \frac g2 \rfloor - m - nm, nm]$ 不断循环。


现在我们来严谨证明一下。

理想状态下,我们自然是给每一个人分发 $m = \lceil \frac g2 \rceil - 1$ 个银币,这样就可以吞掉 $nm$ 个银币。

但是可能存在一下两种情况:

  • 其实根本没有 $nm$ 个银币,所以全部都分配到 $\le m$ 个。所以全部可以吞掉。对应上文中第一部分。

  • 还剩下了 $r = k \times g - nm$ 个银币。由于我们可以按照一个金币为单位再分配,所以我们只需要关注 $r \mod g$ 的值。

    显然,如果把这些银币分给不同的人是不优的,因为破坏了老板吞掉更多人 $m$ 个银币的美梦。

    所以这些银币应该全部分配给一个人,对于答案做出贡献 $w(m + k \times g- nm) - m$

    化简一下)对应上文中第二部分。

提交记录:https://codeforces.com/contest/1836/submission/211134556

C.k-th equality

注意,注意:

Each input file has at most 5 test cases which do not satisfy A,B,C≤3.

所以,$O(10^{\min(A, B)})$ 可以过。

那么考虑顺序枚举 $A$ 位的数 $a$,满足的数 $b$ 应该为一个连续区间,这个可以 $O(1)$ 解决。

所以区间长度与 $k$ 判断一下即可。

提交记录:https://codeforces.com/contest/1836/submission/211137329

1835

B. Lottery

给定一个长度为 $n$ 的序列 $v$,其值域为 $[0,m]$

现在你需要选择一个 $x \in [0,m]$,使其权值最大。定义一个数 $x$ 的权值为:

$$\sum_{c=0}^{m}[\sum_{i=1}^{n}[\vert v_i - c \vert \leq \vert x - c \vert] < k] $$

请你找到权值最大的数 $x$,若有多个,输出最小的那个。

考虑 $k = 1$ 的特殊情况,发现两个人内部的所有点都造成了 $\frac 12$ 的贡献。所以告诉我们不需要枚举太多的点,在一些点的周围枚举一下即可。

这可以很合理的外推到所有的 $k$ 的情况。

C. Twin Clusters

给定 $2^{k+1}$$[0,4^k)$ 内的整数,请求出任意两个不交非空区间使得其异或和相等,若无解则输出 -1

抽屉原理抽象题。-1 是不可能的,这一定有解。

于是考虑生日悖论,随机化一些区间即可(逃。

考虑正解,将 $4^k$ 分成前 $k$ 位和后 $k$ 位。

前缀异或和有 $2^{k + 1} + 1$ 个,而前 $k$ 位最多有 $2^k$ 种取值。所以至少会有 $2^k + 1$ 对前 $k$ 位相等的前缀。

考虑把这些对找出来,其后 $k$ 位却也只有 $2^k$ 种取值,所以至少有两对的后 $k$ 位的异或值相等。所以就完了。

代码:https://codeforces.com/contest/1835/submission/222050899

D. Doctor's Brown Hypothesis

给定一张 $n$ 个点 $m$ 条边的简单有向图和常数 $k$,请求出有多少组 $(x,y)$ 满足 $1\le x\le y\le n$ 且存在一条 $x$$y$ 和一条 $y$$x$ 的长为 $k$ 的路径,$k\ge n^3$

发现 $n^3$,所以发现可以随便走环凑最小公约数。

于是先缩点,在连通块内考虑。

找出生成树,考虑一个非树边,有结论,$d | \mathrm{abs}(dep_y - dep_x - 1)$

所以可以找出 $d$,而合法当 $k \equiv 0 \pmod d$ 或者 $d \equiv 0 \pmod 2 \text{ and } k \equiv \frac d2 \pmod d$

用桶记录一下即可。

代码:Submission #222076413 - Codeforces

1827

A. Counting Orders

简单计数。

两个都排序,双指针维护一下 a[i]b[p] 的位置(a[i] <= b[p])。

那么方案数 $\times (p - i)$

提交:https://codeforces.com/contest/1827/submission/211387552

C. Palindrome Partition

回文好题

考虑利用 Manacher 求出每一个偶数的回文串。

参考:算法学习笔记(13): Manacher算法 - jeefy - 博客园

观察可以发现:每一个合法的串都可以被划分为多个最小的合法串,并且划分方法是唯一的。

所以考虑如下:

我们需要维护出每一个点作为右端点,最靠近的左端点。

这等价于求出满足 $i + p[i] \ge x$,求 $\max i$

然后,设上面对于端点 $i$ 求出来的结果为 $g_i$

得出最终的递推式:

$$f_i = \begin{cases} 0 &,g_i = 0 \\ f_{i - g_i} + 1 &, g_i \ne 0 \end{cases} $$

其中 $f_i$ 表示以 $i$ 结尾的合法的串的个数。

最终的答案为 $\sum f_i$

提交:Submission #211396680 - Codeforces

D. Two Centroids

性质好题

重心有如下性质:

  • 最大子树大小 $\le \lfloor \frac n2 \rfloor$

  • 新增一个叶子节点,重心最多变化一条边。

  • 重心至多有两个。

那么我们考虑每次加入一个点对于原来重心 $c$ 的影响,并设当前最小的子树大小为 $mx$

  • 如果加入的叶子节点在 $c$ 的子树 $t$ 内。更新 $t$ 的大小,并更新 $mx$。如果此时 $mx \ge \lfloor \frac n2 \rfloor + 1$,那么重心向 $t$ 移动。并且此时 $mx$ 更新为 $\lfloor \frac n2 \rfloor$不考虑,把图画出来就明白了

  • 由于我们不可能动态维护以每一个重心为根,所以还要考虑其祖先的情况(同理)。

然后就是如何找 $t$ 的问题。有两种解决方案:

  • 无论如何首先可以通过 dfn 序判断是否在其子树内。

    • 方案1:利用倍增的方法跳祖先。空间复杂度 $O(n \log n)$,单次 $O(\log n)$

    • 方案2:利用 dfn 区间,对于每一个节点保存其子节点的 dfn,每次二分找到叶子的 dfn 所在的区间即可。(我用的这种方法)空间 $O(n)$,单词 $O(\log n)$

  • 实测第二种要快一点点(也快不了多少,主要是常数够好)

提交:Submission #211401150 - Codeforces

E. Bus Routes

差点没用 dlang 卡过去

思路1

考虑更严的限制(等价):叶子节点间两两可以在两次内到达。

于是考虑对于每一个叶节点,求出其能到达的最高的祖先 $high(x)$

也就是求一个 LCA 即可。

那么满足条件的必要条件是每一对 $high(x), high(y)$ 满足祖先/子节点关系。

如果不是,那么至少需要三条路径。

如果满足上述条件,那么所有的 $high$ 满足在一条链上。

那么可以通过 dfn 序判断。

这并不充分。

考虑找到最低那个 $high(x)$,并以 $high(x)$ 作为根。

此时重新求一次 $high$,如果所有的 $high$ 都为 $high(x)$,那么就是 $ok$ 的,否则,如果有 $high(y) \ne high(x)$,那么 $x, y$ 不可达。

不要写倍增求 LCA,利用 ST表 $O(n \log n) \sim O(1)$ 或者 树链剖分 $O(n) \sim O(\log n)$ ,甚至是离线 $O(n)$ 求。倍增太慢了,dlang 卡不过去。

思路2

参考 Alex_Wei 的博客:https://www.luogu.com.cn/blog/_post/575397

利用 DSU on tree

思路3

维护虚树并树上差分。非常的高效。

参考:CF1827E Bus Routes - Kubic 的博客 - 洛谷博客

1824

LuoTianyi and the Show

$n$ 个人观看一场与 VOCALOID 有关的演出,场地里有一行座位,从左到右标号 $1$$m$,接下来观众将按顺序以如下三种方式中的一种选择座位:

  1. 如果没人坐在座位上,就坐在座位 $m$ 上,否则坐在目前最靠左的人的左边。若座位 $1$ 有人,则离开。
  2. 如果没人坐在座位上,就坐在座位 $1$ 上,否则坐在目前最靠右的人的右边。若座位 $m$ 有人,则离开。
  3. 如果 $x_i$ 没人则坐在 $x_i$,否则离开。

现在知道每个人选择座位的方式,你可以让人们按照任意顺序入场,求最多找到座位的人数。

安排方式只有三种,1/2/3 分别先,依次向左/向右/向两边扩展即可。

LuoTianyi and the Floating Islands

给定一棵 $n$ 个结点的树,现在有 $k(k\le n)$ 个结点上有人。

一个结点是好的当且仅当这个点到所有人的距离之和最小。

求在这 $n$ 个点中随机取 $k$ 个点时,好的结点的期望个数,对 $10^9+7$ 取模。

发现用点来算很难算,于是考虑用边来算贡献。由于每种情况边会比点数少 $1$,所以期望点数等于期望边数 $+1$,于是考虑边如何做贡献,两边的点数相等即可。

于是就搞定了:https://codeforces.com/contest/1824/submission/222881710

LuoTianyi and XOR-Tree

给定一棵 $n$ 个节点的树,根节点为 $1$ ,每个点有一个点权 $a_i$ ,每次操作可以选择一个点任意修改点权,求最少的操作次数,使得每一条根结点到叶子结点的路径上的异或和都为 $0$

如果要相等,那么只需要子树所有相等,那么改变只需要改变自己即可。

所以找到子树中最多的那个值,保留即可。

并且启发式合并即可……

代码:https://codeforces.com/contest/1824/submission/222885893

注意 if (maxcnt > 1) 的优化,否则会 TLE。

LuoTianyi and the Function

Feyn 给了你一个长度为 $n$ 的整数数组 $a$,下标由 $1$ 开始。

用以下方式定义函数 $g(i,j)$

  • $i\le j$ 时,$g(i,j)$ 是满足 $\{a_p:i\le p\le j\}\subseteq\{a_q:x\le q\le j\}$ 的最大整数 $x$
  • 否则 $g(i,j)=0$

$q$ 次询问,每次给定 $l,r,x,y$,请求出 $\sum\limits_{i=l}^r\sum\limits_{j=x}^y g(i,j)$ 的值。

需要个可以区间赋值和历史版本求和线段树……不会额。

$\downarrow 2023.09.11$

1819

A. Constructive Problem

给定整数 $n$ 和一个非负整数序列 $a$

你需要选择整数 $l,r,k(1\leq l\leq r\leq n;0\leq k)$,然后将 $a_l,a_{l+1},\cdots,a_r$ 的值均变为 $k$

判断能否通过恰好一次上述操作使操作后的 $\mathrm{mex}(a)$ 增加 $1$

如果没有 $\mathrm{mex}(a) + 1$ 的存在,并且 $\mathrm{mex}(a) \lt n$,那么一定存在方案。

否则,需要变换所有的 $\mathrm{mex}(a) + 1$,而为了使影响最小,只是恰好包含所有的区间变成 $\mathrm{mex}(a)$,重新求一次 $\mathrm{mex}$ 即可。

代码:https://codeforces.com/contest/1819/submission/222839488

B. The Butcher

有一张 $h\times w$ 的纸片,但你并不知道 $h$$w$ 的具体数值。现在对这张纸片进行 $n-1$ 次裁剪。每次裁剪后会将其中一半收归(即这一半不会再被裁剪),保证纸片不会被旋转。

告诉你最终裁剪后的 $n$ 张纸片长宽,问初始有多少 $h\times w$ 的纸片可以裁剪成这 $n$ 张纸片,输出所有可行的 $(h,w)$

发现一张一定是 $h$ 或者 $w$,那么找到 $\max h$$\max w$ 作为两种可能即可。

由于每次减下 $w, h$ 递减,所以考虑双指针扫一遍即可。

代码:https://codeforces.com/contest/1819/submission/222845297

C. The Fox and the Complete Tree Traversal

给定整数 $n$ 和一棵包含 $n$ 个节点的树。

$\text{Dist}(x,y)$ 表示树上节点 $x,y$ 之间最短路径的边数。

你需要判断是否存在一个 $1\sim n$ 的排列 $p$,满足:

  • $\text{Dist}(p_i,p_{i+1})\leq 2$ 对任意整数 $i(1\leq i 成立。
  • $\text{Dist}(p_1,p_n)\leq2$

存在则输出 Yes 然后输出任意一个满足要求的 $p$,不存在则输出 No

有两种方法,一种是我考场想出来的,分讨比较严重:

先考虑状态 $f_{x, 0/1}$ 表示走完其子树后是否可以在其子节点或者本身上。

发现叶子节点对于其可行性没有影响,考虑非叶节点的影响。

不难分类讨论,设当且节点为 $x$

  • 如果没有非叶节点,那么不难发现最后无论在哪里都可以。
  • 如果只有一个非叶节点 $y$,那么发现 $f_{x, 0}$ 满足当且仅当 $f_{y, 1}$ 满足,同理,$f_{x, 1}$ 满足当 $f_{y, 1}$ 满足。
  • 如果有两个非叶节点,发现除非这个点是根,或者父节点为根且根没有其他子树,否则绝对无法满足。而如果满足上述条件,那么最开始无论是从 $x$ 出发,还是最终到达 $x$ 本质相同。

所以我们可以愉快的 DP 了,但是考虑父节点为根且根没有其他子树的情况不太好判断,所以任意找一个度数 $\ge 2$ 的点作为根,那么自然这个条件就无法满足,如果没有找到……这还是能一颗树?

int rt = 1;
void dfs(int x, int p) {
    dep[x] = dep[p] + 1;

    int son = 0;
    vector<int> nonleaf; 
    for (int y : G[x]) {
        if (y == p) continue;
        ++son;
        dfs(y, x);
        if (!leaf[y]) nonleaf.push_back(y);
    }

    if (son == 0)
        leaf[x] = 1, f[x][1] = 1;
    else if (nonleaf.size() == 0) 
        f[x][0] = f[x][1] = 1;
    else if (nonleaf.size() == 1) {
        int y = nonleaf[0];
        f[x][0] = f[y][1], f[x][1] = f[y][0];
    } else if (x == rt && nonleaf.size() == 2) {
        int y = nonleaf[0], z = nonleaf[1];
        if ((f[y][0] && f[z][1]) || (f[y][1] && f[z][0])) f[x][1] = true;
    }
}

这样,从根开始,依据 DP 转移的过程构造即可。

vector<int> v;
void construct(int x, int t, int p) {
    vector<int> nonleaf;
    for (int y : G[x]) {
        if (y != p && !leaf[y]) nonleaf.push_back(y);
    }

    #define pushLeaf() { for (int u : G[x]) if (u != p && leaf[u]) v.push_back(u); }
    if (nonleaf.size() == 0) {
        if (t == 0) v.push_back(x);
        for (int y : G[x]) {
            if (y != p) v.push_back(y);
        } if (t == 1) v.push_back(x);
    } else if (nonleaf.size() == 1) {
        int y = nonleaf[0];
        if (t == 0) {
            v.push_back(x);
            construct(y, 1, x);
            pushLeaf();
        } else {
            pushLeaf(); 
            construct(y, 0, x);
            v.push_back(x);
        }
    } else if (nonleaf.size() == 2) {
        int y = nonleaf[0], z = nonleaf[1];
        v.push_back(x);
        if (f[y][1] && f[z][0]) {
            construct(y, 1, x);
            pushLeaf();
            construct(z, 0, x);
        } else if (f[y][0] && f[z][1]) {
            construct(z, 1, x);
            pushLeaf();
            construct(y, 0, x);
        } else assert(nonleaf.size() == 2);
    }
}

虽然是说稍微复杂了一点,但是分讨很简单,代码依据分讨就可以直接模拟出来,十分的 naive,这比正解要更 brute force 一点(CF优良传统)。

而对于正解,先找出最长链,那么支链的深度不能超过 $1$,否则一定不合法,$O(n)$ 做即可,只是要扫很多遍而已。

D. Misha and Apples

给定 $n$ 个集合 $S_i$,第 $i$ 个集合的大小为 $k_i$,集合元素为 $1\sim m$ 的正整数。特别地,若 $k_i = 0$,则 $S_i$ 可以是正整数 $1\sim m$ 的任意可空子集,由你确定

可重集 $S$,初始为空。按编号从小到大依次遍历每个集合,往 $S$ 中加入 $S_i$ 所有元素。每次加入当前集合的所有元素后,若 $S$ 包含重复元素,则清空 $S$。注意,一个集合内的元素 同时 被加入 $S$

你需要确定 $k_i = 0$$S_i$ 具体包含哪些数,使得最终的 $|S|$ 最大。求出这个最大值。

$1\leq T, \sum n, m\leq 2\times 10 ^ 5$$0\leq \sum k_i\leq 2\times 10 ^ 5$$S_i$ 的元素互不相同。

考虑找到可以清空的位置 $can_i$,以及每一个 $i$ 往前最多可以保留到的位置 $late$

每次找到最后一个冲突的位置 $max\_conflict$ 记为 $mc$,于是如果 $mc \le late$ 那么对于 $late$ 没有影响,而 $can_i$ 可行当且仅当 $(late, i]$ 之间存在一个 $k = 0$

否则 $can_i$ 一定可行,而 $late$ 需要更新到 $mc$ 之后第一个 $can_i$$1$ 的点。

于是,就搞定了。

E. Roads in E City

这是一道交互题

给定一张 $n$ 个点 $m$ 条边的无向连通图,无自环,但可能有重边。

图上有一些特殊边,保证任意两个结点通过特殊边连通,你希望求出所有特殊边。

初始所有边都没有被堵住。你可以进行以下三种操作:

  • $-\ x$$1\leq x\leq m$):如果第 $x$ 条边没有被堵住,则堵住该边。
  • $+\ x$$1\leq x\leq m$):取消堵住第 $x$ 条边。操作前第 $x$ 条边必须被堵住。
  • $?\ y$$1\leq y\leq n$):交互库随机选择某个 $s$ 并返回能否从 $s$ 出发走没有被堵住的特殊边到 $y$

你最多进行 $100m$ 次操作。

$2\leq n\leq 2000$$n - 1\leq m\leq 2000$$1\leq t\leq 1000$$\sum n, \sum m\leq 2000$。保证图无自环且连通。

利用其随机化,以及联通的性质。

找到一个特殊的生成树,然后考虑非树边即可。

问题在于如何判断树边,断开,然后两边跑 $k$ 次,那么错误率为 $(\frac x n \frac {n - x} n)^k$,在 $k \to 20$ 的时候就趋近于 $0$ 了,可以认为完全正确。

于是就做完了。

$\downarrow 2023.09.18$

1817

A. Almost Increasing Subsequence

给定长度为 $n$ 一个序列 $a$ 以及 $q$ 次询问,每次询问给出 $l$$r$,找出序列 $a$$[l,r]$ 内最长的几乎递增子序列。

对于几乎递增的定义:如果一个序列中不存在连续的三个数 $x$$y$$z$,使得 $x \ge y \ge \ z$,则这个序列是几乎递增的。

也就是说每一段递减的都至多取两个。转换一下,减去连续的三个的个数,差分一下即可。

代码:https://codeforces.com/problemset/submission/1817/223787996

B. Fish Graph

定义“鱼图”为满足以下条件的无向图:

  • 该图包含正好 $1$ 个环,环上有 $1$ 个特殊的结点 $u$$u$ 除了连在环上的 $2$ 条边外还有正好 $2$ 条边,每一条边连向一个环外的结点(即,若环的大小为 $s$,整个图一共有 $s+2$ 个结点)。

现在给定一个简单无向图,问该图中是否有一个子图为“鱼图”。一个无向图的子图即为原图中删去若干个点和若干条边所形成的图。如果存在,还需要构造出其中任意一个满足要求的子图。

合法的点当且仅当 $D_x \ge 4$ 并且 $SCC_x \ge 3$,于是可以 $O(n)$ 求了。

注意我的写法中,需要回退,防止 $<><>$ 的这种图找不到环。

代码:https://codeforces.com/problemset/submission/1817/223785932

C. Similar Polynomials

给定两个次数为 $d$ 的多项式 $A, B$$0, 1, 2, \dots, d$ 处的点值对 $10^9+7$ 取模,保证 $B(x) \equiv A(x+s) \pmod {10^9+7}$。求 $s \bmod 10^9+7$

考虑差分:

$$\begin{aligned} \Delta^{n - 1}f &= a(x + s) + b \\ \Delta^{n - 1}g &= ax + b \\ \Delta^{n}f &= \Delta^{n}g = -a \\ \end{aligned} $$

于是可以求出 $s$ 了。

还有拉格朗日插值求出系数然后求的方法,差不多。

代码:https://codeforces.com/problemset/submission/1817/223798973

D. Toy Machine

有一个长 $n$$2$ 的矩形游戏机。保证 $n$ 是奇数。

游戏开始之前,有 $n - 2$ 个玩具放在第一排中间的 $n - 2$ 个位置中(两个角除外)。编号从左到右依次为 $1$$n - 2$。第二行为空,其最左、最右和中心位置是障碍物。你可以控制玩具机向左、向右、向上、向下,分别用字母 $\texttt L$$\texttt R$$\texttt U$$\texttt D$ 表示。

操控时,所有玩具将同时沿相应方向移动,碰到另一个玩具、墙壁或障碍物停止。您的目标是将第 $k$ 个玩具移动到第一行最左边。给定 $n$$k$,构造一个最多使用 $1000000$ 次操作的方案。

认为代码展示了一切:https://codeforces.com/problemset/submission/1817/223803543

E. Half-sum

有一个非负整数序列 $\{a_1,a_2,\dots,a_n\}$

你可以从序列中取任意两个数,并将它们的平均数放回序列。

序列最后会剩两个数,请求出这两个数的差的绝对值的最大值。

因为答案将会是一个小数,所以请输出答案对 $10^9+7$ 取模的结果。

呃,推一点点式子,发现如果从断点 $x$ 到断点 $y$ 的差距为:

$$\sum_{i = x + 1}^{y} (\frac {a_i}{2^i} + \frac {a_i}{2^{n-i+1}}) - \frac {a_x}{2^x} + \frac {a_y}{2^y} + \frac {a_{x + 1}}{2^{n - x}} - \frac {a_{y + 1}}{2^{n - y}} $$

于是可以 $O(y - x + 1)$ 求解,于是发现可以分治求解。

问题在于如何维护这些加加减减的值。

有一个 trickTrygub Number,适用于此。

于是可以 $O(n \log n)$ 求解了。

注意可能需要较快的读入:Submission #223847308 - Codeforces

然而正解,考虑 $2^i$$i \ge 30$ 时便很大了,使得 $\frac {a_i}{2^i}$ 趋近于 $0$,于是可以发现断点只会出现在前/后 $\log n$ 个不同的数上,于是常数为 $64$$O(n)$ 做法新鲜出炉!

1815

Div. 1 确实难,Virtual Contest 上只完成了两道题,想出来了三道题。

A. Ian and Array Sorting

秒切题……考虑将前 $n - 1$ 个数变成一样的一个数 $x$。显然可以完成。

然而考虑此时最后一个数。如果 $\ge x$,那么是 $\texttt{\colorbox{#52C41A}{\textcolor{white}{AC}}}$,如果 $\lt x$,要分类讨论:

  • 如果前面有奇数个,是 $\texttt{\colorbox{#E74C3C}{\textcolor{white}{WA}}}$

  • 反之,则是 $\texttt{\colorbox{#52C41A}{\textcolor{white}{AC}}}$

提交:Submission #211291004 - Codeforces

B. Sum Graph

傻逼交互

好呀好呀,傻逼交互体。想出来了思路,但是就是没有写出来。

考虑 +$n + 1, n + 2$。那么整个图会形成一条链。

static int perm[N]; int l = 1, r = n;
for (int i = 1; i <= n; ++i) {
    perm[i] = (i & 1) ? l++ : r--;
}

于是我们可以在 $n - 1$ 次以内找到链的一端,然后就可以再来 $n - 1$ 次找到可能的排列。

由于我们可能是找到的两端,所以有两种排列方法。

输出即可。

提交:Submission #211296415 - Codeforces

进阶:参考 https://codeforces.com/blog/entry/114847?#comment-1021812 以及 Editorial of Codeforces Round #865 - Codeforces,可以把次数减少到 $n + \lfloor \frac n2 \rfloor + 2$ 次询问。

C. Between

构造好题

考虑包含可以形成依赖。

于是可以形成一张图。

我们从 1 开始 BFS 对其分层,可以发现,第 $i$ 层最多可以放 $i$ 个(包含依赖多套一个)。

那么考虑如何构造合法方案。

我的方法是每一次,按照 BFS 逆序遍历很多遍,每一次遍历到,如果还有没放的则放一个,否则略过。(好像官方题解就是这样?看不懂)

考虑正确性:按照逆序遍历保证出现次数少的在中间,保证不同层之间的依赖关系;每次放一个保证出现次数相同的交替出现,这样就保证了层内的依赖关系无论如何一定满足(互相依赖也没关系)。

提交:Submission #211298131 - Codeforces

D. XOR Counting

打表好题

$m = 1$ 的时候答案就是 $n$

$m \gt 3$ 的时候小小打表,可以发现答案为 $\lceil \frac n2 \rceil \times (\lfloor \frac n2 \rfloor + 1)$

证明:在 $m \gt 3$ 的时候,$[x, \frac {n-x}2, \frac {n-x}2, 0, 0, \dots]$ 可以恰好凑出 $x$,所以所有与 $n$ 奇偶性相同的 $x$(此时 $n-x$ 为偶数,$\frac {n-x}2$ 为整数)都可以被凑出。

然后我们发现,加法和异或得到的奇偶性是一样的,并且有 $a \otimes b \le a + b$,意味着我们只能凑 $\le n$ 并且与 $n$ 奇偶性相同的数。

综合两条,我们便可以得出,所有可能凑出的数就是 $\le n$ 且与 $n$ 奇偶性相同的数。

推一下公式就是上面的了。

于是问题就只剩下了 $m = 2$ 的时候。

我们考虑一个 DP,我们记 $f(n)$ 表示所有可能的异或和的和,$g(n)$ 表示可能的个数。然后稍微分类讨论一下:

  • 如果 $n$ 是奇数,我们不妨假设 $n = a_1 + a_2$,其中 $a_1$ 为偶数,$a_2$ 为奇数。设 $a_1' = \frac {a_1}2, a_2' = \frac {a_2 - 1}2$。我们可以看出:$a_1' + a_2' = \frac {n-1}2$ 以及 $a_1 \otimes a_2 = 2 \times (a_1' \otimes a_2')+1$。此时个数不会变,而和变为原本的两倍再加上个数。也就是 $g(n) = g(\frac {n-1}2)$ 以及 $f(n) = 2f(\frac {n-1}2) + g(\frac {n-1}2)$

  • 如果 $n$ 是偶数,那么我们又要分两类讨论:

    • $n = a_1 + a_2$,其中两者都是偶数,那么类似的,$a_1' + a_2' = \frac n2$$a_1 \otimes a_2 = 2 \times (a_1' \otimes a_2')$

    • 如果都是奇数,有 $a_1' + a_2' = \frac n2 - 1$ 以及 $a_1 \otimes a_2 = 2 \times (a_1' \otimes a_2')$。 

    • 因此,我们可以知道 $f(n) = 2 \times f(\frac n2) + 2 \times f(\frac n2 - 1)$,以及 $g(n) = g(\frac n2) + g(\frac n2 - 1)$

FAKE: 于是我们可以得出递推复杂度 $T(n) = T(\frac n2) + 1$,得出为 $O(\log n)$

依据SMB,复杂度似乎不是这样的,但是题解是这么给的,或许是有一些神秘的分析,或者是加了记忆化,所以复杂度是这样的。

其实完全可以用记忆化……快一点吧。

提交:https://codeforces.com/contest/1815/submission/211297560

E. Bosco and Particle

性质好题

性质:

  1. 循环多次 $=$ 循环一次

  2. $a_i$ 表示实际上从上面进入这个序列的次数,$b_i$ 表示实际上向下面出去这个序列的次数。我们把第 $i$ 个序列单独提出来,类似的定义 $a_i'$$b_i'$。可以发现,$\exists k \implies a_i = ka_i', b_i = kb_i'$,也就是有 $\frac {a_i}{b_i} = \frac {a_i'}{b_i'}$

  3. $a_i = b_{i-1}$

  4. $f_i = a_{i + 1}$$f_0 = a_1$,于是有 $f_k = \prod_{i = 1}^k \frac {b_i}{a_i} f_0$

  5. 需要保证 $\forall k$$ f_k$ 为整数。

于是就可以写出来啦!!!(不是

提交:Submission #211323975 - Codeforces

竟然比 C++ 快,不可思议

1868

A. 2D Traveling

该题共有 $t$ 组数据,对于每一组数据,给定一个共有 $n$ 个节点的图,其中有 $k$ 个关键点(两个关键点之间移动花费为0)。给出 $n$ 个点的坐标 $(x_i,y_i)$ ,求从 $a$$b$ 两点之间的最小移动花费。

除关键点以外,两点之间的移动花费为曼哈顿距离

策略要么是 $a$ 直接到 $b$,要么是 $a$ 先到最近的关键点,跳到 $b$ 最近的关键点。

直接做即可,代码:https://codeforces.com/contest/1869/submission/223695140

B1/2. Candy Party

$n$ 个人,第 $i$ 个人有 $a_i$ 颗糖,在派对上,每个人 会且仅会做下面的事情恰好一次

  • 选一个正整数 $p\ (\ 1 \leq p \leq n\ )$ 和一个非负整数 $x$ ,然后把 $2^x$ 颗糖给第 $p$ 个人。注意任意时刻一个人手上的糖不能变成负数,并且一个人不能把糖给自己。

你需要回答能否在上述操作后让每个人手中的糖果数量相同。

注意本题和 Hard Version 不同的是本题中每个人必须从他人处接受恰好一次糖果,给出恰好一次糖果。

也就是每一个人要么使用 $2^x - 2^y$,要么使用 $2^x$,要么使用 $2^{2x} - 2^x$。分开考虑来 DP 即可。

C. Travel Plan

给定一颗 $n$ 个节点的完全二叉树,每个点有权值 $a_i \in [1,m]$,定义从 $i$$j$ 的路径的权值 $s_{i,j}$ 为路径上的最大点权。

求所有树($m^n$ 种点权)的 $\sum_{i=1}^n \sum_{j=i}^n s_{i,j}$ 的和,模 $998244353$

很显然,我们可以分别求出每种长度路径对答案的贡献,然后再在树上统计各个长度路径的个数,最后把贡献加起来即为答案。

D. Flower-like Pseudotree

给你一个基环树,我们称一个基环树是像花的当且仅当删去基环树中的环后,剩余的所有树高度一致,请你构造一个像花的基环树,满足树中所有点的度数为 $d_i$

大力分讨即可。

1863

A. Channel

Link

没什么好说的,模拟即可。

代码:https://codeforces.com/problemset/submission/1863/225013381

B. Split Sort

给定一个 $1 \sim n$ 的排列 $q$,你可以多次进行以下操作:

  • 新建一个初始为空的序列 $q$
  • 选择一个整数 $x$$2 \leq x \leq n$);
  • 按照在 $p$ 中出现的顺序将所有小于 $x$ 的数添加到序列 $q$ 末尾。
  • 按照在 $p$ 中出现的顺序将所有大于等于 $x$ 的数添加到序列 $q$ 末尾。
  • 用序列 $q$ 替代排列 $p$

你需要找到使 $\forall i \in [1,n]$$p_{i} = i$ 的最小操作次数。

本题有多组测试数据,$1 \leq T \leq 10^{3}$$1 \leq n,\sum n \leq 10^{5}$

$i$ 出现的位置为 $p_i$,则答案为 $\sum_{i = 2}^n [p_i < p_{i - 1}]$

代码:Submission #225039544 - Codeforces

C. MEX Repetition

给定值域在 $[0, n]$ 的一个序列,$p_i$ 互不相同,定义一次操作为 $i = 1 \to n, p_i = \mathrm{mex}(P)$,求 $k \le 10^9$ 后的序列是什么样子的。

将初始的 $\mathrm{mex}$ 放在序列开头,则一次操作相当于 $i = 1 \to n, \mathrm{swap}(p_0, p_i)$,结果是加入了 $\mathrm{mex}$ 的序列向右循环了一次。

所以最后就是循环 $k$ 次,去掉第一个数即可。

代码:https://codeforces.com/problemset/submission/1863/225014759

D. Two-Colored Dominoes

有一个 $n \times m$ 的棋盘,上面铺着一些 $1 \times 2$ 的多米诺骨牌(横竖均有可能),骨牌之间没有重叠。

你需要找到一种染色方案满足以下条件:

  • 每个多米诺骨牌一端被染白,另一端被染黑。其他没有骨牌的格子不染色。
  • 对于棋盘的每一行,被染黑的格子数等于被染白的格子数。
  • 对于棋盘的每一列,被染黑的格子数等于被染白的格子数。

请输出任意一种染色方案,如果无解,输出 $-1$

本题有多组测试数据,$1 \leq T \leq 10^{4}$$2 \leq n,m \leq 500$$\sum (n \times m) \leq 2.5 \times 10^{5}$

发现横竖之间没有影响,所以分开考虑。

考虑只有竖着,那么横向黑白染色,这无法影响道下一行,所以忽略。

纵向类似即可。

代码:https://codeforces.com/problemset/submission/1863/225041894

E. Speedrun

你在玩一个游戏,要完成 $n$ 个任务。其中对于每个任务 $i$,它只能在某一天的第 $h_i$ 时刻完成。游戏每天有 $k$ 个小时,分别编号为 $0,1,...k-1$

给出 $m$ 对任务间的依赖关系,$(a_i,b_i)$ 表示 $a_i$ 必须比 $b_i$ 先完成。保证依赖关系不形成环。

完成任务不需要时间,也就是说可以在同一天的同一时刻先后完成多个任务。

求完成所有任务所需的最短时间。这里的时间定义为:完成最后一个任务的时刻 与 开始第一个任务的时刻 之差。

多组数据,$T\le 10^5$$\sum n,m\le 2\times 10^5$$k\le 10^9$

最优的情况是延迟了一部分拓扑序第一的点,而且这一部分一定是前缀。

所以扫一次前缀,一一延迟更新当前答案,然后更新总答案。

每一个点至多更新一次,所以这部分 $O(n)$

代码:https://codeforces.com/problemset/submission/1863/225021336

F. Divide, XOR, and Conquer

有一个长为 $n$ 的数组 $a_1, a_2, \cdots, a_n$

在每次操作中,你可以把数组分成两段,留下一段,扔掉另一段,要求前者的异或和不小于后者的。重复操作,直到只剩下一个数为止。

对于每个 $i$,问最后剩下来的可不可能是第 $i$ 个数。

$t$ 组数据。$1 \le t \le 10\ 000$$1 \le n \le 10\ 000$$1 \le a_i \le 2^{60}$$\sum n \le 10\ 000$

有一个显然的 $O(n^3)$ 做法。

考虑一个区间 $[l, r]$ 什么时候可以被转移过来,由于异或,从二进制入手。

假定从 $[l, k]$ 转移过来,其区间异或和为 $x$$[l, r]$ 区间异或和为 $y$

如果 $x$ 的第 $k$ 位为 $0$,那么显然两边这一位都是相等的。如果为 $1$,那么有一边会大一点,下面的位随意了。

所以可以有条件 $y \& \mathrm{highbit}(x) \ne 0$ 则可以转移。

于是一个一个长度递减做下去即可。

代码:https://codeforces.com/problemset/submission/1863/225050040

G. Swaps

给定长度为 $n$ 的序列 $a$,每次操作可以选定一个 $i$,并 $\operatorname{swap}(a_i,a_{a_i})$。求能通过某种操作顺序得到的不同序列数。

$n\le 10^6$

简洁的题面,深邃的思想。

首先,一个经典的套路是:

对于序列中涉及到对于 $a_i$​​ 和 $a_{a_i}$​ 进行操作的问题,一般可以考虑建立 $(i,a_i​)$ 的内向基环树或者 $(a_i​,i)$ 的外向基环树转化为图论问题。

-- from weakpyt

一次交换相当于使得一个点自环,儿子连向父亲。

于是转换为对于一个点,儿子可以断一条边,并且至多段一条边的模型。

所以如果只是一棵树的话,答案就是 $\prod (d_x + 1)$

然而有环,发现环上所有边的断掉的情况不存在。

再发现环上留一条边不断,但是每一个点都断了一条边/或者不变的情况都是一样的,这部分显然是 $\sum (d_x - 1 + 1)$ 的。

所以减去重复的,只保留一个,答案为:

$$\prod_{cycles}(\prod_{x \in cycle} (d_x + 1) - 1 - (-1 + \sum d_x)) \prod_{x \not \in cycle} (d_x + 1) $$

化简一下:

$$\prod_{cycles}(\prod_{x \in cycle} (d_x + 1)- \sum d_x) \prod_{x \not \in cycle} (d_x + 1) $$

这样就好求了。

代码:https://codeforces.com/problemset/submission/1863/225037149

H. Goldberg Machine

给定一棵树,每个节点要么没有儿子,要么有两个儿子,每个叶子节点有一个权值。

多次修改某个叶子节点的权值,维护递推式子:$f_x = 2 \max(f_y, f_z) - (f_y \ne f_z)$

$t_x = f_x - 1$,则递推式子转换为 $t_x = 2 \max(t_y, t_z) + [t_y = y_z]$

$x$ 的深度为 $dep_x$,则可以令叶子 $g_x = 2^{dep_x} f_x$,则递推式子为 $g_x = \max(g_y, g_z) + 2^{dep_x}[g_y = g_z]$

有一个结论是 $g_x$ 的二进制中 $1$ 的个数是 $\log A + \log n$ 级别的。

考虑暴力合并。

假定 $x, y$$g$ 相等,则可以在 $z = \mathrm{LCA}(x, y)$ 处贡献 $2^{dep_z}$

于是可以利用 vector 字典序暴力找相同的,然后合并即可。

最后会得到很多个答案,取最大的即可。

为什么取最大的正确性没问题?考虑如果 $x$ 在和 $y$ 之前与某一个 $u$ 合并了,那么合并的位置一定在 $z$ 下面,也就是贡献 $2^{dep}$ 一定大于 $2^{dep_x}$,使得最终的答案大于错误的答案,所以如此是没有问题的。

由于当日晚上呕吐,身体不适,所以没有写本题。然而代码实际上是好写的,不过多赘述。

1753

成功因为虚拟机炸了,重新写一遍此文。

都是没有保存的错

A. Make Nonzero Sum

由于 Note that it is not required to minimize the number of segments in the partition.。考虑每一段最小化……

可以发现,每一段都可以划分为长度为 1 或 2 的段。于是考虑影响。

只有长度为 2 的段会改变正负,不妨令 $C_+, C_-$ 分别表示 1 和 -1 的个数,并假定 1 更多。

不难发现,只需要 $\frac {|C_+ - C_-|}2$ 个长度为 2 的即可。

如果不是整数,那么直接判不可以即可。

由于有影响,考虑 DP。

$f_i$ 表示考虑前 $i$ 个数,最多能够放多少个长度为 2 的。

于是有

$$f_i = \max \begin{cases} f_{i - 1} \\ f_{i - 2} + 1 &, a_i = 1 \end{cases} $$

考虑在 DP 变化的地方放置长度为 2 的即可。

B. Factorial Divisibility

当时脑子抽了,用了两种合并的方法。

详见:https://codeforces.com/contest/1753/submission/211561532

但是实际上只需要通过 $x! = x \times (x -1)!$ 合成即可(2048……

C. Wish I Knew How to Sort

假定有 $C_0$$0$,并且在前 $C_0$ 个数中有 $k$ 个 1。

那么考虑此时一个有效的操作,即是在前 $C_0$ 中选择到了一个 $1$,在后面中选择了一个 $0$

有效的概率为

$$P_k = \cfrac {k^2}{n \choose 2} $$

于是考虑状态转移,设 $f_k$ 表示从前 $C_0$ 个数中有 $k$$1$ 的状态转移到 $0$$1$ 的期望步数。

根据 markov 中的期望线性方程求解的方法,有

$$f_k = 1 + (1 - P_k)f_k + P_k f_{k - 1} $$

稍微魔改一下,就变成了:

$$f_k = \frac {1}{P_k} + f_{k - 1} $$

于是小小递推即可。

然而我当时是反着推的,无所谓,一样的:Submission #211560140 - Codeforces

D. The Beach

转换问题:等价于将两个 . 移动到一起的最小代价。

显然可以发现,一个障碍最多移动一次。

借用大佬的图:

于是我们可以考虑如此建图。跑一个最短路即可。

提交:Submission #211566195 - Codeforces

E. N Machines

非常恶心,虽然不是顶级难度。

最优的策略一定是把乘法向后移,把加法向前移。

思考 It's guaranteed that the current value of the resulting product does not exceed 2x10^9. 的意义。

发现,除去 $\times 1$,最多只会有 $\log C$ 个乘法。

于是考虑枚举其子集,为 $2^{\log C}$。所以需要优化。

有一个简单而优雅的剪枝:如果两个数相等,那么一定是选择最前面的。

由于 $12! = 6227020800 \gt 2 \times 10^9$,所以其实最多只会有 $O(2^{12})$ 种状态。

那么在钦定了向后移动的乘法后,我们需要找到前 $rest$ 个移动到前面贡献最大的加法。

考虑二分移动到前面的贡献 $\Delta$,在每一段再二分数量。

考虑如何计算每一个加法的 $\Delta$ ?考虑加法移动前,其贡献为 $x \times suf_x$,移动后的贡献为 $x \times pre_x \times suf_x$

其中 $suf_x$$pre_x$ 是指乘法移动后,$x$ 前面的乘法前缀积和后面的乘法后缀积。

于是 $\Delta x = x \times (pre_x - 1) \times suf_x$

NOTICE

  • 二分 $\Delta$ 时找到最大的 $cnt > rest$ 的那个 $\Delta$,由于多算了 $cnt- rest$ 个,并且这些数的贡献一定是 $\Delta$,所以再减去 $(cnt - rest) \times \Delta$ 即可。

  • $\Delta$ 可能很大很大,所以上界大一点(我用的倍增,所以直接是从 $2^{60}$ 开始向下……虽然没必要)

提交:Submission #211609810 - Codeforces

F. Minecraft Series

首先固定一个正方形,考虑贡献:将数分为正数与负数,分别计算 $mex_p$$mex_n$

正的为 positive,负的为 negative

于是贡献为 $mex_p + mex_n - 1$

由于 $mex$ 的单调性,发现包括合法正方形的正方形一定合法,所以考虑双指针维护所在最小合法正方形的。

注意,是在每一条对角线上来一发双指针,这样才能保证复杂度。

然后,然后就搞定了。

可以优化的是,$mex$ 可以利用分块优化复杂度。

于是你可以得到一个复杂度为:

$$O(nm \cdot \min\{n, m\} + n m \sqrt k) $$

的优雅 brute force……

提交:https://codeforces.com/contest/1753/submission/211685792

然而……不断的 TLE 让我怀疑人生,最后发现……

参考:讨论

1718

A. Burenka and Traditions (hard version)

$T$ 组数据,对于每一组数据,你有一个长度为 $n$ 的数组 $a$,每一次操作可以选择一段区间 $[l,r]$,花费 $\left \lceil \dfrac{r-l+1}{2} \right \rceil$ 秒使区间内的数都异或 $x$,问最少需要几秒才能把数组中所有的元素都变成零。

首先不难发现有一个非常简单的上界 $n$,也就是每两个两个的变成 $0$ 即可,或者换成一个一个向后推的过程。

然而如果存在一个区间本身异或和为 $0$,那么发现左端点是没有必要推的,这使得操作次数 $-1$。发现这优化十分显然,于是利用 set 维护最小的段即可。

代码:Easy: https://codeforces.com/problemset/submission/1718/229358204, Hard: https://codeforces.com/problemset/submission/1718/229358185

B. Fibonacci Strings

给你一个数列 $\{c_k\}$,可以执行若干轮操作(轮数由你决定)。对于第 $i$ 轮操作:

  • 选定一个 $[1,k]$ 范围内的整数 $d_i$。当 $i \ge 2$ 时,必须保证 $d_i \neq d_{i-1}$

  • $c_{d_i}$ 减去 $f_i$,其中 $f_i$ 是斐波那契数列($1,1,2,3,5,8,13,\ldots$)的第 $i$ 项。

问:你能否让 $c_1$$c_k$ 全为 $0$

呃呃,原题不是这样的,但是既然这么翻译了,那么贪心的模拟一下即可。

代码:https://codeforces.com/problemset/submission/1718/229357931

C. Tonya and Burenka-179

给定一个长度为 $n$ 的序列,要求求出一个权值最大的对 $(p, k)$,其中 $0 \le p, k \lt n$

定义一个对 $(p, k)$ 的权值为 $\sum_{i = 1}^{n} A_{p + k i \bmod n}$

先考虑最朴素的做法 $O(n^2)$,发现,考虑优化其过程,发现可以类似于分治,例如 $(p, k)$ 可以由 $(p, 2k)$$(p + k, 2k)$ 合并而来。

但是发现 $(p, k)$ 一定不必 $max((p, 2k), (p + k, 2k))$ 更优,所以此时 $k$ 是不必要的。

于是发现 $k$ 是最优的当且仅当 $\frac nk$ 为质数,这只有 $6$ 个,每一个用一个 set 维护即可,这是 $O(6 n \log n)$ 的。

代码:https://codeforces.com/problemset/submission/1718/229362201

D. Permutation for Burenka

给定一个排列 $p$ 和有 $k$ 个空位的序列 $a$,已经确定了可以 $k - 1$ 个数,每次询问给定一个数,要求是否可以将这 $k$ 个数填入 $a$ 中使得 $\forall i < j, \arg \max p_{[i, j]} = \arg \max a_{[i, j]}$

发现这个限制可以转化为两者的笛卡尔树同构,发现排列的笛卡尔树是确定的,先构出来,然后考虑 $a$

发现每一个空位都可以填的数是一个区间,而剩下一个数合法也一定是一个区间,于是考虑如何求上下界。

首先将每一个位置的上下界求出来,考虑一个十分经典的贪心来求它,按照区间右端点从大到小排序,尽量选择大的来满足它,那么到第一个不可以填的区间的时候,就意味着剩下的一个数必须大于这个区间的左端点了,于是可以求出下界了。

同理,按照左端点从小到大排序,可以求出其上界。

不过需要注意,如果遇到了两个没有办法满足的区间的时候,无论填什么都不可以了,此时所有询问回答皆为 NO

代码:https://codeforces.com/problemset/submission/1718/229374552

E. Impressionism

Burenka 有两张图片 $a$$b$ ,它们的大小可以表示为 $n \times m$ 的像素组合。每幅画的每个像素都有一个颜色——表示为一个从 $0$$2 \times 10^5$ 的数字,并且在两幅画的每一行或每一列中都没有重复的颜色,除了颜色 $0$

Burenka 想把图片 $a$ 变成图片 $b$。为了实现她的目标,Burenka 可以执行 $2$ 操作之一:交换 $a$ 的任意两行或其任意两列。现在需要你来告诉 Burenka 该如何操作,或者说明其不可能完成。

模拟 $\mathrm{Pity Problem}$,利用二分图一一匹配即可。

F. Burenka, an Array and Queries

每次询问一个区间,求 $\prod a_i$$1 \sim C$ 中互质的数的个数。

有根号分治,或者乱搞。

但是官方题解所说:The only one hint to this problem is don't try to solve, it's not worth it.

1710

B. Rain

给定一个 $n$ ,这 $n$ 天会降雨,每一个降雨天有一个 $x_i$ 和一个 $p_i$ ,表示以 $x_i$ 为中心,降雨量向左右两边递减,即对于所有的数轴上的点 $x$ ,其降雨量都会增加 $max(0,p_i−∣x_i−x∣)$

现在你可以消除一天的降雨,问消除第 $i$ 天的降雨是否可以使得没有任何地方的降雨大于 $m$

考虑整个图长什么样子,发现峰值(很多个)一定是某个 $x_i$ 上。

于是求出每一个 $x_i$ 对应的降雨 $h_i$,这可以通过二分和差分很容易的求出(考虑每一次增加的是一个一次函数,这可以通过 $k, b$ 简单的维护)

于是考虑对于删除一个后 $m$ 的限制。

如果 $h_i \le m$,自然不需要关注,删除一个 $k$ 之后 $h_i \to h_i - \max(0, p_k - |x_k - x_i|)$

我们需要 $h_i - \max(0, p_k - |x_k - x_i|) \le m$ 也就是 $h - (p_k - |x_k - x_i|) \le m$,考虑原本 $h_i > m$,如果后者不满足,那么必定不满足。

于是就是 $h_i - p_k \le m + |x_k - x_i|$,考虑绝对值又是 $\max(x_k - x_i, x_i - x_k)$,于是两边同时都需要满足,也就是:

$$\begin{cases} h_i + x_i \le m + x_k + p_k \\ h_i - x_i \le m - x_k + p_k \end{cases} $$

分别记录 $h_i + x_i$$h_i - x_i$ 的最大值即可判断 $k$ 删除后是否满足条件。

代码(我在乱搞……所以代码有些抽象):https://codeforces.com/problemset/submission/1710/229413132

C. XOR Triangle

给你一个数 $n$,问:有多少对数 $0\leq a,b,c \leq n$ 满足 $a \oplus b,b \oplus c,a \oplus c$ 。三个数字构成了一个非退化三角形,也就是两条短边之和大于第三边的长度。$\oplus$ 表示二进制下的异或操作。

首先,很难发现对于所有数位,如果 $a \oplus b + b \oplus c > a \oplus c$,那么就满足 $x \oplus y + y \oplus z > x \oplus z$。其余两个限制同理。

于是考虑数位 DP,压位判断是否满足三个条件即可。

代码:https://codeforces.com/contest/1710/submission/229415904

D. Recover the Tree

你需要根据题目给出的信息构造出一棵树,满足如下条件:

  1. 树的节点个数为 $n$
  2. 对于每个区间 $[l,r]$ 给出是或不是连通块。

数据保证有解,$n\leqslant 2000$

首先满足小的区间是最优的,考虑如何满足大的区间。

考虑合并 $i, j$,那么此时的联通块大概是这样的:

按照上面的连边即可,注意是连到 $i$$j$,而不是 $i, j$ 所在连通块的某一个点,中间的块随意,利用并查集维护即可。

代码:https://codeforces.com/contest/1710/submission/229423482

E. Two Arrays

现有两个整数数组 $a_1, a_2, \dots, a_n$$b_1, b_2, \dots, b_m$

Alice 和 Bob 将要玩一个游戏,Alice 先手,然后他们轮流进行操作。

他们在一个 $n\times m$ 的网格上进行游戏(网格有 $n$$m$ 列)。刚开始,有一个棋子放在网格的一排一列上。

在 Alice 或 Bob 轮次中,玩家可以选择以下两个动作中的一个进行操作:

  1. 将棋子移动到一个不同的格子上,该格子必须和棋子的原位置在同排或者同列上。玩家不能将棋子移动到已经被访问过 $1000$ 次的格子上(也就是说,在游戏过程中,棋子最多可以在某个格子停留 $1000$ 次)。请注意,我们规定起始单元格在开始时被视作访问过一次。
  2. $a_r + b_c$ 的得分立刻结束游戏,$(r, c)$ 表示棋子当前所在的单元格(也就是说,棋子在第 $r$ 排第 $c$ 列上)。

Bob 想要最大化自己的得分,Alice 则想要最小化自己的得分。如果他们都以最佳方式玩这个游戏,则最终的得分是多少?

其实发现 $1000$ 次和 $1$ 次没有区别,直接忽略。

首先,我们知道博弈双方足够聪明,可以直接知道比赛结果 $res$,那么意味着 Bob 只能走大于 $res$ 的地方,而 Alice 只能走小于等于 $res$ 的地方。

于是可以得到一张二分图,这让我们想到经典的结论:Alice 赢的充要条件是二分图的最大匹配必须包含起点 $S$

但是边数是 $O(nm)$ 的,非常难受,考虑转化思路,找二分图最大独立集,这要求每行每列都只有一边出现,我们给每个行列涂颜色。那么一个方格可以取当且仅当方格的颜色和行列所染颜色都一样。

于是对于整个图($a, b$)排个序,于是发现黑白大概就是如图:

枚举这个点即可,但是直接枚举是不可以接受的,这是 $O(nm)$,但是考虑到这必定是一个凸函数,所以可以单调性优化,可以做到 $O(n + m)$ 找。

于是加上二分的复杂度为 $O(n \log n)$

1707

A. Doremy's IQ

哆来咪·苏伊特参加了 $n$ 场比赛。 比赛 $i$ 只能在第 $i$ 天进行。比赛 $i$ 的难度为 $a_i$。最初,哆来咪的 IQ 为 $q$ 。 在第 $i$ 天,哆来咪将选择是否参加比赛 i。只有当她当前的 IQ 大于 $0$ 时,她才能参加比赛。

如果哆来咪选择在第 $i$ 天参加比赛 $i$,则会发生以下情况:

  • 如果 $a_i>q$,哆来咪会觉得自己不够聪明,所以 $q$ 将会减 $1$
  • 否则,什么都不会改变。

如果她选择不参加比赛,一切都不会改变。哆来咪想参加尽可能多的比赛。请给哆来咪一个解决方案。

  • 简单二分,前面部分只参加 $\le q$ 的比赛,后面部分经量参加,看是否可是使得 $q = 0$
  • 或者从后向前考虑,可以 $O(n)$

B. Difference Array

你有一个初始长度为 $n$ 的有序数组 $a$(从小到大)。设 $a$ 当前长度为 $l$,你要对 $a$ 作差分,即令 $b_i = a_{i+1} - a_i(1\le i < l)$,然后将 $b$ 数组从小到大排序,接着让 $a_i = b_i(1 \le i < l)$,并继续执行上述操作。

显然,每一次操作后 $a$ 数组的长度都会减少 $1$;执行 $n - 1$ 次操作之后,$a$ 中只会剩下一个元素,请你输出这个剩下的元素。

首先有个不难发现的是相同的数,只需要有一个贡献即可。

然后发现会有 $O(\sqrt S)$ 个本质不同的数,也就是说,至多需要删 $O(\sqrt S)$ 次,每次删一个的代价是 $O(n \log n)$,于是你会发现这跑的飞快。

因为这复杂度是 $O(S \log n)$ 而不是根号的。考虑利用构造证明,如果需要每一次都只减少 $1$ 个值,而不产生相同的值,那么最优秀的显然是 $f(x) = 2^x$,因为存在 $\Delta f(x) = f(x - 1)$,于是这种东西至多是 $O(\log S)$ 个的,所以复杂度不会高于 $O(n \log S)$,然而存在神秘证明,操作次数是 $O(\frac S n)$ 的,所以复杂度是 $O(S \log n)$ 的,这看题解即可。

C. DFS Trees

有一图有$n$个点$m$条边。第$i$条边的权值是$i$
现在有一个错误的最小生成树算法(就是有bug)

vis := an array of length n
s := a set of edges

function dfs(u):
    vis[u] := true
    iterate through each edge (u, v) in the order from smallest to largest edge weight
        if vis[v] = false
            add edge (u, v) into the set (s)
            dfs(v)

function findMST(u):
    reset all elements of (vis) to false
    reset the edge set (s) to empty
    dfs(u)
    return the edge set (s)

每次调用$findMST(i)$时,会返回这个图的最小生成树,你要判定那些是正确的最小生成树。

首先,最小生成树是唯一的,于是整张图会变成一棵树加一些边。

在 DFS Tree 里面,只有返祖边,我们考虑每一天非树边在什么时候满足为反祖边。

如果 $(x, y)$ 不为祖先关系,那么是各自子树内即可。树上差分即可。

D. Partial Virtual Trees

给定 $n$ 个点的树以及质数 $p$,对每个 $k=1,2,\cdots,n-1$ 计算满足下述条件的点集序列 $\{S_i\}_{i=0}^k$ 数量 $\bmod\ p$

  • $\{1\}=S_k\subsetneq S_{k-1}\subsetneq\cdots\subsetneq S_0=\{1,2,\cdots,n\}$
  • 对每个 $S_i$ 以及 $u,v\in S_i$,都有 $\text{LCA}(u,v)\in S_i$

其中 $\text{LCA}(u,v)$ 表示以 $1$ 为根时 $u$$v$ 的最近公共祖先。

真子集很恼火,于是利用容斥搞掉。

逆着删元素,于是 $f_{x, i}$ 表示 $x$$i$ 时被删除,初始全部点亮。

于是儿子必须全部消失或只剩下一个,$f_{x, i}$ 才能消失,转移参考 https://www.luogu.com.cn/blog/_post/454338 即可。

1685

A. Circular Local MiniMax

检查是否存在对于 $a_1, a_2, \cdots, a_n$ 的重新排列,使得 $i$$1$$n$ 中至少有一个以下条件成立。

  • $a_{i-1} < a_i > a_{i+1}$
  • $a_{i-1} > a_i < a_{i+1}$

首先奇数长度一定不可以,于是只用考虑偶数。

此时只需要分成两个部分,交错放置,然后判断即可。

B. Linguistics

Alina 发现了一种只由 $\text{A, B, AB, BA}$ 四种单词组成的语言,这种语言不含有空格,书写句子时只需要将单词直接连接起来即可。

她很好奇是否可以用 $a$$\text{A}$$b$$\text{B}$$c$$\text{AB}$$d$$\text{BA}$ 拼接形成句子 $s$

换句话说,是否可以用 $a+b+c+d$ 个单词以某种顺序拼接出句子 $s$,这 $a+b+c+d$ 个单词都得被用到,他们的顺序可以由你决定。

很抽象的贪心。考虑先把形如 $XYXYX...$ 的段都提出来,按照长度排个序。

首先如果长度为偶数,那么优先满足 $XY$ 的。在满足了所有的偶数之后,我们继续考虑奇数的,此时发现,两者可以满足的数量相加是恒定的,所以可以任意满足。

最后剩下了一点偶数的,那么贪心的放即可。

C. Bring Balance

Alina 有一个长度为 $2n$ 的括号序列 $s$,她想把这个括号序列变成一个合法的括号序列。每一次操作可以 reverse $s$ 的任意子串,求最小操作次数。

经典的画折线,发现至多需要两次,也就是翻转至高点左右两侧。

考虑什么时候只用翻转一次,找到至少翻转的那个区间 $[l, r]$,找到左右两部分最高的点 $L, R$,如果 $\forall i \in [l, r], h_i \le h_L + h_R$,那么可以只用一次,正确性显然。

D. Permutation Weight

给定一个 $1\sim n$ 的排列 $p$$n \le 200$
对于一个 $1\sim n$ 的排列 $q$,定义其权值为:

$$ 找出 **任意一个** 权值最小化的 $1\sim n$ 的排列 $q$。 Hard Version 是找到字典序最小的。 先考虑简单版的怎么做。 设 $f = p^{-1}$,先不考虑 $q$ 是否是一个排列,那么存在 $q_i = p_{q_{i + 1}}$,两边同时套上 $f$ 得到 $f_{q_i} = q_{i + 1}$。 于是,可以钦定 $q_1 = 1$,于是可以推出 $q$ 的样子。 然而发现 $q$ 存在多个环,推不出来,所以需要交换某些东西,使得只存在一个环。为了达到下界,我们只能交换相邻的 $f_i, f_{i + 1}$,保证损失最小。 利用并查集维护可以做到 $O(n)$。 然而对于字典序最小,看到数据范围容易想到,每位钦定的选择某一个值,判断这个前缀是否可行,可以做到 $O(n^3)$。 我们重新看简单版的过程,我们有很多 $q_i \to f_{q_{i + 1}}$,考虑得到了一些 $(i, f_i)$,$q_i$ 则规定了其顺序,而答案则是 $\sum (q_i, f_{q_i})[0] - (q_{i - 1}, f_{q_{i - 1}})[1]$。 于是我们根据 $f_i$ 可以划分出一些环,发现在这些环内跳是没有代价的,这十分优秀。 现在转而考虑 $f_{q_{i - 1}} \to q_i$ 的这条边,发现需要经量使得两者接近,并且所有连完之后满足: - 所有边只形成一个环。 - 使得所有 $f_i$ 划分出来的环联通。 而为了使得答案最优秀,我们需要: - 每个边不会重复合并划分出来的环。 - $f_{q_{i - 1}} \to q_i$ 形成的图中,每个环编号都是连续的,且可以被拆分为递增和递减的两个段。 此时我们需要判断一个前缀是否合法/优秀,于是就可以采用如下方法: - 不存在两条单增链相交,不存在两条单减链相交(自环同时算作单增链及单减链)。 - 不存在未连边的点同时被单增链及单减链覆盖。 - 不存在被覆盖的某边 $(i, i + 1)$ 在同一个划分的环内。 - 剩下的所有作为边界的 $(i, i + 1)$ 可以使得所有颜色联通。 这可以利用差分 + 并查集每次 $O(n)$ 的维护。 于是总复杂度为 $O(n^3)$。 ## GYM 103495 > 这里挑选部分值得一谈的题。 ### B. Among Us 给出一张带边权的无向图,边权可被视为长度。最开始有 $2$ 个内鬼和至多 $8$ 个船员,内鬼起始位置给出,内鬼只能沿着边走。内鬼知道一系列形如“船员 $p$ 会在第 $t$ 秒出现在顶点 $x$ 的信息。若内鬼与船员在同一时间和同一地点出现,则 内鬼可以把船员给砍了。内鬼只能在前面给出的时间/地点砍人。你需要为 $2$ 个内鬼分别规划路径使得它们能够尽快将所有船员都给砍了。若方案存在则输出最短时间,否则输出 $−1$。 核心:状压,最短路,DP。 首先利用状压将两个内鬼分开,于是问题简化为对于一个人。 不难想出一个状态,设 $f_{x, t, S}$ 表示是否能够在杀了 $S$ 中的人后在 $t$ 时到 $x$。 如果固定 $x, S$,发现对于一个后缀 $t$ 都生效,那么可以将 $t$ 作为值,于是状态为 $f_{x, S}$ 表示杀了 $S$ 中的人并到达 $x$ 的最短时间。 接下来转移有两种: - $\to f_{y, S}$,也就是移动到 $y$。 - $\to f_{x, S | 2^k}$,也就是在 $x$ 蹲守某个人。 类似 djk 的跑即可。 ### D. Pattern Lock 给定 $n$ 行 $m$ 列的点阵图,用一条折线经过所有的点各一次,要求每条线段不经过除端点外的其他点,且形成的角都是锐角。 对于 $n, m$ 存在偶数的情况是简单的。 ![](https://gitlab.com/jeefies/image-repo/uploads/9f0c188abc2e49ce856b4b112072980b/202401102157041.png) 这样两行两行的构造即可。 对于都有奇数的,那么先构造一个 $3 \times 3$ 的,接下来会分出两个偶数矩阵即可。 大概就是 ![](https://gitlab.com/jeefies/image-repo/uploads/0eb7fdb0d6e057eba082121c9494c525/202401102202511.png) ### E. Stone Ocean 定义一个长为 $n$ 串的权重 $w(s)$ 为有多少个排列 $p$ 使得 $s[p_1]s[p_2] \ldots s[p_n]$ 是一个回文,现在有 $n \le 30$ 个串,从每个串随机选一个位置的字符,连接成一个长为 $n$ 的新串,求这个新串的 $w$ 的期望。 先考虑如何计算 $w(s)$。先判断是否能够成为回文,如果可以,枚举哪两个会配对,最后乘上 $(\frac n2)!$ 来修正这些配对的位置即可。 于是类似的,枚举哪两个字符串会配对,记 $mat(i, j)$ 表示 $s_i, s_j$ 选择相同字符的方案数。那么总贡献即是 $(\frac n2)! 2^{\frac n2} \prod mat_{i, j}$ 其中 $2^{\frac n2}$ 是选择一个子集作为左部,$\prod$ 内的东西是所有配对的对。注意在奇数的情况下需要新建一个虚点 $x$ 使得 $mat_{i, x} = |s_i|$,与虚点匹配的放在最中间,还要注意这个虚点不会影响前面的系数。 考虑 $n$ 很小,进行状压,$f[S] \times mat_{i, j} \to f[S | 2^i | 2^j]$,这是容易理解的。最后除以方案数即可得出期望。为了不重复贡献,每次 $i$ 只需要设为最小的即可。 乍一看是 $2^{30}$ 的状态数,然而实际上远远没有这么恐怖,由于我们每次选择了最小的 $i$,对于状态,必须满足前缀 $1$ 的个数 $\ge 1$ 的个数的一半,于是状态数大概为: $$

\sum_{i = 0}^{\frac n2} \binom{n - i}{i}

$$ 在 $n = 30$ 时 $= 1346269$(实际也是如此),利用类似队列的思路转移,那么只需要 $\times 30$,计算级别在 $4 \times 10^7$,能过。 题解状态数分析就是一坨,不好评价。 ### F. Jumping Monkey II 对每个点 $x$,以 $x$ 为起点出发时,求所有简单路径的 `LIS`,注意 $x$ 必选。 首先容易得出一个 $O(n^3 \log n)$ 的解法,也就是 $O(n^2)$ 的枚举路径,然后 $O(n \log n)$ 的求 `LIS`。 其次,枚举每一个根 $rt$,设 $f_{x, i}$ 表示以 $i$ 开头的 `LIS` 的最长长度,这容易利用线段树合并完成 $O(n^2 \log n)$。 发现这是 $O(n^2)$ 树上状态问题,考虑分治。这里的话边分治更简单,并且常数很小。 只是注意这里边分治需要在三度化的时候将点权下放到边权上: ![](https://gitlab.com/jeefies/image-repo/uploads/b7b0c0fd8e41b8f9128da0500c4c5812/202401111937735.png) 最终复杂度 $O(n \log^2 n)$。 ### G. Five Phases 给定一个 $5$ 元环,需要进行 $k \le 10^5$ 次操作,每次操作可以进入如下操作之一,求到达目标局面的方案数。 - 单点 $\pm 1$ 或者全局 $\pm 1$。 - 相邻的 $3$ 个 $\pm 1$。 - 相邻的 $2$ 个 $\pm 1$,对面的那个 $\mp 1$。 联想到生成函数,是 $5$ 元的: $$

[x^a y^b z^c w^d v^e] \left(
\begin{aligned}
& x + y + z + w + v + \frac 1x + \frac 1y + \frac 1z + \frac 1 w + \frac 1 v \
& xyzwv + \frac 1 {xyzwb} \
& xyz + yzw + zwv + wvx + vxy + \frac 1 {xyz} + \frac 1 {yzw} + \frac 1 {zwv} + \frac 1 {wvx} + \frac 1 {vxy} \
& \frac {xy}{w} + \frac {yz}{v} + \frac {zw}{x} + \frac {wv}{y} + \frac {vx}{z}+ \frac {w}{xy} + \frac {v}{yz} + \frac {x}{zw} + \frac {y}{wv} + \frac {z}{vx}
\end{aligned}
\right)^k

$$ 经过通分化简,可以得到: $$

[x^a y^b z^c w^d v^e] \left(
\frac {(1 + xy)(1 + yz)(1 + zw)(1 + wv)(1 + vx)}{xyzwv}
\right)^k

$$ 将 $\frac 1 {xyzwv}$ 提出去,得到: $$

[x^{a + k} y^{b + k} z^{c + k} w^{d + k} v^{e + k}] \left(
{(1 + xy)(1 + yz)(1 + zw)(1 + wv)(1 + vx)}
\right)^k

$$ 先考虑一个简化的问题:$[x^a y^b z^c]((1 + xy)(1 + yz)(1 + zx))^k$。 考虑有哪些组合 $(xy)^l (yz)^m (zx)^n$ 可以贡献到目标,列出等式: $$

\begin{cases}
a = l + n \
b = l + m \
c = m + n
\end{cases}

$$ 发现 $l, m,n$ 都是唯一的,类似的推广,也就变成了 $5$ 个组合数相乘即可。 ### H. Reverse the String 给定字符串 $S$,至多可以翻转一个区间,求最小字典序。 首先发现翻转的开头是一定的,也就是第一个存在 $S_j \lt S_i$ 的那个 $i$。 之后也就只有 $O(n)$ 种可能,利用 `hash` $+$ 二分比较字典序即可。 ### L. Tree Game 给一棵树,每个点有权值,权值是一个排列。从叶子开始,每次重新排列 $x$ 和其所有儿子,然后向上递归。目标权值等于结点编号,给定其中一些权值,问有多少可能的权值排列可以排序成功。 首先考虑全部确定的情况,发现只需要不断交换模拟即可。 而加入 $0$ 之后呢,发现判断还是只需要模拟即可,只是 $0$ 是万金油,可以等于一切。 于是呢,考虑当前节点 $x$,现在可以重排一些东西,和一些 $0$,发现其实这些 $0$ 任意排列都可以,也就是可以贡献一个 $cnt!$。而又无法影响到子树内部,所以可以得到递推式: $$

f_x = cnt! \prod f_y

$$ 随便做即可。 ## GYM 103743 ### B.Prime Ring Plus 将 $1 ∼ n$ 分成若干个环,每个环上相邻两数之和是质数,$n \le 10^4$。 $O(n^2)$ 的枚举可以放在一起的,发现奇偶形成二分图,那么跑一个网络流即可,注意一个需要连两个。 复杂度 $O(n \sqrt {n^2}) = O(n^2)$。 ### D. Finding Pairs 给定一个序列和一个数 $k$,每次询问一个区间,问在区间中找若干对不含重复元素的距离为 $k$ 的数的最大权值和。 将 $\bmod k$ 相同的弄出来,可以作为一个单独的问题。 如果是暴力,自然想到设 $f_{i, 0/1}$ 表示考虑了前 $i$ 个数,最后一个数选没选的最大价值。 于是考虑可以莫队,但是回滚,设 $f_{i, 0/1, 0/1}$ 表示 $\bmod k$ 为 $i$ 的序列的 DP 数组,那么稍微特判一个只有一个/两个数的情况转移即可。 复杂度 $O(n \sqrt n)$。 ### E.Playing Cards 给定序列 $A, B$,以及一个 $k \le 10^9$,构造一个排列 $P$,使得下式最小: $$

\sum_{i = 1}^n \left\lceil \frac {\max(0, B_i - A_{P_i})}{k} \right\rceil

$$ 有一个不是那么优秀的做法,每次取出最小的 $A_i$,如果存在比 $A_i$ 小的 $B_i$,贪心匹配 即可,否则将 $A_i \leftarrow A_i + k$,并 $ans \leftarrow ans + 1$,将 $A_i$ 重新放入堆中,这样是 $O(n^2 \log n)$ 的。 注意这似乎不太好优化,我们将对于 $A_i$ 的 $+ k$ 变为对于 $B_i$ 的 $-k$,那么做法变为从大到小枚举 $A_i$,如果存在 $B_i \gt A_i$,那么不断 $B_i \leftarrow B_i - k, ans \leftarrow ans + 1$,直到所有 $B_i \le A_i$,此时 $A_i$ 与最大的 $B_i$ 配对即可。 利用线段树上二分即可优化为 $O(n \log n)$。 ### F. Pockets $n$ 种物品价值 $v_i$,体积 $w_i$,无限个,总容量 $k$。 如果购买 $i$ 个物品,则总容量变为 $i + k$。 至多购买 $m$ 个物品,求所有合法购买方案的价值之和,定义一个方案的价值为 $\prod v_i$。 对于多项式还是不会……考虑单次购买的生成函数:$f(x) = \sum v_i x^{w_i}$。 于是答案为:$\sum_{i = 0}^m \sum_{j = 0}^{i + k} [x^j] f^i (x)$。 注意到后面是生成函数前缀和可以转化为:$\sum_{i = 0}^m [x^{i + k}] f^i(x) \frac 1 {1 - x}$。 然而这个 $[x^{i + k}]$ 很难处理,考虑将系数平移一下: $$

[x^{m + k}] \sum_{i = 0}^m f^i(x) \frac {x^{m - i}} {1 - x}

$$ 然后可以将 $f^i(x)$ 转化为 $f^{m - i}(x)$ 的形式: $$

[x^{m + k}] \frac {f^m(x)}{1 - x} \sum_{i = 0}^m \frac {x^{m - i}}{f^{m - i}(x)}

$$ 后者可以利用 $\frac {1 - x^{k + 1}}{1 - x} = \sum_{i = 0}^k x^i$ 的形式化简: $$

[x^{m + k}] \frac {f^m(x)}{1 - x} \frac {1 - \cfrac {x^{m + 1}}{f^{m + 1}(x)}}{1 - \cfrac x {f(x)}}

$$ 再稍微化简一下: $$

[x^{m + k}] \frac {f^{m + 1}(x) - x^{m + 1}}{(1 - x)(f(x) - x)}

$$ 多项式全家桶即可。 ### H. Super Gray Pony 求长为 $n$ 的 $0/1$ 串 $S$ 求 $k$ 次格雷码后的结果,求格雷码是指将 $S$ 看做二进制数,求其在 $n$ 阶格雷码序列中的下标。 格雷码有个小小的性质:$Rank(x) = x \oplus (x >> 1)$。 于是求 $k$ 次对于前面的 $S_{x + i}$ 来说其贡献次数为 $\binom ki$。 利用 `Lucas` 来分析,只有 $i \& k = i$ 的那些 $S_{x + i}$ 会对于 $S_{x}$ 做出贡献。~~于是对于每一个地方来一次子集卷积?~~ 考虑 DP 的思路,设 $f_{x, i}$ 表示对于 $x$ 只考虑 $k$ 的前 $i$ 位构成的子集的贡献。 初始 $f_{x, 0} = S_x$,考虑第 $i$ 位,如果为 $0$,那么不会存在新的子集,那么 $f_{x, i} = f_{x, i - 1}$,如果为 $1$,那么可以存在新的子集,其从 $f_{x + 2^i, i - 1}$ 转移而来。 也就是 $f_{x, i} = f_{x, i - 1} \oplus f_{x + 2^{i - 1}, i - 1}$。 交换一下枚举顺序,先枚举 $i$,那么可以利用 `bitset` $O(\frac {n \log n}{w})$ 的完成。 ### J. Balanced Tree 求 $n$ 个点组成的每个节点都满足左右子树大小相差至多 $1$ 的二叉树个数。 容易想到一个记忆化搜索的方式: $$

f_n = \begin{cases}
2 f_{\frac n2} f_{\frac n2 - 1} & \text{n is even} \
(f_{\frac n2})^2 & \text{n is odd}
\end{cases}

$$ 不难证明状态数是 $2 \log n$ 的,答案一定形如 $2^c$,可以变为指数加法。 直接记忆化复杂度是 $O(T \log n \log \log n)$ 的,无法通过,但是可以通过分层记忆化的方式优化到 $O(T \log n)$,只是常数略大,需要狠狠卡常才能过。 此时其实会发现每一层至多两个状态,模拟这个过程即可去掉记忆化的常数。 然而 [@The_Last_Candy](https://codeforces.com/profile/The_Last_Candy) 给出了一种不同的方法。 将对于指数加法的式子改写为: $$

f(x) = f(\left\lfloor \frac {x - 1} 2 \right\rfloor) + f(\left\lceil \frac {x - 1} 2 \right\rceil) + [\text{x is even}]

$$ 发现偶数的地方会贡献一个 $2$,那么考虑是否可以通过类似数位 DP 的方式求得所有转移时为偶数的个数。 设 $f_{i, 0/1}$ 表示考虑了前 $i$ 位,当前位为 $0/1$ 的个数,然而由于存在 $-1$,所以还需要增加一个 $0/1$ 表示是否向前借位。 那么对于转移: $$

\begin{aligned}
x &= n 的第 i 高位 \
f_{i, 0, 0} &= \begin{cases}
f_{i + 1, 0, 0} + 2f_{i + 1, 1, 0} & x = 0 \
f_{i + 1, 0, 0} + 2f_{i + 1, 1, 1} & x = 1
\end{cases} \
f_{i, 1, 0} &= \begin{cases}
0 & x = 0 \
f_{i + 1, 0, 0} + 2 f_{i + 1, 1, 0} & x = 1
\end{cases} \
f_{i, 1, 1} &= \begin{cases}
f_{i + 1, 0, 0} + 2 f_{i + 1, 1, 1} & x = 0 \
0 & x = 1
\end{cases}
\end{aligned}

$$ 反着来变成 DP 减少常数,最后指数就是 $\sum f_{i, 0, 0}$。 ## GYM 104396 ### B. Honkai in TAIKULA 给定一张 $n$ 个节点 $m$ 条边的有向带权图,对每个节点,若不存在奇权圈(可经过重复顶点、重复边,若经过重复边,边权计多次),输出 `Battle with the crazy Honkai`,否则,输出最小奇权圈的权值(负无穷输出 `Haha, stupid Honkai`)。 由于需要存在圈,那么圈一定在强连通分量内,那么可以利用 `tarjan` 分为若干强连通子图进行求解。 考虑由于需要奇偶分开,那么拆成奇偶两个点即可。 考虑如果是跑 `SPFA` 的话就需要 $O(nm^2)$ 的复杂度,显然不太能过,所以需要用到 `Johnson` 全源最短路算法,优化为 $O(nm \log n)$。 注意有负权环存在的情况。 ### D. Rail Star 二维平面上有 $n$ 个点,设 $A_i,j$ 表示将第 $i$ 个点删除后,将剩下 $n − 1$ 个点划分为两个集合后,提取其中点数为 $j$ 的集合,这个集合的种类数。求出该矩阵。 类似于 [1860F](https://codeforces.com/contest/1860/problem/F) 的想法,一共 $O(n^2)$ 种斜率,带来 $O(n^2)$ 种映射方式,每种映射带来的一种排序都会对于答案做出贡献。 这 $O(n^2 \log n)$ 很容易维护这一个排序方式,但是我还不太清楚该如何维护答案。 ### E. LCM Plus GCD 输入 $x, k$,求大小为 $k$ 的不同的集合个数,其中所有数的 $\gcd + \mathrm{lcm} = x$。 考虑 $\mathrm{lcm} = k \gcd$,那么枚举 $\gcd$ 即可得到 $k$。 观察每一个数,将 $k = \prod {p_i}^{c_i}$,那么对于每一个数的分解,再除以 $\gcd$,指数需要满足 $\min = 0, \max = c_i$。 考虑实际上因数的个数 $\le 9$,那么考虑状压容斥,先枚举有哪些没有满足下界,在这个基础上枚举有哪些没有满足下界,复杂度 $O(Tm2^{2m})$。 ### G. Moving Boxes $n$ 个物品在一条直线上,每个需要从 $x_i$ 移动到 $y_i$ ,有一个机器人移动,机器人每次只能拿一个物品,速度为 $1$,转向需要 $c$ 秒,最后需要回到起点,方向回到初始方向。求运输完所有物品需要的最小时间。 贪心,还不太会。 ### L. Architect 给出 $n$ 个长方体,询问其是否拼接成一个 $W \times H \times L$ 的立方体,没有重叠和空隙。 1. 做法一,先判断体积和。将全部无交容斥为有交,数点问题即可。 2. 做法二,利用随机化将每个立方体的体积放缩,如果满足要求,那么无论如何放缩体积都是合法的,多次随机充分 $\to$ 必要。 3. 做法三,还是先判断体积和,从一维结论合理外推,充要条件是每个点都覆盖了偶数次,利用 `map` 判断即可。 > $\downarrow 2024.03.04$ ## 1936 ### [A. Bitwise Operation Wizard](https://codeforces.com/contest/1936/problem/A) 交互题,每次可以询问 $a_i | a_j$ 与 $a_x|a_y$ 的大小关系,求最大的 $a_i \oplus a_j$,其中 $a_i$ 是一个 $0 \sim n - 1$ 的排列。 首先贪心的肯定要选择最大的那个,然后选择一个数(选了最大的,自然这个就是最小的了)凑出一个 $2^k - 1$。 那么根据 $x | x = x$,利用 $O(n)$ 次形如 $(i, i, j, j)$ 的询问即可找出最大。 找到了 $i$ 最大,接下来需要 $a_i \oplus a_j = 2^k - 1$,只需要找到 $a_i | a_j$ 最大的那些 $j$ 中最小的那个即可。考虑满足 $a_i | a_j$ 最大的一定是 $a_i$ 补集的超集,而需要恰好凑出全部,那么自然是最小的那个,分别 $O(n)$ 次即可。 ### B. Pinball 给定一个 `<>` 组成的字符串,当一个球至于其上某一个位置,其会按照一下规则运动: - 如果所在字符为 `<`,那么向左一位,否则向右。消耗 1s 时间。 - 当球移动之后,原本所在位置字符取反,即 `<` 变成 `>`,反之同理。 - 如果移出串内,则停止运动,既可以是左边,也可以是右边。 多组数据,给定长度为 $n$ 的串,分别求出把球放在 $1 \sim n$ 这些位置需要多少秒才能走出这个串。可以证明一定可以在有限步内走出。 先考虑模拟,比较容易发现,实际上球在一段反复走,向两边拓,于是可以变成双指针 $O(n^2)$ 求。 观察双指针的本质,设出发点在 `>`,分讨出发点左侧(包括)`>` 的个数 $S_0$ 和右边 `<` 的个数 $S_1$。 当 $S_0 > S_1$,那么最终会从字符串右边出去,推推式子即可;当 $S_0 \le S_1$ 则反之,也是推推式子即可。 ### C. Pokémon Arena 有 $n$ 神奇宝贝。一开始,竞技场上只有第 $1$ 只神奇宝贝。 每只神奇宝贝都有 $m$ 种属性。而第 $i$ 只神奇宝贝的 $j$ 属性是 $a_{i,j}$ 。第 $i$ 只神奇宝贝的雇佣费用是 $c_i$ 。 为了最终让 $n$ 只神奇宝贝站在竞技场,可以按照任意顺序执行以下两种操作: - 花费 $k$($k > 0$)的代价,将 $a_{i,j}$ 永久增加 $k$ 。 - 花费 $c_i$ 代价雇佣第 $i$ 只神奇宝贝与当前场上的神奇宝贝 $k$ 决斗,并选择任意属性 $j$。如果 $a_{i,j} \ge a_{k, j}$ ,则 $i$ 击败 $k$,$i$ 上场,否则保持不变。 求出让第 $n$ 只神奇宝贝站在竞技场上所需要支付的最低费用。 > 傻逼翻译。 最直观的想法是,一个神奇宝贝一定不要上场两次,否则直接跳过中间部分。 另一个十分重要的观察:不会连续选择相同的 $j$。否则不如直接跳过中间次决斗,省下雇佣费。 相当于只有去决斗前才会调整 $a_{i, j}$,并且之后都不会在用到这个值。 于是如果让 $i$ 用属性 $j$ 与 $k$ 决斗,那么一定需要的花费是 $c_i + \max(0, a_{k, j} - a_{i, j})$。 利用这个东西建图,可以做到 $O(n^2 m)$。考虑可以优化建图。 将 $c_i$ 提出来,拆点处理,接下来考虑 $\max(0, a_{k, j} - a_{i, j})$ 的边,发现实际上只需要在同层间前后缀一下即可。 于是建出图来跑 DJK 即可。 ### D. Bitwise Paradox 我原本以为只是支配对相关的题目,因为只有 $O(n)$ 个对,但是带修就炸了。考虑 $b_i | b_{i + 1} | \ldots | b_{j}$ 有一个很好的性质,在固定 $i$ 的情况下,只有 $O(\log V)$ 种取值。 所以放在线段树上,维护前缀,后缀,与值与最大值,合并即可。 直接合并是 $O(\log^2 V)$ 的,但是利用支配对考虑,双指针合并变成 $O(\log V)$。 总复杂度 $O((n + q) \log n \log V)$。 ### E. Yet Yet Another Permutation Problem 首先有一个很 `naive` 的 $O(n^2)$ DP: $$

f_{i, j} =
\begin{cases}
[i \ge j](i - j + 1) f_{i - 1, j} + \sum_{k < j} f_{i - 1, k} & j \ne P_i \
0 & j = P_i
\end{cases}

$$ 前面直接做,后面前缀和即可,最后答案是 $f_{n, n}$。 没什么优化的前途,考虑 $P$ 的前缀 $\max$ 数组 $Q$。 考虑构造出来的排列和 $Q$ 存在某一位相同,设为 $i$,那么需要满足 $Q_i$ 在 $i$ 或者之前出现,并且 $i$ 前都没有比 $Q_i$ 大的。 逆着不好考虑。顺着不会考虑,还是没太懂题解的 DP 是怎么来的。 TODO。$$