8 月做题记录
1 NFLS 训练赛 T3
2025 山东省队一轮集训 D5T1,懒得说了。
2 NFLS 训练赛 T4 / QOJ4914
\(fa_i \geq fa_{i-1}\),所以 \(dep_i \geq dep_{i-1}\)。
对于每个 \(i\),令 \(g_i\) 为最大的 \(j\) 使得 \(fa_j < i\)。首先可以发现,\([i,g_i]\) 内的点两两不相邻,其次是,这里面任意两个点深度差至多为 \(1\)。这是因为 \(dep_{g_i} = dep_{fa_{g_i}}+1 \leq dep_i + 1\)。
对于询问 \([l,r]\),所有点构成了若干连通块,每个连通块最上面的点的父亲 \(<l\),不难发现连通块的最上点就是区间 \([l,\min(g_l,r)]\) 内的所有点。任意两个连通块之间的两个点 LCA 比 \(l\) 小。所以答案是每个连通块的点权和的平方的和。
也就是说,我们要对于区间 \([l,\min(g_l,r)]\) 内的每个点 \(i\),求 \(i\) 子树内,属于 \([l,r]\) 范围内的所有点的点权平方的和。
注意到这些点子树内不会有小于 \(l\) 的点,所以只需要求属于 \([1,r]\) 内的点的信息。
按 \(r\) 扫描线,每根号次重构一次,询问对多出来的那些部分求答案即可。需要解决怎么找一个 \([l,r]\) 内的点所属连通块的顶端是哪个点,由于连通块顶端深度差不超过 \(1\),所以求一个 \(k\) 级祖先就行。长链剖分即可。
扫描线过程可以记录下来,时空复杂度都是 \(O(n \sqrt n)\),可能要卡常。
3 P7448
首先做二次离线莫队,要进行 \(O(n \sqrt m)\) 次询问,每次给定 \(l,r\),求 \([l,r]\) 中大于 \(a_r\) 的本质不同数个数。
按照 \(l\) 从大到小扫描线。问题变为 \(O(n)\) 次单点修改,\(O(n\sqrt m)\) 次查询矩形和。特别地,由于映射到的点是 \((r,a_r)\),所以询问横坐标互不相同,纵坐标可以离散化成互不相同的。
我们希望 \(O(\sqrt n)-O(1)\) 解决这个问题。
我们将引入二维分块。具体来说,首先将 \(n \times n\) 平面划分为 \(\left(\dfrac{n}{n^{0.75}}\right)^2 = n^{0.5}\) 个 \(n^{0.75} \times n^{0.75}\) 的正方形。并且在单点修改的时候,更新这些正方形整体的二维前缀和。修改复杂度显然是 \(O(\sqrt n)\)。
但是这显然还不足以应对查询,考虑将每个 \(n^{0.75} \times n^{0.75}\) 的正方形划分为 \(n^{0.25}\) 个 \(n^{0.75} \times n^{0.5}\) 的矩形,并对每一行的总共 \(n^{0.5}\) 个这样的矩形维护前缀和。这样修改的时候更新的复杂度仍然为 \(O(n^{0.5})\)。
同理,我们还将其划分为 \(n^{0.25}\) 个 \(n^{0.5} \times n^{0.75}\) 的矩形,相当于转了个角度。
另外将平面划分为 \(n\) 个 \(n^{0.5} \times n^{0.5}\) 的块,维护所有不能被 \(n^{0.5} \times n^{0.75}\) 及其反过来的表达的位置的前缀和。
这样进行一次询问时,除了询问边界的散块外,左下角大部分都被整块完全包含,可以直接计算答案。
对于散块,不妨考虑在进行点权修改时维护每种询问的答案。在对 \((x,y)\) 修改时,找到其所在的 \(n^{0.5} \times n^{0.5}\) 的块,若查询的矩形完全包含这个块,则其不可能成为散块。所以在 \(x,y\) 轴上扫描这些位置对应的询问即可。由于 \(x,y\) 两两不同,这样的复杂度是 \(O(\sqrt n)\) 的。
综上,这个题做到了 \(O(n\sqrt n+n\sqrt m)\) 的复杂度。代码我没写,先这样吧。
4 QOJ1185
容斥,变为钦定 \(x\) 对相邻。这是容易轮廓线 DP 处理的。
5 QOJ1177
任意时刻非负很难受,向序列中加入 \(-(n+1)d,-nd,-(n-1)d,\cdots,-d\),不难发现此时如果原序列的数没有改为负数,则不影响方案合法性。否则若改成负数,不如全体加 \(1\) 变回非负数。
令 \(b_i = a_i - i \times d\),则 \(a_i - a_{i-1} \geq d \iff b_i \geq b_{i-1}\)。问题变为有序列 \(b_1,b_2,\cdots,b_{2n+1}\),每次修改一个 \(b_i\) 将其加 \(1\) 或减 \(1\),要求序列单调不降,求最小操作次数。
这是很显然的 Slope Trick,维护所有斜率变化的位置即可。
6 杭电多校 1011
场上写了无脑分块,但是过了。
直接做是考虑双指针,要维护加点删点判断连通性。考虑对这个东西做整体二分,维护一个可撤销并查集就行了。
7 P2594
我们声称对于任意一个局面,将其视作若干个游戏,其中每个游戏对应局面中一个反着的硬币,且这个游戏中其他硬币都是正着的。这个大游戏的胜负结果和原游戏相同。证明是考虑归纳,每一次在大局面中选择某个小游戏进行决策,双射到原问题的一个操作。
对于整个局面上只有 \((i,j)\) 是反而其他是正着的游戏,其 SG 函数容易打表观察出来,证明容易归纳得出。
8 QOJ4890
完全注意不出来。
考虑若行上的 \(1\) 和列上的 \(1\) 分别有 \(x,y\) 个。考虑一组方案合法,当且仅当 \(\sum \limits_{i,j} [c_{i,j}=a_i] + \sum \limits_{i,j} [c_{i,j}=b_j]-\sum \limits_{i,j} [a_i=b_j] = n^2\)。并且若方案不合法,这个等号必然只会变为小于号而不会变为大于号。
初始假设所有要填的都是 \(0\),对于每行和每列,可以算出将其从 \(0\) 改为 \(1\) 对这个值的增量。显然行列独立,分别取前 \(x,y\) 大的求和就达到了最优值。若最优值未达到 \(n^2\),则无贡献,否则是考虑第 \(x,y\) 个数的出现次数的一个组合数,随便算算就行了。
复杂度 \(O(n^2)\)。
9 核桃 NOI 模拟赛 T2
编了个和题解完全不同的东西,不知道对不对。
考虑贪心的走法是,每次考虑左边和右边能走的最长后缀与前缀,然后选不超过这个段的,和最大的走。
那么若从 \(i\) 出发,开始时血量为 \(x\),被 \([l,r]\) 卡住,则要求 \([i,r]\) 任意后缀和非负,\([l,i]\) 任意前缀和非负,且 \(x+\sum \limits_{i=l}^r c_i\) 这么多血量能走到的 \([1,l)\) 的所有后缀与 \((r,n]\) 的所有前缀和都小于等于 \(0\)。特别地需要考虑能把 \([1,l)\) 和 \((r,n]\) 走完的情况,这个情况看起来可以特殊处理一下。
考虑对每个 \(l\),求 \(g_l\) 表示,血量至少得是 \(g_l\),才能走到一个 \([1,l)\) 的某个后缀和大于 \(0\) 的位置。对 \(r\) 同理计算 \(h_r\)。
则对于任意 \(l \leq i \leq r\),且 \([l,i]\) 最小前缀和非负,\([i,r]\) 最小后缀和非负,要求 \(x+s_r-s_{l-1} \geq \min(g_l,h_r)\)。目标即求 \(\max \limits_{l,r} \{\min(g_l,h_r) - s_r + s_{l-1}\}\)。
不妨假设 \(g_l < h_r\),另一边对称。固定 \(i,l\) 后,要求 \(s_r\) 最小的 \(r\),满足 \(h_r > g_l\)。有一个重要观察是,符合 \([i,r]\) 任意后缀非负的 \(s_r\) 随 \(r\) 增加而单调不降。所以只需要求最小的 \(r\) 满足 \(h_r > g_l\)。注意到 \(h\) 也随 \(r\) 增加单调不降,所以可以找到唯一对应的 \(r\)。对于 \(r\) 同理。只需要按照 \(i\) 扫描线过程中维护双向关系,即 \(l\) 认为 \(r\) 优,\(r\) 也认为 \(l\) 优,就可以解决问题。
10 NOI D2T2 集合
vp 的时候想的方向不太对,写了个没有优化前途的容斥。
考虑枚举 \(S,T\),限制是 \(S\subseteq f(P)\) 和 \(T\subseteq f(Q)\),求符合这个限制时,所有 \(P,Q\) 的贡献和。记这个答案为 \(f(S,T)\),要求的是 \(\sum g(S,S)\)。由于 \(f(S,T) = \sum \limits_{S \subseteq A, T \subseteq B} g(A,B)\),所以 \(g(S,T) = \sum \limits_{S \subseteq A, T \subseteq B} f(A,B)(-1)^{|A|+|B|-|S|-|T|}\)。于是我们希望求 \(\sum \limits_{S \subseteq A, S \subseteq B} f(A,B)(-1)^{|A|+|B|}\)。
考虑如何计算 \(f(A,B)\)。对于每个数 \(S\),若 \(A \nsubseteq S\) 且 \(B \nsubseteq S\),则 \(S\) 既不能属于 \(P\) 也不能属于 \(Q\)。若 \(A \subseteq S\) 且 \(B \subseteq S\),则即可以在 \(P\) 中也可以在 \(Q\) 中,贡献系数是 \(2a_S+1\)。若只包含 \(A\) 或 \(B\) 但不同时包含,贡献系数则是 \(a_{S}+1\)。
所以 \(f(A,B)=\prod \limits_{A\subseteq S} (a_S+1)\prod \limits_{B\subseteq S}(a_S+1)\prod \limits_{A\cup B \subseteq S} \dfrac{(2a_{S}+1)}{(a_S+1)^2}\),容易写作 \(f(A,B)=g_A\times g_B \times h_{A\cup B}\) 的形式。
需要计算的 \(\sum \limits_{S \subseteq A, S \subseteq B} f(A,B)(-1)^{|A|+|B|}\) 等于 \(\sum \limits_{A,B} (-1)^{|A|+|B|}f(A,B)2^{|A\cap B|}\)。由于 \(|A\cap B| = |A| + |B| - |A \cup B|\),把式子写为 \(\sum \limits_{A,B} \dfrac{(-1)^{|A|+|B|}\times f(A,B)\times 2^{|A|} \times 2^{|B|}}{2^{|A\cup B|}}\),进一步等于 \(\sum \limits_{A,B} \dfrac{(-1)^{|A|}\times g_A\times 2^{|A|} \times (-1)^{|B|} \times g_B \times 2^{|B|} \times h_{A \cup B}}{2^{|A\cup B|}}\)。
枚举 \(A \cup B = S\),则只需要求 or 卷积,FWT 计算即可。
一个细节是,若存在 \(a_S=998244352\),其加 \(1\) 后可能没有逆元。考虑把所有数写成 \(a\times 998244353^{b}\) 的形式,可以直接做加减乘除。复杂度 \(O(n2^n)\)。
11 QOJ4891
强制在线一定程度上是假的,至少我们可以在不回答任何询问的前提下知道修改操作的全部信息与查询操作涉及的节点。
先考虑只对第二棵树查询内邻域颜色数。一个做法是启发是合并,然后维护可持久化平衡树,这样时空都难以接受,不太能过。
我们需要快速维护,对于每个点 \(x\),希望知道其内邻域内所有颜色的最小出现深度。对每种颜色建虚树,可以发现每条虚边上的这个值完全相同,于是可持久化线段树合并即可支持这些操作。
对于原问题,我们还希望对第一棵树上 \(n\) 个节点判定其颜色是否出现在第二棵的某个点的内邻域中。直接在刚才建的可持久化线段树上查询是 \(O(nq \log m)\) 的,显然过不去。离线下来做树上启发式合并,用数组存储信息,即可做到 \(O(nq + m\log m)\),这也是最终的总复杂度。
12 P13559
猜猜猜。
首先,我们有 \(2c-1\) 次的构造,\(c\) 为本质不同度数个数。\(c\) 大概不超过七百多一点,所以这个算法无法通过。
考虑我们浪费了一些东西。具体来说,我们将所有点按照度数排序,对于每种度数,找一个点使得其邻居中叶子节点个数尽量小,我们找一个 \([x,y]\),我们的构造方式是,先按照一般做法做 \([1,x)\) 和 \((y,n]\),然后将 \(x\) 激活,然后每次激活一个非 \(x\) 邻居的叶子,直到 \(deg_y\) 被访问到。对于所有这样的 \(x,y\) 算一下次数,取 \(\min\) 即可通过本题。
13 杭电多校 1012
考虑计算所有情况的和。不难发现只有极长连续没有加减号的前缀有贡献,而其他部分由于其前面可正可负,贡献相互抵消。所以我们希望对每个前缀计算贡献,然后求贡献和。
对于任意一个未出现在给定排列中的数 \(i\),其被填入到这个前缀的,不是开头的位置,贡献为 \(\times i\) 或 \(\div i\),构造 OGF 为 \(F(x)=\prod \limits_{i}\left( (i + \dfrac{1}{i})x+1 \right)\),则对于每个前缀,若其有 \(k\) 个空位,且 \(p_1 \neq -1\),所有可能情况的贡献和为 \([x^k]F(x)\),还要乘上对应的方案数。\(F(x)\) 各项系数容易分治 NTT 求出。复杂度 \(O(n \log^2 n)\)。
对于 \(p_1 = -1\) 的情况,需要枚举一个 \(p_1 = i\),贡献是 \(i \times \prod \limits_{j \neq i} \left( (j + \dfrac{1}{j})x+1\right)\),即求 \(\sum \limits_{i} i \times \prod \limits_{j \neq i} \left( (j + \dfrac{1}{j})x+1\right)\),这个是经典的多项式少一项相乘求和,分治 NTT 时维护原多项式和待求多项式即可。复杂度仍然是 \(O(n \log^2 n)\)。
14 杭电多校 1011
怪题。
考虑序列中有 \(x\) 种本质不同的数,则对于任意一个 \(k\) 进行判断只需要 \(O(x)\) 的复杂度。
另一方面,对于每种 \(d\),模 \(k\) 余 \(d\) 的数,也就是形如 \(kx+d\) 的数,只有最多 \(\dfrac{m}{k}+1\) 种,所以要求 \(c(\dfrac{m}{k}+1) \geq x\),即只有 \(O(\dfrac{mc}{x})\) 种可行的 \(k\),直接对这些 \(k\) 判定,总复杂度 \(O(mc)\)。
15 杭电多校 1010
分类讨论还是过于困难了。
这种东西看着和绝对众数那种东西感觉有点像,但是细节上又很难下手。
考虑最大值,设其为 \(m\),出现次数为 \(c\)。若 \(2\mid c\),必然有解。让其余的人互相撞,直到只剩一个人,他撞 \(m\) 显然撞不死,然后还剩 \(c\) 个两两匹配。
若 \(2 \nmid c\),考虑其余数的和是否至少为 \(m\),如果能,则可以撞死恰好一个 \(m\),从而使得最大值变为偶数个。若不能,则啥都撞不死,最大值总是还有奇数个,此时必然无解。
但是前者不完全对。若 \(c=1\),你把他撞死了,就没最大值了,那咋办。
对 \(c=1\) 讨论细节。现在我们的前置条件是,非 \(m\) 的和大于等于 \(m\)。记次大值 \(m_2\),出现次数 \(c_2\)。若 \(c_2 \times m_2 \leq m\),则我们可以先用其他撞 \(m\),撞到其血量第一次不超过 \(c_2 \times m_2\),则其必然大于 \((c_2-1) \times m_2\)。然后把剩余的对撞到一个后撞 \(m_2\),最后用所有 \(m_2\) 撞 \(m_1\),此时必然有解。
若 \(c_2 \times m_2 > m\),记 \(k=\lceil \dfrac{m}{m_2} \rceil\),也就是最少要撞多少次。如果 \(c_2-k\) 是偶数,用 \(k\) 个 \(m_2\) 撞 \(m\),还剩偶数个 \(m_2\),为此时的最大值,则必然有解。
否则,\(c_2 - k\) 是奇数,如果除了所有 \(m,m_2\) 外的数的和至少为 \(m-(k-1)m_2\),则用这些不断撞 \(m_1\) 使得其和小于等于 \((k-1)m_2\),然后两两对撞剩一个给某个 \(m_2\),用 \(k-1\) 个 \(m_2\) 撞死 \(m_1\) 后,还剩偶数个 \(m_2\) 两两匹配,此时必然有解。
否则若和小于 \(m-(k-1)m_2\),则无论如何都要消耗 \(k\) 个 \(m_2\) 撞死 \(m_1\),并且剩下的不等于 \(m_2\) 的数的和小于 \(m-(k-1)m_2 \leq m_2\),故此时无解。
所有情况讨论完毕。
16 杭电多校 1002
\(k_2 < k_1\) 时,\(k_2\) 是前缀 \(\gcd\),很容易算的。
难点是 \(k_2 > k_1\),不妨令 \(a_1 \leq a_2 \leq \cdots \leq a_n\),则 \(k_1=a_1\),对于固定的 \(k_2\),贡献是 \(\sum \limits_{i=1}^n \left(\lfloor \dfrac{a_i}{k_2}\rfloor+\lceil \dfrac{a_i \bmod k_2}{k_1}\rceil\right)\)。
\(k_2\) 固定时,枚举区间 \([xk_2,(x+1)k_2)\),则 \(\lceil \dfrac{a_i \bmod k_2}{k_1}\rceil\) 贡献形态形如 \(0,1,1,1,\cdots,1,2,2,\cdots,2,\cdots\)。对于每个 \(i\),处理若 \(i\) 这个位置是这个 \(0\) 的开头,后缀的贡献和。对于区间贡献,对后面差分一下然后处理一下最后那段的特殊贡献即可。总复杂度 \(O(m \ln m)\)。
17 QOJ5020
题意:静态链邻域数点,可离线。
想到重剖后就很容易了。总共有 \(O(n \log n)\) 次重链前缀询问,LCA 上的那个区间询问可以差分。离线对重链从上往下扫,维护树状数组,遇到每个点时插入轻儿子子树内所有点即可。
LCA 以上的部分,需要做单点的外邻域数点。重链切换位置,要做单点的内邻域数点。外邻域数点是邻域数点减去内邻域数点。内邻域数点是 \((dfn,dep)\) 的二维数点,咋做都行。邻域数点直接跳点分树即可。总复杂度 \(O(n \log^2 n)\),不卡常。
18 NFLS 训练赛 T2
将答案写成 \((\sum a)^2 - \sum \limits_{j} (sum_j)^2\) 的形式。
树剖,将信息分成轻儿子和重儿子分开维护。子树加只对祖先节点更新信息,子树内类似懒标记维护,询问的时候将祖先上的子树加信息拉出来算即可。复杂度 \(O(n \log^2 n)\)。
19 ARC128F
\(p\) 固定时,不妨假设重排序列使得 \(p_1 > p_2 > \cdots > p_n\),对于后手,要求其第 \(i\) 次取的在前 \(2i\) 个数内。则对于先手,从后往前取数,要求到数第 \(i\) 取的在后 \(2i\) 个内。从后往前贪心,维护一个堆,每次加入两个数,弹出最大值,答案为弹出的数的和。
这个堆的性质很强,具体地,其加入,弹出的形态必然是每次加两个弹一个,且我们只关心堆内的数的相对顺序。不妨设 \(a\) 就是 \(n,n-1,\cdots,1\),如果能对每个 \(i\) 求出 \(i\) 在所有排列中,被选择的次数,即可直接计算答案。
由于我们只关心相对顺序,考虑经典操作,将值域划分为 \(0,1\),于是我们希望对于每个 \(i\),将 \(\geq i\) 的视为 \(1\),\(<i\) 的视为 \(0\),求出在所有排列中,\(1\) 被选的次数总和。
从前往后依次考虑每两个数,有 \(3\) 种可能,分别是两个 \(1\),一个 \(1\),或没有 \(1\)。其中两个 \(1\) 对应两种方案。而维护堆的过程,现在只需要关心堆内 \(1\) 的个数。每次加数弹出的过程是,\(c \gets \max(0,c+x-1)\)。将其视为平面上 \((i,c)\) 这样一个点,表示到了第 \(i\) 组,堆内有 \(c\) 个 \(1\)。每次向右或右上或右下,向右对应两种方案。从 \((0,0)\) 希望走到 \((\dfrac{n}{2},i-\dfrac{n}{2})\)。而整个过程中,本来有 \(\dfrac{n}{2}\) 次弹出都有贡献,但是与 \(0\) 取 \(\max\) 导致有些地方没有贡献。套路地,这等价于把 \(\max\) 去掉,贡献是 \(\dfrac{n}{2}\) 加上历史 \(y\) 最小值。
现在考虑怎么算这个。反射容斥。对于 \(k\),容易计算不超过 \(y=k\) 的方案数。细节是这里向右的系数是 \(2\),不过直接刻画 OGF \((x^{-1}+2x^0+x^1)^n\) 即可得到一个组合数形式。把式子算出来可以发现是一个可以直接计算的形式。然后就做完了。
20 QOJ5019
有简单的 \(O(4^n)\) 级别的做法,从高到低数位 DP,记录每个数和其限制的前面那些位是否都相同。
考虑刻画一下转移的细节。
对于 \(R_i=0\) 的位,转移是 \(0 \times 0 \rightarrow 0\),\(0\times 1 \rightarrow 0\),\(1 \times 0 \rightarrow 1\)。
对于 \(R_i=1\) 的位,转移是 \(0 \times 0 \rightarrow 0\),\(0 \times 1 \rightarrow 0\),\(1 \times 0 \rightarrow 0\),\(1 \times 1 \rightarrow 1\)。
\(R_i=1\) 的位本质上是 and 卷积。对于 \(R_i = 0\) 的位,考虑设计其新状态,\(0\) 表示原来 \(0,1\) 的和,\(1\) 表示原来的 \(0\),则是点积。
问题是对 \(R_i=0\) 的那些位,求其新状态的值,以及如何做,有些位点积,有些位 and 卷积。
这两个问题是类似的,考虑后面的问题。我们规定了每一位的运算方式,对于两个集合 \(A,B\),其在每一位上操作可能是 and 或者点积。考虑改一下 FWT,我们本来是对于每个集合求超集和,现在改为,求 and 位的超集和,点积位是不变的。这个在 FWT 过程中改改就行了。IFWT 是同理的。复杂度 \(O(n2^n\log V)\)。
21 P5416
\(y,z\) 毫无用处,求的是 \(\min \limits_{(x,c) \in S} \{(x_0-x)^2+c\}\)。
离线建出操作树,每个 \((x,c)\) 影响的是一个子树扣掉一些小子树,就是 DFN 序若干区间。线段树分治套李超树即可。
22 QOJ5016
好题。
计数的常见手法:容斥,双射,判定。
容斥不是很有前途。判定确实有方法,对于区间 \([l_i,r_i]\),限制最小值为 \(m_i\),则每个 \(a_i\) 就等于包含其的区间中 \(m_i\) 的最大值,对这个 \(a\) 进行判定,但是过程过于复杂。虽然可以进行一定简化,但总而言之仍然不具有可以进行 DP 的性质。
考虑构建双射。考虑将 \(b\) 和序列 \(a\) 构建双射,\(a\) 就是上述判定的过程的 \(a\),但是这个做法仍然不容易刻画什么样的 \(a\) 能对应某个 \(b\)。把限制变强,将合法的 \(b\) 映射到一个 \(a\) 的生成方式。具体来说,令 \(c_i\) 表示包含 \(i\) 的区间最小值的最大值。我们每次选取目前区间中 \(c_i\) 最小的,若有多个选取最靠左的,然后递归生成 \([l,i)\) 和 \((i,r]\)。这样每个 \(b\) 唯一对应一个生成序列。
我们现在解决两个问题,分别是如何刻画一个生成序列是可行的,以及为什么每个不同的生成序列唯一对应一个合法的 \(b\)。
对于目前要生成的区间 \([l,r]\),由于递归的过程,我们会有一个额外限制 \(x\) 表示最小值大于等于 \(x\)。从 \(i\) 切开则递归到 \(\left([l,i),x-1\right)\) 与 \(\left((i,r],x\right)\)。考虑一个 \(i\) 合法的必要条件是,存在某种 \(b\),使得 \(i\) 是 \(c\) 里最小的且在此之上最靠左的。事实上这等价于,记 \(S_i\) 为区间 \([l,r]\) 内的,包含 \(i\) 的给定区间集合。则要求不存在 \(j< i\) 使得 \(S_j \subseteq S_i\),并且 \(S_i \neq \varnothing\)。反之,若 \(S_i = \varnothing\),显然其不会成为 \(c\) 最小的。另一方面,若 \(j<i\) 且 \(S_j \subseteq S_i\),则 \(c_j \leq c_i\),与 \(c_i\) 最小性矛盾。
据此,可以设计 DP,\(f_{l,r,x}\) 表示区间 \([l,r]\),每个数大于等于 \(x\) 的生成方案数,转移枚举可行的 \(i\),\(f_{l,r,x} \gets f_{l,i-1,x+1} \times f_{i+1,r,x}\)。此外也有可能 \(x\) 不选,\(f_{l,r,x} \gets f_{l,r,x+1}\)。
我们仍然希望说明为什么每个生成方式唯一对应一个 \(b\)。考虑过程中位于区间 \([l,r]\),我们要加入数 \(x\),有两种选择划分点的位置 \(i_1,i_2\),使得得到的 \(b\) 相同。不妨设 \(i_1 < i_2\),则选择 \(i_2\) 的时候,必然有 \(a_{i_2}=x\) 且 \(a_{i_1} > x\),选择 \(i_2\) 时必然有 \(a_{i_1}=x\),\(a_{i_2} \geq x\),如果存在给定区间仅包含 \(i_1\) 而不包含 \(i_2\),则其对应的 \(b\) 不同。否则所有包含 \(i_1\) 的区间都包含 \(i_2\),则有 \(S_{i_1} \subseteq S_{i_2}\),与 \(i_2\) 被选定为划分位置矛盾。
经过可行的预处理,我们可以在 \(O(n^3c+n^4)\) 的复杂度内解决问题。
进一步,容易归纳证明答案是关于 \(c\) 的至多 \(n\) 次多项式,上述过程可以在 \(O(n^4)\) 的复杂度内求出 \(c \in [1,n+1]\) 的每个 \(c\) 对应答案,拉格朗日插值即可。
23 P6684
询问删去区间等价于破环为链后的一段区间。
对于每个 \(i\) 求出 \(f_i\) 表示最小的使得 \([i,f_i]\) 不是二分图。
显然 \(f\) 单调不降,考虑整体二分。对于目前待求区间 \([l,r]\),答案区间 \([L,R]\),求出 \(\lfloor \dfrac{l+r}{2} \rfloor\) 处的 \(f\),然后递归两侧。
考虑如何求出中点的 \(f\),直接从中点往后加边复杂度不对,我们希望在进入递归前,若 \(r < L\),则在并查集中保留 \([r,L)\) 内的所有边,每次查询中点答案时,从 \(L\) 开始往后加。这样访问边数与 \([L,R]\) 长度呈线性,总复杂度就是 \(O(n \log^2 n)\) 了。
24 QOJ5017
挺厉害的题,难点在于要敢往下想。
树上路径计数,考虑能不能点分治。
对第一棵树点分治,设分治重心为 \(r\),对于两个在不同儿子子树内的点 \(u,v\),考虑什么时候 \(T_1\) 上 \(u,v\) 这条经过 \(r\) 的链会在 \(T_2\) 上也是一条链。
点分治的过程总是把 \(r,u\),\(r,v\) 路径拆开考虑,然后通过一些方式合并两条链。我们来考虑处理关于 \(r,u\) 路径的什么信息才能判定两条链的拼接符合条件。
首先有一些必要条件。考虑 \(T_1\) 上 \(r,u\) 这条链,其在 \(T_2\) 上必然需要形成一个链的形态,不能有一个点使得三个儿子子树内都存在点。总而言之,我们可以求出 \(a_u,b_u\),表示 \(T_1\) 上 \(r,u\) 这条链在 \(T_2\) 上,用一条最短链覆盖这些点,这条链的两端是什么,对于 \(a,b\) 的维护,简单在 \(T_2\) 上通过讨论一些 LCA 的东西即可。
对于两条链的拼接,考虑在 \(T_2\) 上的这条链的两端,其必然是 \(a_u,b_u,a_v,b_v\) 四者之二。我们考虑直接用哈希刻画两条路径上的点集相等。我们另外处理 \(c_u,d_u,e_u\),表示 \(T_2\) 上,\(a_u,b_u\) 到 \(r\) 的集合哈希,与 \(T_1\) 上 \(u\) 到 \(r\) 的集合哈希。则要求四种选二共 \(6\) 种情况,存在某种使得对应异或后得到的是 \(e_u \oplus e_v\)。这个式子拆开后,分别维护关于 \(u,v\) 信息即可。
细节上,这么做会算重。其一是,这四个端点可能有相同的。其二是,即使没有,四者选二符合条件并非充分条件。仔细观察一下发现可能有情况是,\(u,v\) 路径上所有除了 \(r\) 的点在 \(T_2\) 中属于 \(r\) 的同一个儿子的子树内,这个时候上述条件有可能会错算。把错算的减去即可。
总而言之,只要在点分治过程中敢于往下想,把细节想明白,就能做了。写一个比较好的 LCA 就可以做到 \(O(n \log n)\),两个 \(\log\) 也可以过。
25 QOJ5098
一个区间 \([l,r]\) 满足条件,等价于 \(\min \limits_{i=l}^r pre_i < l\)。
有两个做法:
第一种是,修改过程中,总共会涉及 \(O(n)\) 次 \(pre\) 的单点修改。对于每个 \(i\) 维护最小的左端点 \(f_i\) 满足 \([f_i,i]\) 符合条件。则 \(pre_i\) 的限制相当于对于所有 \(j \geq i\),都要符合 \(f_j>pre_i\)。所以本质上我们有 \(O(n)\) 次对后缀取 \(\max\) 限制的加入删除。这个过程可以离线下来线段树分治维护。复杂度 \(O(n \log^2 n)\)。
第二种做法常数和实现都更优秀,但是需要多花点脑子。考虑我们直接在线段树上维护这个过程。先考虑,如果要求线段树上每个点的答案怎么做。
我们来考虑怎么高效地维护两个儿子区间 \([l,m],(m,r]\) 的合并。左儿子 \([l,m]\) 的信息可以直接继承,考虑如何计算横跨 \(m\) 的区间的贡献。
在这种信息无法直接简单上传的问题中,考虑单侧递归。在维护这类答案前,我们先处理出每个线段树区间中的 \(pre\) 最大值。记 \(x\) 为 \([l,m]\) 中 \(pre\) 的最大值。我们要求所选区间左端点不能超过 \(l\)。我们找到 \((m,r]\) 对应的左右区间 \((m,m_2]\) 与 \((m_2,r]\)。若 \(\max \limits_{i \in (m,m_2]} pre_i \geq x\),则若横跨 \(m\) 的区间右端点落在 \((m_2,r]\) 内,我们是不关心 \(x\) 的值的,我们只关心 \((m,r]\) 内这些位置的 \(pre\) 对其的影响。对于线段树,额外维护 \(\max \limits_{i\in (m,r]} \operatorname{subsum}(\max \limits_{j=l}^i pre_j + 1, i)\),即只关心区间前缀的 \(pre\) 时,最优区间的答案。对于 \((m,m_2]\) 部分,递归处理。如果 \(\max \limits_{i \in (m,m_2]} pre_i < x\),则右端点为 \((m,m_2]\) 中任意一个点,左端点为 \(x+1\),这个区间均合法。显然应该取右端点为 \(m_2\),然后递归处理右儿子。
而事实上,我们只需要对于线段树每个点维护 \(\max \limits_{i\in (m,r]} \operatorname{subsum}(\max \limits_{j=l}^i pre_j + 1, i)\),就可以在 \(O(\log n)\) 复杂度内求出,对于一个线段树区间 \([l,r]\) 和其左侧某个 \(x\),要求选的区间左端点大于 \(x\),右端点属于 \([l,r]\) 情况下的答案。维护的这个信息的过程就是上述的单侧递归过程。对于区间查询,把区间对应的线段树区间拉出来逐个维护 \(pre\) 的最大值,然后将这个值在下一个区间上做询问即可。时间复杂度同样是 \(O(n \log^2 n)\),但是为在线算法且空间为 \(O(n)\)。
26 QOJ5100
先求整体的答案。
记 \(f_i\) 表示 \([1,i]\) 且 \(i\) 为结尾的答案。直接转移,复杂度 \(\widetilde{O}(n^2)\)。
考虑到 \(x,y\) 的贡献为 \(S - S \bmod \operatorname{lcm}(x,y)\)。有一个做法是,对于每个 \(i\),转移过程中,枚举 \(a_i\) 的倍数。我们可能将 \(\operatorname{lcm}(x,y)\) 在其若干倍上统计到,但是这是无所谓的,因为若如此答案只会变小。
据此,考虑根号分治。记 \(B = \sqrt{n}\),分别考虑小小,小大,大小,大大的转移如何维护。大大的转移按照上述过程即可。其余情况都含有小,直接枚举小是什么即可。复杂度 \(\widetilde{O}(n\sqrt n)\),为了消去求 \(\gcd\) 的 \(\log\) 复杂度因子,预处理任意两个 \(\leq B\) 的数的 \(\gcd\),查询两数 \(\gcd\) 总有一个小于等于 \(B\),查表即可。
第二问。序列反过来做上述 DP。对于 \(i\) 求答案,必然是某个 \(j < i < k\),贡献是 \(f_j + g_k + w(a_j,a_k)\)。
这个东西并不是很好求,观察性质。注意到对于任意 \(x,y \leq B\),必然有 \(w(x,y) \geq \dfrac{S}{2}\),原因是 \(\operatorname{lcm}(x,y) \leq B\),所以要么 \(\operatorname{lcm}(x,y) \leq \dfrac{S}{2}\),要么 \(S-\operatorname{lcm}(x,y) \leq \dfrac{S}{2}\)。这意味着,对于选出的子序列两项之间,最多存在 \(2\) 个未被删除的 \(\leq B\) 的数。
枚举 \(k\),对于 \(a_j \leq B\) 的情况,向前枚举 \(O(1)\) 个即可。若 \(a_k \leq B\),可以枚举 \(j\) 并向后枚举 \(O(1)\) 个 \(k\)。
现在考虑 \(a_j > B\) 且 \(a_k > B\)。类似 DP 转移过程,我们枚举 \(k\) 并枚举 \(a_k\) 的所有倍数,每个倍数对应若干个 \(j\),记最靠后的这个 \(j\) 为 \(j_0\),我们发现若 \(i<j_0\),但是 \(j_0\) 没选,\(k\) 选了,不如把 \(j_0\) 选上。所以只需要考虑 \(i=j_0\) 或 \(i \in (j_0,k)\),这相当于进行 \(O(n\sqrt n)\) 次区间 chkmax,ST 表维护即可。
总复杂度 \(O(n \sqrt n)\)。
27 NFLS 训练赛 T4
第一问,答案是奇数点数量除以 \(2\) 上取整。下界显然,可以取到可以对森林进行归纳。
第二问,二分答案 \(mid\),考虑 DFS 的时候考虑每个子树,我们要在子树内取的链数量尽量少的情况下,求出这个点到父亲的这条链最短延伸了多少。对这个点度数分类讨论。若为偶数,则儿子两两匹配后剩一个。若为奇数,如果能两两匹配,给父亲一条 \(1\) 的路径,否则需要砍掉一条路径,保留一条路径,其他的两两匹配。
第三问,考虑延续第二问的思路。设计 DP,\(f_{i,j}\) 是 \(i\) 子树内满足链数量最小且每条链长度不超过第二问答案的情况下,\(i\) 与父亲的这条链长度为 \(j\) 的方案数。转移需要考虑怎么求任意两个儿子匹配的方案数,之后类似第二问,不过要做一个状压 DP。
\(j\) 这一维是 \(O(dep)\) 的,所以考虑长链剖分优化 DP。过程中由于长短儿子有所不同,需要进行一些分类讨论。对每个点开一个大小为子树深度的线段树即可维护所有操作。
复杂度 \(O(n2^D)\) 加上一些与 \(n,D\) 的多项式复杂度。
28 CF2127F
考虑枚举最大值 \(a_n = i\),然后考虑所有 \(i\) 后面跟着一个数的和的总贡献。\(a_1\) 的贡献可以类似计算。
也就是,要计算,某个位置已经确定等于 \(i\) 的方案数,乘以总和 \(m-2i\),除以 \(n-2\) 即可。这个贡献显然可以在 \(O(\dfrac{m}{i})\) 的复杂度内通过容斥算出。总复杂度 \(O(m \ln m)\)。
29 GYM105992A
记集合大小为 \(n\),共出现 \(m\) 种数,第 \(i\) 种出现 \(c_i\) 次,则子集权值和为 \(\sum \limits_{i=1}^m 2^n-2^{n-c_i}\)。
枚举 \(n,m\),这个式子等于 \(2^nm - \sum \limits_{i=1}^m 2^{n-c_i}\),所以需要判定是否存在 \(\sum \limits_{i=1}^m c_i = n\),\(\sum \limits_{i=1}^m 2^{n-c_i} = k\),\(c_i > 0\)。数位 DP 即可。复杂度分析出来大概是 \(O(\log^5 x)\) 或者 \(O(\log^6 x)\),但是显然跑不满,实则跑的飞快。
30 GYM105981A
考虑先忽略 \(d_q=m\),但是我们仍然要求 \(c_p = n\)。我们希望对于每个 \(a\) 的前缀 \([1,i]\),求出 \(c_p = i\),\(d_q\) 可以不等于 \(m\) 但最后两个必然匹配至少一个的前提下,最大的 \(f_i\) 使得 \(a[1\cdots i]\) 与 \(b[1\cdots f_i]\) 符合条件。显然对于任意 \(j \leq f_i\),\(a[1\cdots i]\) 与 \(b[1 \cdots j]\) 均可行。
考虑如何进行转移。对于 \(i\),二分答案 \(j\),判定 \(a[1 \cdots i]\) 与 \(b[1 \cdots j]\) 是否符合要求。判定考虑取出 \(b_j\) 与 \(b_{j-1}\),则 \(a\) 中必然有两个相邻的位置,使得都等于 \(b_j\) 或 \(b_{j-1}\),从这个位置的 \(f\) 进行判定即可。
复杂度 \(O(n \log n)\) 或 \(O(n \log^2 n)\)。
31 GYM105949L
先将只出现两种以下字符的当成三种算,然后减去他们的贡献并加上应有的贡献,这步是容易的。
对于三种字符分别做前缀和,固定左端点 \(i\),即求 \(\sum \limits_{j \geq i} \max\{A_j-A_{i-1},B_j-B_{i-1},C_j-C_{i-1}\}\),\(\min\) 部分同理。
分别计算 \(\max\) 取到其中每一个的贡献,限制是一个二维偏序,加上序列的 \(i\) 总共三维,cdq 分治即可做到 \(O(n\log^2 n)\)。
题解提到了更加优秀的做法。注意到 \(\max\{a,b\}-\min\{a,b\}=|a-b|\),我们有 \(\max\{a,b,c\}-\min\{a,b,c\} = \dfrac{|a-b|+|a-c|+|b-c|}{2}\),这样不再是三维限制而是二维限制,这个可以 \(O(n \log n)\)。
32 GYM105949D
搜一下可以发现,一个排列 \(p\) 生成的图是三分图,当且仅当不存在 \(a<b<c<d\) 且 \(p_a > p_b > p_c > p_d\)。
思考一下证明,原因是,根据 Dilworth 定理,最长下降子序列不超过 \(3\) 等价于可以用不超过 \(3\) 个上升子序列覆盖整个排列。对于这三个子序列分别填 \(1,2,3\) 三种颜色即可。
对于这样的一个排列做判定,等价于维护三个变量 \(a,b,c\) 表示三个上升子序列的结尾,依次考虑 \(p_1,p_2,\cdots,p_n\),对于每个 \(p_i\),尝试替换三者中能替换的最大值。
在数轴上画出 \(a,b,c\) 以及其对应的三段,我们显然只关心对应段内的数的个数 \(c_0,c_1,c_2\),分别表示 \((a,b),(b,c),(c,n]\) 中未加入的数的个数。于是记 \(f_{c_0,c_1,c_2}\) 表示个数是这么多时,合法排列方案数,容易通过在 DP 过程中处理一些东西在 \(O(n^3)\) 复杂度内算出。对于原问题,枚举 LCP 和 LCP 下一个数即可。总复杂度 \(O(Tn^2+n^3)\)。
33 GYM105941I
很好想的,只是一堆 corner case。
可以看出,大部分情况下是有解的。一个显然的无解条件是有一种新的集合编号。
我们尝试对于一个一般的数据给出构造。我们为每个目标集合 \(i\) 钦定一个代表元 \(x_i\),其中 \(b_{x_i}=i\),表示我们需要将每个代表元移动到其对应的 \(b\) 集合内,之后每个集合内都存在一个不需要移动的人,将所有其他人复位即可。
为了让代表元移动到对应的集合内,我们尝试刻画一个人从 \(x\) 移动到集合 \(y\) 内可行的条件。当且仅当 \(x\) 目前所属集合不在 \(b\) 中出现,或者 \(x\) 所属集合大小至少为 \(2\)。反之,\(x\) 所属集合大小为 \(1\),此时将 \(x\) 移走,其原所属集合就不存在任何数了,这个集合也随之从此消失,这是不符合预期的。
我们希望逐个将代表元移入目标集合,移动时可能存在上述不合法的情况,也就是我们希望将 \(x\) 移入集合 \(b_x\),但 \(x\) 所属集合大小为 \(1\),此时 \(x\) 所属集合的代表元必然未移入 \(x\) 所属集合,递归处理那个代表元后再移动 \(x\)。
这个过程仍然有问题,过程中可能存在环。我们引入自由元,表示一个可以随意移动的人,其只需要是某个所属集合不出现在 \(b\) 中或所属集合大小至少为 \(2\) 的非代表元即可。遇到环时,用自由元将环断开,显然自由元之后仍然是自由元,问题得到解决。
corner case 很多,比如找不到自由元的时候怎么办。这些都是容易分类讨论解决的。复杂度 \(O(n \log n)\) 或 \(O(n)\)。
34 GYM105941B
对取数方案进行计数。设 \([l,r]\) 次全都取出的是 \(c\),且 \(l-1\) 和 \(r+1\) 均不是,对方案数的贡献是 \(\prod \limits_{i=l}^r cnt_i-(i-l)\),表示每次取出的方案数。
据此容易设计 DP,\(f_{i,j}\) 表示考虑了 \([1,i]\),下一次取的数是 \(j\),\([1,i]\) 内部的方案数。转移有 \(f_{i,j} \rightarrow f_{i,j+1}\) 与 \(f_{i,j} \rightarrow w_{i,k,j} \times f_{k,j+1}\)。直接做是 \(O(n^3)\) 的。
将转移过程拆开,记 \(g_{i,j}\) 表示某次取了 \(i\),目前出现次数为 \(j\) 的总贡献。注意到 \(j \leq cnt_i\),所以总状态数是 \(O(n)\) 的。维护这个转移即可。总复杂度 \(O(n^2)\)。
35 GYM105922A
每次先比较 \(a,b\) 的整数部分,然后可以令他们各自减去取整部分得到小数部分,此时 \(a<1,b<1\),递归比较 \(\dfrac{1}{a}\) 与 \(\dfrac{1}{b}\)。
这个过程类似辗转相除,递归次数最多的情况是斐波那契数列,可以算出这个次数是对的,略低于限制。
36 GYM105922H
显然等价于,判定区间中奇数位置集合是否等于偶数位置集合。
维护哈希,若支持快速维护从 \(\operatorname{hash}(S)\) 到 \(\operatorname{hash}(\{y\mid y=a+b,a \in S\})\) 的变换,即可使用线段树维护。
常见方法是 \(\operatorname{hash}(S) = (\sum \limits_{x \in S} B^x) \bmod P\) 或 \(\operatorname{hash}(S) = \sum \limits_{x \in S} \sin(x)\)。前者需要预处理关于 \(B^x\) 的光速幂,所以 \(P\) 不能太大,后者套用区间加区间 \(\sin\) 和即可。复杂度均为 \(O(n \log n)\)。
37 GYM105941E
相当于在 trie 树上选 \(n\) 个结尾涂黑,其他涂白,最大化两两 LCA 的深度和,这也等价于,每个点子树内黑点数量乘以白点数量,上界是 \(\sum \limits_{i} \lfloor \dfrac{c_i}{2} \rfloor \times \lceil \dfrac{c_i}{2} \rceil\),\(c\) 为子树内结尾数量。这个答案显然可以取到,递归构造即可。
38 NFLS 训练赛 T2
等价于询问临时加这些边后点集 \(S\) 是否在一个边双连通分量内。
先缩点,现在有若干森林,将加的边和询问的点拉出来建虚树,对虚树上的这些点跑 tarjan 即可。
39 NFLS 训练赛 T3 / CF1016F 强化版
\(n \leq 500\),答案对 \(10^9+7\) 取模。
固定根 \(r\) 后,给所有边选定顺序,一条边在合并时其中一段的连通块包含 \(r\) 等价于这条边是到根路径上最大的那条,每条这样的边的贡献是 \(\dfrac{1}{2}\)。
据此,尝试设计 DP。\(f_{u,i}\) 表示子树 \(u\) 内,所有给边排序的方案中,只考虑相对大小前 \(i\) 大的边的贡献乘积的和。转移考虑合并 \(u,v\) 子树,并增加一条连接 \(u,v\) 两点的边。钦定 \(u\) 子树内前 \(i\) 大和 \(v\) 子树与新边里前 \(j\) 大会成为新的 \(sz_u+sz_v+1\) 条边前 \(i+j\) 大的。枚举 \(u,v\) 边在 \(j\) 子树内的相对大小即可转移,前缀和优化即可做到 \(O(n^2)\)。
对于每个根计算答案,总复杂度 \(O(n^3)\)。
40 杭电多校 1002
枚举 \(x\),钦定 \(x\) 是第 \(k\) 大的,将所有边权 \(w\) 变为 \(\max(0,w-x)\),算出最短路后,将答案加上最短路经过边数乘以 \(k\)。这样可以算出最短路。
次短路在此基础上改改即可。
41 杭电多校 1003
考虑 \(a,b,c\) 中权值中间的那个数,不妨设 \(b < c\),有分段函数 \(f(x) = \begin{cases} b && x < b \\ x && x \in [b, c] \\ c && x > c \end{cases}\),结果即为 \(f(a)\)。
众所周知,形如这样的分段函数复合后均得到同样的形式,线段树维护即可,复杂度 \(O(n \log n)\)。
42 QOJ5156
考虑环长足够大时的策略,从起点开始,走 \(B\) 格,并将每一格染成随机结果。然后开始绕环一圈,直到这个格子前 \(B\) 格和填的一样,视为我们恰好绕了一圈。正确率可以分析出不低于 \((\dfrac{2^B-1}{2^B})^n\)。
取 \(B=22\),对于环长小于 \(B\) 的部分,依次对于每个 \(i < B\) 判定环长是否为 \(i\),方法是走 \(i\) 步后 flip 走回去看结果是不是一样。次数很充裕。
43 QOJ5160
对于每个输入的 \(a,b\),连边 \(a \leftrightarrow b\),先忽略重边和自环,依次考虑每个连通块。
原问题有环,不妨先考虑序列问题,发现此时一个连通块内有环必然无解。对于树,要求其是毛毛虫。对于原问题,若环有意义,则原图必然只有一个连通块,这个连通块是环外面挂着一些叶子的结构。
重边不重要,但是自环重要,总而言之分类讨论一下即可。
44 AGC059C
询问 \((x,y)\),得到 \(P_x < P_y\),则连边 \(x \rightarrow y\),一个排列合法当且仅当,依次考虑每个限制加入边 \(a \rightarrow b\) 时,不存在 \(c\) 使得已经加入 \(a \rightarrow c\) 与 \(c \rightarrow b\) 的边。
考虑任意一个无向三元环 \(a,b,c\),假设 \((a,b)\) 是询问中最靠后的,则要求 \(P_c < \min(P_a, P_b)\) 或 \(P_c > \max(P_a,P_b)\),换句话来说,\(P_c\) 与 \(P_a\) 的关系与 \(P_c\) 与 \(P_b\) 的关系相同。据此建图,答案要么是 \(0\) 要么是 \(2^k\),其中 \(k\) 为连通块个数。判断其是否为 \(0\) 只需要判定这个图构造的任意一个合法 \(P\) 是否符合原意。
45 CF1713F
操作就是做 \(n\) 次前缀异或和,每次操作后会告诉你序列末尾的数,还原原序列。
不妨设序列从 \(0\) 开始编号,对于 \(k\) 次操作后,序列的末尾是什么。对于任意一个 \(i \in [0,n)\),相当于其从 \((1,i)\) 开始,每次向右或向下,移动到 \((k,n-1)\),方案数是 \(\dbinom{k-1+n-1-i}{k-1}\)。根据 Lucas 定理,其模 \(2\) 等于 \(1\) 当且仅当 \(k-1 \subseteq k-1+n-1-i\),也就是 \((k-1) \cap (n-1-i)=\varnothing\)。将 \(a\) 序列反转,则相当于是 \(i \cap (k-1) = \varnothing\)。
总而言之,对于任意 \(0 \leq i < n\),我们得知了所有与 \(i\) 不交的数的异或和。我们记其为 \(a_i\)。则 \(a_i = \sum \limits_{j \cap i = \varnothing} b_j\)。我们希望还原 \(b\)。
若 \(n=2^k\),我们可以得到每个集合的子集异或,IFWT 回去就行。但是 \(n \neq 2^k\) 时,不能简单地通过将 \(n\) 补全至 \(2^{\lceil \log_2 n\rceil}\) 以解决问题,原因是这样你只知道 \(n\) 个子集异或信息,不足以求出整个 \(b\)。
考虑从 \(b\) 到 \(a\) 的过程,我们希望有一个可逆的过程。考虑对 \(b\) 求超集和得到 \(c_i = \bigoplus \limits_{i \subseteq j} b_j\),然后对 \(c\) 求子集和 \(a_i = \bigoplus \limits_{j \subseteq i} c_j\)。考虑任意一个 \(i\) 对 \(j\) 的贡献,若存在某位同时为 \(1\),则这位恰好被算两次,根据异或的性质被抵消。否则其恰好被算一次。
对于 \(a\) 到 \(b\),将上述过程逆向求解,把 \(a\) IFWT 回去得到 \(c\),并将 \(c\) 的从 \(n\) 开始的位设为 \(0\),然后 IFWT 得到 \(b\) 即可。
46 NFLS 训练赛 T2
笛卡尔树上启发式合并,要维护 \(O(n \log n)\) 次单点修改子集求和。直接做是 \(O(2^{\frac{m}{2}}n \log n)\),可以通过。
套用观虫我就是 \(O((\dfrac{4}{3})^m n \log n)\)。
47 NFLS 训练赛 T4 / CF343E
建最小割树,两个点的最小割是路径最小值。
对树建 Kruskal 重构树,两个点的最小割是 LCA 点权。显然取叶子的 DFS 序即为答案。
48 P9131
对于每个问题,我们记 \(S_i\) 为,认为其困难的人的集合。显然一个问题排列 \(a_1,a_2,\cdots,a_k\) 合法当且仅当 \(S_{a_1} \subseteq S_{a_2} \subseteq \cdots \subseteq S_{a_k}\)。
据此可以设计 DP,\(f_{S} = \sum \limits_{T \subsetneq S} f_T \times \sum \limits_{j=1}^{c_S} \dbinom{c_S}{j} \times j!\)。直接做是 \(O(3^m)\) 的,枚举 popcount 做高维前缀和即可做到 \(O(m^22^m)\),足以通过。
此外,存在 \(O(m2^m)\) 的做法。考虑 FWT 的分治过程,每次递归 \([l,mid]\) 和 \((mid,r]\) 之后,计算 \([l,mid]\) 的高维前缀和对 \((mid,r]\) 的 \(f\) 的贡献,同时更新高维前缀和即可。
49 P10141
对于每个 \(i\),考虑将整个合并过程分阶段,将所有包含 \(i\) 的合并视为关键点,将整个合并过程分段。每个关键点,\(i\) 目前对应了一段区间 \([l,r]\)。每次扩展到 \([l,r']\) 或 \([l',r]\)。
据此,设计区间 DP。\(f_{l,r}\) 表示目前关键点区间为 \([l,r]\),之后的概率。每次从 \([l,r']\) 与 \([l',r]\) 转移。直接转移是 \(O(n^3)\) 的,通过维护一些转移过程的前缀和即可做到 \(O(n^2 \log n)\) 或 \(O(n^2)\)。
50 P8108
并非很容易啊。
如果所有颜色不同,答案显然是 \(n^2\)。我们可以通过消除连续颜色从而减小答案。
考虑任意相邻两列,我们希望选择一些颜色相同的对应的位置 \(a_i,b_i\),要求这两个块在之后的过程中同时被消去。不难发现列之间没有影响,我们只需要考虑相邻两列内部的贡献。
对于相邻两列,不难发现我们要求的是 LCS,数据随机情况下,DP 时枚举另一列对应的相同的位置即可。期望复杂度 \(O(n^2 \log n)\)。
51 AGC058D
考虑对极长非法连续段的起点进行容斥,假设有 \(i\) 个这样的起点,每个起点是 ABC,BCA,CAB 的一种。相当于还有 \(A-i,B-i,C-i\) 个 ABC,然后先把这些随意排列,考虑插入 \(i\) 个三者之一进入序列。
由于是连续段起点,要求插入 ABC 前面的不是 C,BCA 和 CAB 类似,这个应该是相对容易进行计算的。
52 QOJ4923
为了让询问有意义,考虑若所有位置都是 \(1\),那么操作一个位置后即可确定其具体的值。
但是困难的问题在于,操作这个位置之后,在其左侧的 \(1\) 全变成了 \(0\),很难在可行的操作次数内将其归位。
考虑不进行归位,而是继续向后做,可以发现我们可以在 \(O(n)\) 次询问内求出所有前缀最小值位置,并且将所有位归 \(1\)。
随机 \(1\) 到 \(n\) 的排列 \(p\),每次从前往后将所有未求出的前缀最小值求出。每移除一个目前的前缀最小值,LIS 至少减 \(1\)。随机排列 LIS 期望长度 \(O(\sqrt n)\),所以直接这么做期望次数 \(O(n \sqrt n)\),即可通过。
53 QOJ4913
纯纯对脑电波。
我们声称将 \(1\) 视作 \(+1\),将 \(0\) 视作 \(-1\),取从左到右最靠前的前缀和最大的位置翻转即可。
证明是,我们考虑任意两个对称差大小为 \(2\) 的两个数,证明对称差位置不可能同时取到最靠前的前缀最大值,这个分析一下就好。
54 P4416
由于矩形的性质,容易转化为一个森林的形态。覆盖是点到根路径,很容易维护的。
55 GYM106007J
枚举前缀和对应的 \(\gcd\),式子为:
\(\sum \limits_{i=1}^n \sum \limits_{d=1}^m m^{n-i}d\sum \limits_{a_1,a_2,\cdots,a_i} [\gcd(a_1,a_2,\cdots,a_i)=d]\)。
都除以 \(d\),等于:
\(\sum \limits_{i=1}^n \sum \limits_{d=1}^m m^{n-i}d\sum \limits_{a_1,a_2,\cdots,a_i \leq \lfloor \frac{m}{d} \rfloor} [\gcd(a_1,a_2,\cdots,a_i)=1]\)。
这等于 \(\sum \limits_{i=1}^n \sum \limits_{d=1}^m m^{n-i}d\sum \limits_{a_1,a_2,\cdots,a_i \leq \lfloor \frac{m}{d} \rfloor} \sum \limits_{x \mid a_1, x \mid a_2, \cdots, x \mid a_i} \mu(x)\)。
枚举 \(x\),等于 \(\sum \limits_{i=1}^n \sum \limits_{d=1}^m m^{n-i}d \sum \limits_{x} \mu(x)(\lfloor \dfrac{m}{dx}\rfloor)^i\)。
枚举 \(dx=k\),等于 \(\sum \limits_{i=1}^n m^{n-i} \sum \limits_{k} (\lfloor \dfrac{m}{k} \rfloor)^i\sum \limits_{x|k} \mu(x)\dfrac{k}{x}\)。后面是积性函数可以直接算,前面可以整除分块,做到单次 \(O(\sqrt m)\)。
56 QOJ4892
对于每个限制 \(i,j,k,x\),将 \(x\) 加入 \(S_i,S_j,S_k\),表示每个位置的候选集合,显然若有解则存在解使得每个位置最终的值为候选集合内的数。
考虑 \(O(m)\) 个 \(01\) 变量 \(x_{i,j}\),表示 \(a_i > S_{i,j}\) 是否为真。
限制 \(a_i,a_j,a_k\) 中位数为 \(x\) 等价于限制,若 \(a_i > x\),则 \(a_j \leq x\) 且 \(a_k \leq x\)。若 \(a_i < x\),则 \(a_j \geq x\) 且 \(a_k \geq x\),对于 \(j,k\) 同理。
对此建立 2-SAT 模型求解即可。
57 P12967
考虑树 \(D\) 是 \(T\) 的一个子树,且每个点子树大小和为 \(n-m\),这样的子树两两不交。我们只需要在 \(O(size)\) 的复杂度内判定一个子树即可。
考虑判定过程,对于以 \(u\) 为根的子树,和其内的某个点 \(v\) 的子树,要求 \(v\) 子树在原树中出现了至少 \(\operatorname{dis}(u,v)\) 次。对子树同构的 \(v\) 将 \(\operatorname{dis}\) 累加即可。复杂度线性。
58 QOJ4894
贪心过程是,对于 \([l,r]\),初始变量 \(x=l\),每次找到 \(r\) 最小的给定区间 \([l,r]\) 使得 \(l \geq x\),然后令答案加 \(1\) 并执行 \(x \gets r+1\)。直到 \(x>r\) 停下。
不妨记 \(nxt_x\) 表示 \(x\) 对应的下一次 \(x\),本质上需要维护一个内向树。考虑加入区间 \([l,r]\),会将一段 \([p,l]\) 的 \(nxt\) 变为 \(r\),考虑颜色均摊段,对于每个非连续段末尾的点 \(i\),连边 \(i \rightarrow i+1\),边权为 \(0\),对于末尾,连到其对应的 \(nxt\),边权为 \(1\)。LCT 维护即可。
59 QOJ4895
考虑 \(\left(f_d(x)\right)^2\) 等于 \(1\) 或 \(0\),所以 \(f_d(i\times j) = g(i)\times g(j) \times \left(f_d(i \times j)\right)^2\),其中 \(g\) 是 \(\prod (-1)^{k_i}\)。
进一步,\(f_d(i \times j)^2=1\) 当且仅当其每个质因数的次幂不超过 \(d\)。记 \(h(x)\) 为最大的 \(y\) 使得 \(y^{d+1} \mid x\),则要求 \(h(i \times j) = 1\)。则 \(f_d(ij) = \sum \limits_{y^{d+1}\mid ij} \mu(y)\)。
考虑对于一个集合 \(S\),加入一个数 \(x\),\(\sum f_d(i\times j)\) 的增量。增量是 \(\sum \limits_{a \in S} f_d(ax) = g(x)\sum \limits_{a \in S} g(a)f_d(ax)^2=g(x)\sum \limits_{a \in S} g(a)\sum \limits_{y^{d+1}\mid ax} \mu(y)\)。
注意到必然有 \(y \mid x\),否则 \(a\) 本来就不合法。我们只维护合法的 \(a\),则只需要枚举 \(y \mid x\) 的 \(y\)。
枚举 \(y\) 后,式子是 \(g(x) \sum \limits_{y \mid x} \mu(y) \sum \limits_{a \in S} [\dfrac{y^{d+1}}{\gcd(y^{d+1},x)} \mid a]\)。在每次插入 \(x\) 时,枚举其约数进行贡献即可。
对于树上问题,简单使用树上启发式合并即可。
60 NFLS 训练赛 T3
将集合幂集数套用在矩阵树定理上,瓶颈是预处理 \(\prod (\dfrac{3}{4}+\dfrac{1}{4}x^{w_i})\)。其中乘法是 xor。
直接对每个点乘是 \(O(\sum a2^m)\),无法通过。
考虑对每一项 \(\dfrac{3}{4}+\dfrac{1}{4}x^{w_i}\) 求 FWT 后 \([x^S]\) 是多少。显然是 \(\dfrac{3}{4} + (-1)^{\mathrm{popcount}(S \oplus w_i)}\dfrac{1}{4}\)。为 \(1\) 或 \(\dfrac{1}{2}\)。我们只需要对于每个 \(S\) 求出,\(\mathrm{popcount}(S \oplus w_i)\) 为奇数和偶数的 \(w\) 数量,记为 \(c_0\) 与 \(c_1\)。注意到 \(c_0+c_1\) 为输入的 \(w\) 数量,而 \(c_0 - c_1\) 就是 FWT 过程中求出来的那个东西,做完了。
61 NFLS 训练赛 T4 / QOJ4897
考虑每个前缀 \([1,i]\),必然存在某只手使得其左端点 \(\in [p_i-l,p_i]\)。
记 \(f_{i,j,k}\) 为 \([1,i]\),某个左端点位于 \(p_i-j\),另一个在 \(k\) 的答案。转移列出来是维护序列支持全局加区间求 \(\min\),按位求 \(\min\) 生成新序列。线段树合并即可。仔细写出来发现复杂度是 \(O(nL^2\log n)\) 的。
复杂度瓶颈是 \(p_i \in [k,k+l]\) 时要枚举 \(j\),大概是可以对这一部分拉出来单独维护做到 \(O(nL^2+nL\log n)\) 的。
62 CF1483F
枚举 \(s_j\) 以及 \(s_i\) 在 \(s_j\) 中出现的结尾位置 \(x\),显然只有左端点最靠左的 \(s_i\) 可能符合要求。总共只有 \(O(\sum |S_i|)\) 个 \((i,j)\),每个判定一下是容易的。
63 P8368
整个过程中,会有若干次的回撤操作,也就是从目前区间 \([l,r]\),移动到某个 \([l',r']\) 使得 \(l'<l\) 且 \(s[l\cdots r] = s[l' \cdots r']\)。这是为了避免后面删空。
考虑最后一次这样操作到了 \([l',r']\) 后,每次都会直接往前。由于 \([l',r']\) 长度确定,所以之前进行过的操作数也确定。这样的一个区间 \([l',r']\) 操作后的结果长度唯一确定,并且其可能合法的充要条件是其至少在之后还出现过,总而言之维护一些后缀数据结构即可。
64 P13833
首先,两两异或的最小值等于排序后相邻两项异或的最小值。原因是,对于任意 \(a \leq b \leq c\),\(\min(a \oplus b, b\oplus c) \leq a \oplus c\),找到 \(a\) 和 \(c\) 二进制下最高的不同位分析即可。
此外,我们可以证明 \(f(a)\) 是 \(O(\dfrac{V}{n})\) 量级的。考虑 \(f(a) \geq 2^k\),则序列中任意两个数右移 \(k\) 位后两两不等,所以 \(V\) 是 \(O(2^kn)\) 级别的,也就是 \(O(f(a)n)\) 级别的。故 \(f(a)\) 是 \(O(\dfrac{V}{n})\) 级别的。
将求和变为枚举 \(k\),求大于 \(k\) 的序列数。则 \(k\) 是 \(O(\dfrac{V}{n})\) 级别的。对于每个 \(k\),从大到小 DP,\(f_{i,j}\) 表示从大到小考虑了 \(i\) 个数,最后一个数是 \(j\),相邻两个数异或大于 \(k\),对应原序列方案数。转移枚举上一个数 \(x \geq j\),要求 \(x \oplus j > k\)。状态数 \(O(nV)\),转移 \(O(V)\),要做 \(O(\dfrac{V}{n})\) 次,总复杂度 \(O(V^3)\)。
将 DP 式子写出来考虑进一步优化,\(f_{i,j} = \sum \limits_{x \geq j, x \oplus j > k} f_{i-1,x}\) 乘以一个只和 \(j\) 有关的东西。
枚举 \(x \oplus j\) 与 \(k\) 的二进制 LCP,暴力枚举 LCP 里每一位的两种情况。转移复杂度是 \(O(\sum 2^i) = O(V)\)。做一次 DP 复杂度 \(O(nV)\),总复杂度 \(O(V^2)\)。
65 P5576
建立 SA,一个区间合法当且仅当包含 \([l,r]\) 内的所有数。问题转为求一个区间使得最小值最大且包含 \([l,r]\) 所有数。
按照值域大到小扫描线,维护每个序列连续段在值域上构成的连续段,合并时启发式合并,查询是一个二维偏序,复杂度 \(O(n \log^2 n)\)。
66 ARC200E
令 \(a_1 = 0\),将所得答案乘以 \(2^m\) 即可,原因显然。
任意 \(\mathrm{popcount}(a_i \oplus a_j) \leq 2\) 的必要条件是任意 \(\mathrm{popcount}(a_i) \leq 2\)。每个数要么是 \(0\),要么形如 \(2^i\),要么形如 \(2^i+2^j\)。
建立 \(m+1\) 个点的图,编号 \(0\) 到 \(m\),\(2^i+2^j\) 视为边 \((i,j)\),\(2^i\) 视为边 \((i,m)\),\(0\) 视为没有边。一个序列合法当且仅当不存在两条边没有公共顶点。这样的图要么是没有任何边,要么是菊花,要么是三元环,每一类都可以分类讨论进行计数,这是相对容易的。
67 P13834
对 \(a,b\) 同时进行分块。\(b\) 的整块对 \(a\) 的贡献容易进行计算。具体来说只需要预处理 \(f_{i,j}\) 表示 \(b\) 的块 \(i\) 对 \(a\) 的 \([1,j]\) 这段前缀的贡献,也就是出现次数和。查询枚举 \(b\) 的整块进行计算即可。
对于 \(b\) 的散块,将贡献分为对 \(a\) 的散块与整块的贡献。对 \(a\) 的整块的贡献可以同理通过预处理 \(a\) 的第 \(i\) 个块与 \(b\) 的 \([1,j]\) 的贡献直接计算。
另一方面,考虑计算 \(b\) 的散块对 \(a\) 的散块的贡献。查询遍历散块中每个数在 \(S\) 的所有出现位置即可。为此,对 \(a\) 需要按照出现数量进行带权分块。时空复杂度均为 \(O(n \sqrt n)\)。
68 ARC198E
记 \(f_S\) 表示从 \(0\) 变到 \(S\) 的方案数,\(g_S = f_{S+1}\),\(c_S\) 表示 \(S\) 是否在给定集合内。
则 \(f_S = g_{S-1} = \sum \limits_{x \operatorname{or} y = S-1}f_xc_y\)。
故 \(g_S = \sum \limits_{x \operatorname{or} y = S}f_xc_y\)。
考虑计算 \(x \operatorname{or} y \subseteq S\) 的贡献,减去 \(x \operatorname{or} y \subsetneq S\) 的贡献。
即 \(g_S = (\sum \limits_{x \subseteq S} f_x)(\sum \limits_{x \subseteq S} c_x) - \sum \limits_{x \subsetneq S} g_x\)。
其中 \((\sum \limits_{x \subseteq S} c_x)\) 可以预处理。整个过程是半在线高维前缀和形态,解决方法是分治过程中动态维护高维前缀和。复杂度 \(O(n2^n)\)。
69 P6881
考虑每个 \(i\) 的贡献位置在哪。不难看出一般情况下是一个平行四边形结构,找到前面第一个比他大的与后面第一个比他大的即可分析出来。
相当于有一个 \(n \times n\) 矩形,有若干其中一个顶点在 \(y=0\) 上的竖着的平行四边形,每次查询一个 \(y=k\),\(x \in [1,r]\) 的前缀和。
将每个平行四边形写成两个有一个腰在 \(x\) 轴上的等腰三角形相减的结构。问题变为矩形上给定若干个某条边贴着 \(x\) 轴的等腰三角形,每次查询 \(y=k\),\(x \in [1,r]\) 的权值和。考察每个三角形和这样的区间交,将交大小的 \(r-l+1\) 对于 \(l,r\) 分开贡献,整个过程是二维偏序,复杂度 \(O(n \log n)\)。
70 QOJ4915
按照 \(r\) 扫描线。
海胆的第一个限制是,恰有一个环。找到最小的 \(l'\) 使得 \([l',r]\) 区间子图恰有一个环,则要求 \(l \geq l'\)。这个可以 LCT 维护。
第二个限制是,除了环上点,每个点度数不超过 \(2\)。满足这个限制的 \(l\) 也是 \([1,r]\) 的一个后缀。可以在扫描线过程中直接更新。这个也可以 LCT 维护。
最后的限制是连通。注意到满足 \(l \geq l'\) 的 \([l,r]\) 要么恰有一个环,要么无环。则一个这样的图连通当且仅当 \(|V|=|E|\)。否则 \(|V| > |E|\),维护 \(|V| - |E|\) 的最小值,相当于对区间内所有最小值做加法,询问区间历史和。线段树维护即可。
71 P11394
给的串不是很重要。对于每个 \(S \subseteq \{0,1,2,3\}\),容易预处理 \(S\) 在 \(s^{+\infty}\) 中的最长连续段。
至此我们得到了一个 \(O(n^2m^2)\) 的算法,枚举每个起点,BFS 遍历所有点判定其是否会被感染,若能则加入其邻居。根据这样的结构,我们可以写出若干条边 \(u \rightarrow v\),表示若 \(u\) 被感染则 \(v\) 也会被感染。我们要找一个点使得其能到达的点数最少。
显然这些点是缩点后叶子 SCC 内点数最少的 SCC,数量即对应的这些 SCC 点数和。
此题的巧妙之处在于,我们考虑对于这个图求出一棵极大根向生成树,即每个根能直接到达的点都在其对应的树内。则对于任意一个 SCC 我们选定了至多一个代表元,为这个 SCC 中对应的至多一个树根,这是因为若有两个树根则其不为极大生成树。若一个 SCC 不是叶子,则其不会有任何代表元,这是因为若其存在代表元,则其能到达的点必然都在对应子树内,而对应子树内所有点均可到达他,与其不属于叶子 SCC 矛盾。
所以总而言之,只要能找到一个极大根向生成树,则每个根唯一对应一个叶子 SCC,从其开始 BFS,能到达的所有点对应着这个 SCC。这样复杂度是 SCC 大小总和,即 \(O(nm)\)。
考虑如何找到极大根向生成树。这是本题第二个巧妙之处。考虑类似无向图最小生成树的 Boruvka 算法,初始时每个点单独成一棵树,每次对于每个根开始 BFS,找到第一个其能到达的不属于其子树内的点。这个复杂度是 \(O(nm)\) 的。这样每棵还能向外扩展的树根都存在一条向其他树的出边。以任意顺序加入边,有意义的树的数量至少减半,维护并查集判定整个过程,复杂度 \(O(nm \log nm \times \alpha(nm))\)。
72 ARC186E
众所周知,忽略特定子序列不能出现而要求所有子序列都出现,则充要条件是,将序列分为尽量多的段使得每段都出现 \([1,k]\) 中所有数,则段数大于等于 \(m\)。
考虑要求给定序列不出现,则最多划分段数必须恰好为 \(m-1\),且后面剩下的那个后缀包含了除给定序列末尾 \(x_m\) 之外的所有数。原因显然。若段数不足 \(m-1\) 则每个段取末尾后随意取剩下的数至少会存在 \(2\) 个未出现的子序列。所以段数恰为 \(m-1\) 且最后只有 \(x_m\) 没有出现。
除此之外,要求划分的 \(m-1\) 个段末尾依次是 \(x_1,x_2,\cdots,x_{m-1}\)。否则若某段其不为末尾,取子序列为其他位置不变这一位置改为末尾也不会出现。
这是必要但并非充分条件。仍然可能存在某一段不取 \(x_i\) 仍然未出现。考虑某一段不取 \(x_i\) 而取 \(z \neq x_i\),则要求这段中 \(z\) 在 \(x_{i+1}\) 前先出现,否则下一段直接取 \(x_{i+1}\),后面都不变,这个序列就不出现了。而这显然是充分条件,因为考虑一个和 \(x\) 不同的序列,为了使其也不出现,最优方式必然只修改一个位置,这是因为如果相邻两个 \(y_i \neq x_i\) 且 \(y_{i+1} \neq x_{i+1}\),将 \(y_i\) 改为 \(x_i\) 仍然符合条件。
所以一个合法序列要求,段数为 \(m-1\),最后一段除了 \(x_m\) 都出现,每一段末尾为 \(x_i\)。对于每一个 \(1 \leq i < m-1\),要求 \(x_{i+1}\) 在这段中最后一次出现时,之前除了 \(x_i\) 全都出现过。这些都是容易 DP 的,容易做到 \(O(n^3)\)。
73 ARC164F
每个点最终是否会被反转是确定的,根节点深度为 \(0\),则偶数深度节点不会被反转,奇数深度会被反转。双方都希望最小化自己选的奇数深度点的数量。
编一些感性理解上很对的贪心。有偶数深度叶子时,双方必然会优先选这些点。考虑一般情况,所有叶子深度都为奇数。此时对于某个叶子,若其为父亲的唯一儿子,将其删去后,对方可以立即选取其父亲。这是很亏的。所以双方都会优先选取父亲的儿子数大于 \(1\) 的叶子。
在所有叶子都是父亲的唯一儿子时,每走一步都是亏的。感性理解上我们希望尽可能快的交换先后手以将自己处于优的局面。考虑找到一个最小的子树,使得其父亲为儿子个数大于 \(1\) 的偶数深度节点,将这个子树操作完后,先后手互换。至此我们得到了一个 \(O(n^2)\) 的做法。
这个过程相当于,每次取出树上最小的符合条件的簇并删去。考虑静态地将树划分为簇。DFS 过程中通过分类讨论目前点深度奇偶性以及儿子簇的情况容易合并。复杂度 \(O(n \log n)\)。
74 P10787
我们声称,如果任意一个 \(a_i \rightarrow b_i\) 中有至少两条边未定向,则必然存在解。
构造的方式是这样的,我们将所有已定向的边的两端点合并,然后将树黑白染色,每条边都指向黑点。任意 \(a_i \rightarrow b_i\) 上至少有相邻的两条边,这两条边方向必然相反,符合要求。
对于原问题,此结论立即引出了一个 \(\tilde{O}(n^2)\) 的算法,依次枚举每条边,判定将其定向为 \(0\) 后是否产生矛盾,确定这一位后然后往后继续。
看起来,我们需要维护支持修改一条边的方向,然后维护整个判定过程。这相对困难。但是注意到若每个 \(a_i \rightarrow b_i\) 上有至少两条未定向边,将任意一条边随意定向后仍然有解,这是因为你可以把黑白颜色反转而继续使用上述构造。
进一步,我们可以设计一个贪心流程。维护目前存活的所有路径。每次若不存在剩余限制小于等于 \(1\) 的边,将目前未定向的最小边定向为 \(0\)。若有些路径剩余恰好 \(1\) 条边,则将其定向。根据上述结论容易证明正确性。
现在问题变为我们需要维护所有边与路径,支持将一条边激活,并动态维护所有剩余边数 \(\leq 1\) 的路径。
考虑建图。将每条 \(a_i \rightarrow b_i\) 的链上的所有边向这条路径连边。则这个过程相当于激活一条边后,将出边中入度小于等于 \(1\) 的点拉出来。倍增优化建图即可在 \(O(n \log n)\) 的复杂度内维护这个过程。
还需要解决问题是,找到了某个限制 \(1\) 条边的路径后,如何确定这条路径上哪条边还没选,以及其应该选什么或没有限制。后者直接维护边修改路径求和即可。前者考虑每次激活边 \((u,v)\) 时,维护树上并查集,这样容易求出一个点对应的极大已定向簇内的最浅点,从而确定剩下的唯一一条边,复杂度 \(O(n\log n)\)。
75 P10790
考虑特殊性质 C,保证 \(1\) 为一个一类点。
首先,我们尝试找出所有一类点。比较显然的是,一类点肯定是缩点后唯一一个入度为 \(0\) 的 SCC 内部的点。这显然是必要条件。
以 \(1\) 为根建立叶向 DFS 生成树,由于 \(1\) 已经是一类点,非树边只有返祖边,不存在前向边或横叉边。现在考虑点 \(u \neq 1\) 是一类点的充要条件。首先其必须能到达所有点,至少要满足子树内存在返祖边能到达 \(fa_u\) 或以上。而若存在至少两条这样的边,则 \(u\) 到 \(fa_u\) 存在至少两条简单路径,此时 \(u\) 必然不是一类点。所以存在且仅存在一条返祖边 \(x \rightarrow y\)。可以发现 \(u\) 到子树内的点路径唯一,而到子树外的点必然要访问 \(x \rightarrow y\) 这条边。\(u\) 是一类点等价于 \(y\) 是一类点。从上往下依次判定每个 \(u\) 即可确定所有一类点。
现在考虑找出所有二类点。考虑一个点 \(u\) 是二类点的要求是什么。我们希望删去一些边使得 \(u\) 成为一类点的同时,之前的一类点仍然是一类点。考察什么边可以删。首先,树边肯定不能删。其次,为了保证之前的一类点仍然为一类点,对于之前每个一类点 \(v\),其子树到上面唯一返祖边 \((x,y)\) 必然也不能删去。而其余的边可删可不删。
考虑点 \(u\) 能否成为二类点。与之前一样,要求删去若干边后其子树内存在唯一经过 \((u,fa_u)\) 的返祖边。若有至少两条这样的边限制不能删,则 \(u\) 必然无法成为二类点。若恰有一条 \(x \rightarrow y\) 不能删去,则其他返祖边都必须删去。\(u\) 此时能成为二类点当且仅当 \(y\) 是一类或二类点。而若所有边都可以删去,则任取一条 \(x \rightarrow y\) 要求 \(y\) 是一类或二类点即可。这些东西都是好维护的。
对于非特殊性质部分,我们只需要找到任意一个一类点并进行上述过程即可。这个咋做?我还没看懂。
76 LOJ4261
\(f_i\) 表示考虑前缀 \([0,i]\) 且 \(i\) 必须选。转移是 \(f_i \gets a_i + \max \limits_{j \leq i -k} f_{j}\)。
将 \(n\) 个数的序列每 \(k\) 个划分为一段,先进行 \(\max\) 的转移,然后加上 \(a_i\)。注意到 \(\max\) 的来源是前一段的前缀最大值,或者两段之前的全局 \(\max\)。
给定的 \([l_i,r_i]\) 将序列划分为了 \(O(q)\) 个区间,每个区间权值相同。所以按照上述分段过程进行 DP,维护线段树就可以维护所有操作。复杂度 \(O(q \log n)\)。
77 QOJ9222
将 \((a_i,b_i)\) 写到平面上,发现一个点用 B 买则右下角所有都用 B。
换句话来说,存在一条左下到右上分界线,分界线上侧全都是 A,下侧全都是 B。
直接对分界线 DP,转移等价于加入一个矩形的 A 或 B 且加入的权值严格不降。总状态数是线性的,维护一些数据结构大概可以做到 \(O(n \log n)\)。
78 P5979
直接 DP 是 \(O(n^2)\) 的。
考虑 CDQ 分治优化 DP。将动态问题以多一个 \(\log\) 的复杂度变为静态问题,也就是考虑计算 \([l,mid]\) 对 \((mid,r]\) 的贡献。对于 \(i \in [l,mid],j\in (mid,r]\),容易算出 \(l_i,r_i\) 表示要求 \(j \in [l_i,r_i]\) 且 \(i \in [l_j,r_j]\)。对 \(l_i,r_i\) 做扫描线,维护线段树即可。复杂度 \(O(n \log^2 n)\)。
79 QOJ9254
有点意思的套路题。
枚举 \(x\),计算有多少序列众数出现次数至少为 \(x\)。
存在某个数出现次数大于等于 \(x\) 比较难,改为每个数出现次数严格小于 \(x\)。
考虑容斥。钦定 \(j\) 个数出现次数 \(\geq x\)。
记 \(f_{i,j}\) 表示长度为 \(i\) 的序列,总共有 \(j\) 种数,且每种数出现次数都大于等于 \(x\) 的序列个数,乘以容斥系数 \((-1)^j\)。
转移是 \(f_{i,j} = j \times f_{i-1,j} - (m-j+1)\times f_{i-x,j-1}\times \dbinom{i-1}{x-1}\)。
转移意义是,分类讨论第 \(i\) 个数是否为 \([1,i-1]\) 已经钦定的数。前面表示是,后面代表在之前的 \(j-1\) 个数外。
注意到 \(jx \leq i\),所以单次复杂度 \(O(\dfrac{n^2}{x})\),总复杂度 \(O(n^2 \ln n)\)。
80 QOJ7645
将负数和正数分开,不难证明我们每次操作是三种之一:
- 选负数的一段前缀。
- 选正数的一段后缀。
- 选负数的一段前缀与正数的一段后缀。
所以整个过程中任意时刻的状态可以描述成一个区间。
记二元组 \(f_{i,j}\) 表示目前的区间为 \([i,j]\),之前的次数最小值,以及最后一次剩下的最长时间。转移分三种,考虑上述三种情况即可。复杂度 \(O(n^2)\)。
81 炼石 NOIP R1T1
首先可以二分答案,问题变为判定是否能每次选 \(k\) 个减 \(1\) 使得任意时刻 \(t\) 都有所有数大于等于 \(t\)。
任意时刻不重要,我们只关心二分的时刻 \(t\)。这是因为如果存在某个 \(x < t\) 使得 \(x\) 时刻已经不合法了,之后也调整不了。
一个序列每次选 \(k\) 个位置减 \(1\),问 \(t\) 次是否可行。这是经典问题。在 \(k\leq n\) 的前提下,只需要满足总和与最大值合法。对于原问题,二分一下,简单维护就是 \(O(n \log n)\) 的。
82 炼石 NOIP R1T2
第一问是容易的,没有任何额外限制,答案就是区间内黑色连续段长度除以 \(k\) 下取整求和,证明显然。
第二问也是容易的,每个点的下一次移动容易贪心求出,倍增一下就行。
83 炼石 NOIP R1T3
见过一万遍了。
把序列上的套过来做就好了。\(f_{i,j}\) 表示 \(x_i\) 时刻,一只手在 \(y_i\),另一只在 \(j\)。整个东西都可以线段树优化,复杂度 \(O(n \log n)\)。
84 炼石 NOIP R1T4
这个题有点牛。
对于这种,正反同时需要考虑的问题,尝试两边向中间扩展。
关键观察是,若 \(A \times C = R(A)\),则 \(1 \leq C < k\),原因显然。
也就是说,\(A \times C\) 在乘法运算时,只需要乘一次。
枚举 \(C \in [1,k)\),我们考虑前后向中间扩展,每个时刻我们都填好了一段前缀 \([1,i]\) 和后缀 \([n-i+1,n]\)。注意到 \(A \times C\) 的末尾 \(i\) 位已经通过填入的后缀确定了,并且要求等于这段前缀反过来的形态。另外,\(A \times C\) 的前 \(i\) 位也确定,尽管 \(A_{i+1}\) 没有确定,但是这前 \(i\) 位必然等于 \(A\) 确定的后缀反过来的结果。
设 \(A_i = a\) 且 \(A_{n-i+1}=b\)。我们要求末尾 \(i\) 位合法,且前 \(i\) 位在考虑 \(A_{i+1}\) 对其进位后合法。所以我们在过程中关注 \(b\times C\) 向前进位次数,以及要求 \(A_{i+1} \times C\) 对 \(a\) 的进位次数,总而言之可以用 \(\mathrm{poly}(k)\) 个信息记录,数位 DP 过程即可。总复杂度看起来 \(k\) 上有好多个,但其实合法状态数很小,直接做应该就能过。
85 QOJ7644
若区间 \([l_i,r_i]\) 与 \([l_j,r_j]\) 有交但互不包含,则连一条无向边。一个区间集合法,要求不存在奇环。
如果数的是,对于每种区间集,合法的将区间划分为上部或下部的方案数总和,就容易计算了。具体来说,先考虑计算要求都在下部的方案数,记做 \(f_n\),这很容易通过枚举 \(2n\) 和 \(i\) 匹配进行计算。然后考虑 \(g_n\) 表示划分为上下的方案数总和,枚举 \(2n\) 和 \(i\) 并钦定其向上即可算出。
对于原问题,考虑每次剥离 \(2n\) 所处连通块。我们希望计算 \(h_n\) 表示 \(2n\) 个点的,连通可行图个数,用 \(g_n\) 减去存在一个包含 \(2n\) 的非全集连通块方案数即可,这是容易 DP 的。原问题的剥离连通块 DP 与这个类似,总复杂度 \(O(n^3)\)。

浙公网安备 33010602011771号