2023SDPT-Round1

未整理完 Day4C Day5C Day6A Day8A Day8Bsolve2 Day9 Day10C Day11 Day12 应该是摆了。

SDOI

Day1

题面

A

连续的一段 A 和 B 贡献只能选一个,贪心必然是选择最大的,先缩。记最后缩成了 \(k\) 个点,容易发现头和尾上的永远不可能被选到,选择一个点后,两侧的点会合并然后保留较大值。所以总共可以选的点有 \(\lceil \dfrac{k-2}{2} \rceil\),然后去掉头尾后选前 \(\lceil \dfrac{k-2}{2} \rceil\) 大即可,证明考虑一段连续要取得答案从一段开始取,大的总能被保留下来,并掉的是旁边的小的。特判掉 \(k=1,2\)。复杂度 \(\mathcal O(n \log n)\),瓶颈在于排序但是可以线性。

B

对操作序列分块,每个块维护一个表,记录每一个点进入这一段操作后出来是在什么点。记 \(x\) 走向 \(y\),即 \(x \to y\)

散块暴力走,如果在祖先或某个祖先的另一个子树中,那就直接往父亲走,即 \(x \to fa_x\);如果在当前点的子树中,预处理出每个点的树上 \(k\) 级祖先,如 \(x\)\(y\)\(k\) 级祖先,那就走向 \(y\)\(k-1\) 级祖先,可以 \(\mathcal O(n\sqrt{n})\) 光速幂预处理,\(\mathcal O(1)\) 查询。

整块直接查表,考虑如何维护表,如果是单个点操作相当于整棵树上所有的点向这个点移动一步。把每个块里点拉出来建立虚树,在虚树上的点每个之间还有一段点,每段用一个双端队列维护,每次移动相当于 \(\Theta(1)\) 的头 pop,尾 push。双端队列里面每个节点维护一个链表,因为可能有很多个点在一次操作到达同一个点,直接插入到链表中,以后每一次插入删除直接移动整个链表。链表中加入一个点整个虚树上移动的点就会少一个,均摊下来依然是 \(\Theta(1)\) 的。不在虚树上但会进入的点会有一个时刻进入虚树,这个可以预处理出来,到时候再插入队列即可;不会进入虚树的点直接用 \(k\) 级祖先计算最后到哪里。

设分成 \(T\) 个块,每个块就会有 \(T\) 个双端队列,单次操作都是 \(\mathcal O(1)\) 的,所以就可以 \(\mathcal O(T^2 + n)\) 处理每一个块的表。\(T\)\(\sqrt{n}\),总复杂度就是 \(\mathcal O(n\sqrt{n} + n_0 + m + \sqrt{(n_0 + m)(n+m)n_0})\)

C

首先合并满足 \(a_{i+1} = b_{a_i}\) 的合法极长段,遍历一遍可以合并出来。

\(i\)\(b_i\) 连边,由于排列的性质最后得到至少一个置换环,把每一个置换环单独拉出来排完后重标号。

考虑拆开询问,对于 \([l,r]\) 拆成跨过 \(l\)\(r\) 的散环和完全处于 \([l,r]\) 的整环。

对于散环,相当于知道了在环上的起点和需要走的长度,判断一下能不能走到含有 \(x\) 值的点就可以了,随便维护点什么。

对于整环,右端点的限制没有用了,相当于我们从这一段的左端点所在的位置进入,然后知道了走的长度,转化成在二维平面上,横轴是序列下标,纵轴是权值,每个环在序列上左端点的标号的位置插入一个纵线段,长度是置换环的长度和极长连续段的长度取 \(\min\)。单点修改相当于断环更改,转化过来就是删除原线段,插入新的。询问操作就是区间 \([l,r]\) 上插入一条权值为 \(x\) 的横线段,看它和相交的纵线段的权值 \(\max\)。对权值一维线段树分治,里头再套一层线段树来维护答案,树套树的复杂度 \(\mathcal O(q \log^2 n)\)

Day2

题面

A

设有 \(x \to y\)\(x \to z\) 的路径,路径长长均为 \(L\)。若出现 \(y \to a\)\(z \to a\),则出现了长度为 \(2L + 2\) 的环;若出现 \(y \leftrightarrow z\),则出现了长度为 \(2L + 1\) 的环。做一个 BFS,从一个点 \(x\) 向外一层一层扩展检测是否形成环,有环就找到了包含 \(x\) 的最小环。用一个桶存下每一个点被扩展时在第几层,如果扩展到之前来过的点则统计答案:两点层数相同是 \(2L + 1\) 的环,否则是 \(2L + 2\) 的环。每个点扩展是遍历每一个节点,成环后停止扩展。找到环是顺便累加环的个数,最后答案是 \(\text{总环数} \div \text{环上点的个数} \div 2\),因为环上每一个点都会累计一次答案,每个点有两个方向遍历。单个点扩展 BFS 是 \(\mathcal O(n + m)\) 的,要统计每一个点的答案,环长是对所有环取 \(\min\),累加个数答案,总复杂度 \(\mathcal O((n+m)n)\)

B

处理 \(P_{i,j,k}\) 表示对于字符 \(i\) 把序列分成了若干段,第 \(j\) 段中有没有字符 \(k\)

注意到 \(j \times k = n\),所以这个东西的空间大小是 \(\mathcal O(|\Sigma|n)\),预处理的时间复杂度也是这个,再做一个前缀和就可以 \(\mathcal O(1)\) 查一个询问 \([l,r]\) 中,有多少个 \(k\)

直接枚举字符,整段直接按照上面的方法查,跨过询问端点的散段可以再记录一个字符 \(k\) 在块里面第一次和最后一次出现的位置,特判一下就好了。时间复杂度是 \(\mathcal O(|\Sigma|n + |\Sigma|^2m)\)

C

把符合 \(l \le y_k \le r\) 的合法 \(y\) 的位置标记成 \(1\),然后考虑要满足 \(a_i = a_j\),转化题意就变成了多次询问一个询问区间 \([l,r]\) 中连续 \(1\) 段做小z的袜子的和。小z的袜子之所以是根号是因为区间信息不好合并,这个甚至是小z的袜子加强版,所以 poly 肯定没救了。

只有 \(y_i\)\([l,r]\) 的值域区间内的 \(i\) 所对应的 \(a_i\) 才会对答案有贡献。记一个二维平面纵轴是 \(y\) 的值域,横轴是下标。我们在值域上每个 \([l,r]\) 做莫队,将 \([l,r]\) 限制下合法的区间视为 \(01\) 串中的 \(1\),莫队的伸缩相当于合并或分裂两段连续的 \(1\)。分裂的答案是很难操作的,可以使用回滚莫队搞掉。

现在的问题在于如何 \(\mathcal O(1)\) 合并两个区间贡献。考虑根号平衡,对于 \(a\) 序列中出现超过 \(\sqrt{n}\) 次的颜色拉出来离散化重标号,独立跑回滚莫队,总共跑不超过 \(\sqrt{n}\) 次。小于 \(\sqrt{n}\) 次的颜色可以发现 \(\sum col \le n \sqrt{n}\),直接暴力枚举同色点对。假设我们找到了一个相同颜色对他们的下标为 \(L,R\),那么区间 \([L,R]\) 只会对 \((-\infty,\min_{L \le i \le R} b_i] \cup [\max_{L \le i \le R} b_i,\infty)\) 的位置产生 \(+1\) 的贡献,这个东西本质上是 \(2-side\) 矩形数点,为了平衡复杂度需要分块 + 扫描线,加点 \(\mathcal O(n\sqrt{n})\),查询 \(\mathcal O(m\sqrt{n})\)

最后合并大小块的答案,总复杂度为 \(\mathcal O(n \sqrt{m} + m)\)

Day3

题面

A

状压DP,注意到图是无向图,所以不妨找一个特殊点 \(x\)(直接使用 \(1\) 号节点了),对于 \(a \to b\) 的哈密尔顿路必然经过 \(x\),所以 \(a \to x \to b\) 等价于找 \(x \to a\)\(x \to b\) 的两条路径不相交且点集并起来是全集。

\(f_S\) 表示当前走过的点的集合为 \(S\),最后一步可以位于哪一个节点。这个东西可以 \(\mathcal O(n2^n)\) 预处理:如果 有边与 \(x\) 相连的点组成的集合\(f_{S - x}\) 求交之后不为空集,那就是合法的,求交显然 \(\Theta(1)\),剩下的是纯枚举。然后枚举 \(x \to a\) 得到的集合 \(S\),也容易得到其补集 \(x \to b\),对于每个 \(a\) 更新出合法的 \(b\) 并统计答案,时间复杂度也是 \(\mathcal O(n2^n)\) 的。

神秘做法:dwt 使用卡时爆搜,每次只找一条哈密顿路,找不到就退出了。然后 shuffle 下标序列,重新搜。注意到稠密图随便走就走出了,稀疏图能很快走完,所以正确性很难卡掉,基本随 \(500\) 组才挂一组。看到特殊性质 A,图中的边是随机的,可以使用邓老师调整法

B

三种操作分别对应三种函数:

\[f_i(x) = \begin{cases} -\infty \quad & x \le a_i \\ x - a_i \quad & otherwise \\ \end{cases} \quad g_i(x) = \begin{cases} -\infty \quad & x < a_i \\ a_i \quad & otherwise \\ \end{cases} \quad h_i(x) = \begin{cases} -\infty \quad & x = -\infty \\ a_i \quad & -\infty < x < a_i \\ x \quad & x \geq a_i \\ \end{cases} \]

使用 \(-\infty\) 表示挂掉了,需要做的是维护最后这些函数的映射,并快速查询第一个 \(-\infty\) 在什么位置。能够发现这三个函数复合起来得到的函数形如一段为 \(-\infty\),一段斜率为 \(0\),一段斜率为 \(1\)。是个一次/常值函数,这个东西可以线段树维护,询问直接在线段树上二分第一个 \(-\infty\) 的位置。

C

先尝试算出次数的下界,再考虑如何到达下界。

进行 \(k\) 次操作最多得到长度为 \(2^k\) 的序列,所以有一个比较宽松的下界 \(\lceil \log_2{n} \rceil\)。构造出来的序列在任何时刻一定是 \([l,r]\) 一段连续完整的区间,在任何时刻一次操作不会构造出同一序列多次。建一张图,对于一个点表示区间 \([l,r]\),如果它由两个小区间 \([l,mid]\)\((mid,r]\) 拼合而得来,则从两个点向它连边。注意到所有的叶子节点一定形如 \([i,i]\),而且任意一个叶子节点只会被一个区间直接包含,图中必定有所有的 \([1,i] \quad i \in [1,n]\) 节点(因为这是最后的答案),所以最后得到的一定是一棵外向树。结合上面的拼合区间,这还一定是一棵二叉树。

我们总共有 \(n-1\) 个叶子节点,树中的节点要么完全(被)包含,要么完全不交,证明如上。设进行了 \(k\) 次操作,合并次数为 \(s\),那么根据题意有 \(4k \geq s\)。我们一次操作只能够得到一个 \([1,i]\) 区间,原因是上面的树中节点特性,易证的。设我们需要 \(A\) 个形如 \([1,i]\) 的区间在树上,得到这么多区间总共需要 \(n - 1\) 次合并,树外还有 \(n - A\) 个区间,就算每次都能够得到一个区间,也需要做 \(n - A\) 次,这样我们总共需要 \(2n - A - 1\) 次合并。容易得到 \(k \geq A - 1\),所以 \(k \geq 2n - 2 - s\),加之 \(4k \geq s\),我们得到了 \(k \geq \max (\dfrac{s}{4},2n - 2 - s) \geq \dfrac{2n - 2}{5}\)

综上所述,我们得到了操作下界 \(\max (\lceil \log_{2} n \rceil,\lceil \dfrac{2n - 2}{5} \rceil)\)。当 \(n \le 16\) 时前者大于后者,可以直接爆搜得到答案。对于 \(x > 16\) 的情况,如何卡紧这个界呢,这个界大概是 \(0.4n + \mathcal O(1)\)。我们能够很容易做到 \(3\) 步构造 \(n = 8\),它的复杂度为 \(\dfrac{3}{8-1} n + \mathcal O(1)\),那么能不能 \(6\) 步干掉 \(n = 16\) 呢,它的操作就卡成 \(\dfrac{6}{16-1} n + mathcal O(1) = 0.4n + \mathcal O(1)\) 了。直接合并两个 \(n = 8\) 的区间还要多一个 \(1\) 的常数,行不通。事实上我们可以爆搜或者手玩出一个合法的方案,因为这个方法必然是存在的,然后直接套用就好了。

Day4

题面

A

根据样例可以猜测出总能存在一个合法方案使得差值为 \(0\)。将一个物件视为长度为 \(v_i\) ,高度为 \(\dfrac{m_i}{v_i}\) 的矩形,将高度从小到大排序放在二维平面上。取一条长度为 \(\dfrac{\sum_{i=1}^n v_i}{2}\) 的线段在横轴上平移,这样我们已经固定了两部分 \(v_i\) 的差值为 \(0\),剩下的部分就是要使得横线上对应的矩形面积差值为 \(0\),容易做到线性。考虑正确性,一个时刻最多只有左右端点同时处于两个矩形中,所以最多切割两次,符合题目中的切割次数限制。矩形的面积从左向右单调递增,线段处于最左边时总矩形面积小于 \(\dfrac{\sum_{i=1}^n m_i}{2}\),处于最右边时总矩形面积大于 \(\dfrac{\sum_{i=1}^n m_i}{2}\),那么中间必然会有一个位置恰好等于 \(\dfrac{\sum_{i=1}^n m_i}{2}\),正确性由此保证。

B

\(f_{x,y}\) 表示在以 \(x\) 为根的子树中,\(x\) 所在的连通块大小为 \(y\),这种情况下的得分。暴力转移的话考虑选不选当前点的儿子的边,不选则统计答案,选则更新 \(x\) 所在块的最小值。需要枚举点和钦定的最小值,复杂度为 \(\mathcal O(n^3)\)。但实际上一个点能够贡献转移的点只有子树大小,考虑做树形背包,只枚举有贡献的部分,可以优化到 \(\mathcal O(n^2)\)。考虑每次合并贡献信息,我们做的东西形如 \(f_{y,-}\)\(f_{x,-}\) 做单点修改或者区间乘,这个东西可以使用动态开点线段树优化。合并的话也不需要启发式合并,直接在线段树上做线段树合并维护信息,就能够优化到 \(\mathcal O(n \log n)\)

C

如果放在序列上做,手玩发现本质是对于序列的前缀和,每次操作交换其中的两项,最后使得逆序对数量为 \(0\)

定义环的前缀和,使 \(A_0 = A_n\)\(S_i = S_{i-1} + A_{i \mod n}\),此时再对 \(A_i\) 操作,等价于 \(S_{i+kn}\)\(S_{i+kn-1}\) 交换。无解的情况为 \(S_n \le 0\)\(A_i\) 不全为 \(0\)

\(R_i\) 为有多少 \(i > j\) 使得 \(S_i < S_j\)。操作存在两种情况:

  1. \(A_i < 0\),操作后变为 \(R'_{i - 1} = R_i - 1\)\(R'_i = R_{i - 1}\)
  2. \(A_i > 0\),操作后变为 \(R-_{i + 1} = R_i + 1\)\(R'_i = R_{i - 1}\)

操作一使得逆序对减一,操作二使得逆序对加一,因此我们总会选择操作一进行。现在的问题变为如何快速找到要操作的位置,快速计算 \(R_i\)。能够发现 \(R_i = R_{i + n}\)

Day5

题面1

题面2

A

首先对原图缩边双,一个边双内的点可以随便连边,对答案没有影响。缩起来后是一棵树,节点有一个大小的权值。题意为使图中没有割边,新加入的边必然不是割边,割边是缩出来的树上的边。记 \(f_{x,S}\) 表示以 \(x\) 为根的子树中与 \(x\) 相连的联通块大小为 \(S\) 的带容斥系数的贡献和,每次转移我们钦定 \(x\) 和它的儿子之间的边是否是割边,做一个类似树形背包的 DP。

  • 初值为点的内部可以随便连边,即为 \(\dfrac{siz_i \times (siz_{i} - 1)}{2}\)
  • 如果不是割边,那么任意两两间都能连边,就是累加上 \(f_{x,T} \times f_{son_x,S-T} \times 2^{T \times (S-T) - 1}\)
  • 如果是割边,那么就是一个都不选 - 选一个 + 选两个...,容斥系数为 \((-1)^{割边数量}\)

根据上述嗯转移即可,综上所述时间复杂度做到了 \(\mathcal O(n^2)\)

B

\(f_{i,x}\) 表示从 \(1\) 号节点出发,走 \(x\) 条黑边,至少要走几条白边。构建坐标系,横轴为黑边条数,纵轴为白边条数,提出来发现只有左下凸壳是有用的,这又是整点凸包,所以点的数量级为 \(\mathcal O(n^{\frac{2}{3}})\)(有关证明见此),加之是图的缘故这个上界并不容易卡满。使用左下凸壳上的点转移最短路即可,时间复杂度 \(\mathcal O(n m \log n^{\frac{2}{3}} + q)\)

C

D

首先考虑 \(k = 0\),设 \(f_i\) 表示从 \(i\) 走向 \(i\) 的父亲 \(fa_i\) 的期望步数,记一个点的度数为 \(D_i\),则有 \(f_i = \dfrac{1}{D_i} + \sum_{j \in son_i} \dfrac{f_j + 1 +f_i}{D_i}\),前半部分是一步从儿子走到 \(i\),后半部分是儿子先走到了儿子的儿子,又走上来走到 \(i\)。整理一下可以得到 \(f_i = D_i + \sum_{j \in son_i} f_j\)。答案为 \(\sum_{i \in (x \Rightarrow 1) | i \neq 1} f_i\),不计 \(f_1\) 是因为一步跳到根后就结束,没有机会后退了。

如果 \(k \neq 0\),那么如果有一个点 \(y\) 到父亲 \(x\) 的边被定向了,那么他走到父亲之后就不会再有往这个儿子掉的可能了,因此要 \(f_x = f_x - f_y\)。如果一段路径上都被定向(即 \(y \Rightarrow x\) 上的边都被定向),那么他们的贡献只会被计算一次:离 \(x\) 最近的那一条边的贡献被减掉,这个可以感性或从定义上理解。

计算方案数的方法为考虑每个点什么时候对 \(x \Rightarrow 1\)主链上的点产生影响,这个东西的充要条件是一个点到主链的路径上没有被定向的边。对于点 \(x\) 我们钦定他到父亲的边被定向了。所以最后一个点的贡献就是:

\[\dfrac{\sum_{i = 2}^{dep_x} \binom{n - k - (dep_x - 1)}{k - 1}}{\binom{n}{k}} \]

使用上指标求和处理,树形 DP 时间复杂度做到 \(\mathcal O(n)\)

E

转化操作,设行上加的值为 \(\mathcal F(x)\),列上加的值为 \(\mathcal G(y)\),要保证 \(\sum_{x = 1}^n \mathcal F(x) + \sum_{y = 1}^m \mathcal G(y) = 0\)

每个点都会构成一个限制,要求 \(\mathcal F(x) + \mathcal G(y) \geq - a_{x,y}\)。将这个式子看作 KM 算法的顶标,跑最大权完美匹配,如果 \(> 0\) 则无解,\(< 0\) 则存在合法解。构造方案枚举边即可。

Day6

题面

A

solve1:模拟费用流。设 \(f_i\) 表示操作一的收获,\(g_i\) 表示操作二的收获,\(h_i\) 表示都操作的次数,都操作显然比只操作一个不劣。

B

显然如果一个区间被覆盖了 \(\le 1\) 次,那么无解。如果有一个大区间包含了小区间,这个小区间必然会选和大区间相反的颜色。去重之后所有区间没有包含关系。如果这个环上有偶数个段,交替染色即可。如果有奇数个段必然有一个段和相邻的一段颜色选取要相同,那么要求两个段相交的部分每个点都要被覆盖 \(\geq 3\) 次。可以直接枚举这个段是谁,如果合法就视作和相邻段合并,这样就又可以交替染色了。

更为自然的想法是注意到解不是特别紧,先任意给定一个分配方案,然后每次随机从不合法的位置随机选一条覆盖这个点的线段改颜色,这样随机调整。判断合法的方法可以直接两棵线段树查是否都被覆盖,能够做到 \(\log\)

C

把列视为桶,将行视为球,那么每个桶里面有 \(\leq 2\) 个球,有不同的 \(n\) 个球,球之间无标号。矩阵的形式不好计数,考虑转化成图,对图计数。如果一个桶里面有两个球,就在两种球之间连边;如果只有一个球,就连一个自环。因为行上只能有 \(\leq 2\) 个球,所以每个点的度数 \(\leq 2\),除去自环的情况,最后得到的是若干个环和链。加上自环的话,自环只能加在链头。

考虑 \(n = 1\) 的组合对象有三种:点,带一个自环,带两个自环;\(n \geq 2\) 的组合对象有四种:环,链,一个链头带环,两个链头带环。假设一种组合对象的生成函数为 \(\mathcal F\),另一种组合对象的生成函数为 \(\mathcal G\),因为这些组合对象是能区分的,从图上实际意义考虑是构成的形态有区别,因此这两种组合对象共同构成的生成函数为 \(\mathcal F * \mathcal G\)

只有 \(n = 1\) 有三种,十分难看,所以假设它也有四种最后再去掉。当求第 \(n\) 项的答案的生成函数的时候,答案就是前 \(n-1\) 项的四种生成对象的生成函数都卷起来。考虑如何优化这个过程:我们可以先将每项的一种生成函数卷起来,考虑其组合意义,假如说这种生成对象为孤立点,那么就是单个孤立点/两个孤立点/三个孤立点 \(\cdots\) 构成的图,这个东西的生成函数本质是将一个正整数拆分成若干个正整数的和,可以使用根号分治或者五边形数在 \(\mathcal O(n \sqrt{n})\) 的时间求出。四种组合对象的生成函数是相同的,然后可以使用 \(NTT\) 乘四遍。更快的方法是做四遍上面的 DP,每次初值继承上一次的结果即可,不过因为神秘原因不如前者优秀。这个时候得出的东西还要去掉 \(n = 1\) 额外多算的一种,这里也不用使用多项式除法,因为第一项的生成函数是 \(\dfrac{1}{1 - x}\),只需要乘上 \(1-x\) 即可。

Day7

题面

A

\(b_i\) 的实质是 \(i\)\(popcount\) 的奇偶性。对 \(b\) 进行分块,设块长为 \(T\),根据上面的性质如果将 \(2^k\) 个元素分在一个块中,那么本质不同的块只会有两种,证明来自 modinte:

\(b_i = \text{popcount}(i) % 2 = \text{popcount}(i >> k) % 2 \oplus (\text{popcount}(i \text{二进制最后} k \text{位}) % 2)\),每个块内部的 \(\text{popcount}(i >> k) % 2\) 相同,这个东西只有两种;不同块之间的 \(\text{popcount}(i \text{二进制最后} k \text{位}) % 2\) 序列完全相同。

\(f_{i,0/1}\) 表示在序列 \(a\) 中区间 \([i,i + 2^k - 1]\) 和两种块的不同位置数量,\(f\) 可以做到 \(\mathcal O(nT)\) 预处理。查询只需要散块暴力跑,整块用预处理好的偏移量统计答案。考虑上修改操作,一个位置上的 \(a_i\) 修改最多影响到 \(\mathcal O(2^k)\) 个位置,直接暴力修改。取 \(T = 2^k = \sqrt{n}\),总时间复杂度 \(\mathcal O((n + m) \sqrt{n})\)

B

建立一个二维平面,横轴表示序号,纵轴表示权值,问题转化成选取一个左下角和右上角的矩形,问有几种框出点分组不同(点也可以不框)的方法。考虑点卡住了矩形边界的情况才会做出不同的贡献,以卡住边界的点的权值大小为序编号,那么他们在序列一维上的表现为 \(12\)\(132\)\(213\)\(2143\)。前三种都可以转化成第四种,所以先考虑第四种怎么计数。将贡献记在 \(3\) 上,我们从值域一维从小到大做扫描线。这个形式非常不好,再容斥一下变成 \(??43 - 1243\),再标记已经扫过的点为 \(S\),未扫过的点为 \(L\),那么前者求的就是对于每一个位置形如 \(SSL\) 的点对个数,记一个点左下角有多少个点(因为排列的性质这个东西好求)为 \(S^w\),后者求的就是形如 \(S^w L\) 的点对个数,这些东西使用线段树维护分治信息(这个东西的典型应用是区间最大子段和)可以很好处理。那么回过头来看转化,\(12\) 是平凡的,\(132\) 是求形如 \(SL\) 的点对数,\(213\) 是求 \(??3 - 123\)\(SS - S^w\)。因为所有信息都要知道,先都一遍记录下来然后嗯查就好了。线段树做到 \(\mathcal O(n \log n)\)

C

注意到树苗加入和弹出的操作非常像括号串的匹配,转换成括号序来做。对于一个树苗 \(x\),他只会对他弹出后加入的第一个树苗 \(y\) 产生影响,所以我们将一对括号中左括号和右括号被弹出后加入的第一个左括号之间连边,对于只有左括号的括号对,即直到操作最后都留在栈中的树苗,我们建一个虚点 \(n + 1\) 并将前者向它连边,于是我们得到了一棵 \(n + 1\) 个节点的树。考虑这棵树有什么性质:如果有一个点是蓝色,他会把根链上所有点都染成蓝色。

能够发现,加入树苗的顺序相当于树上的 dfs 序的倒序,那么对于一对括号,它在括号序列的左侧部分构成了其在树上的子树,括号之间的部分构成了这个节点在树上的右侧。询问操作相当于把 \([l,r]\) 区间拉出来构成的导出子图进行询问。由此,操作被转化成了树上某个 dfs 序区间的节点颜色反转,查询 dfs 的一个区间中的点构成的森林的答案。这个东西的计算方法是常用套路,构造出这些节点的。如果我们每次查询的都是后缀(这对应着 \(r = n\) 的部分分),那么在树上这部分必然联通,线段树可以轻松维护。但是现在可能并不联通,如果硬做的话每个联通块都要做虚树大小的复杂度,用菊花可以轻易卡飞。我们将 \(l - 1\) 节点的根链拉出来一块构造虚树,这样得到的东西必然联通,证明来自 HMSF:

因为如果不连通的话,一定是顺着这条链的一部分回溯回去的,所以相当于回溯几次再往下 dfs 一次,加入这个根链后一定联通。

最后我们再将答案去掉这部分即可。显然这条链上只有一段前缀是蓝色的,我们只需要找出第一次变蓝的位置。看似需要二分,实则这个节点对应的正是 \(l - 1\)\([l,r]\) 在 dfs 序中最小的蓝点的 LCA。综上所述,我们要做的是区间颜色反转,区间维护两两蓝色的距离,使用线段树做到 \(\mathcal O(n \log n)\)

Day8

题面

A

DP 按列从左往右做,设 \(f_{i,0/1/2,0/1/2,0/1/2}\) 表示做到了第 \(i\) 列,三个 \(L\) 形状的状态,状态分别为还未填/正在填/填完了。

B

solve1:值域不大,直接在数轴上搞。记 \(f_i = 0/1\) 表示数轴上 \(i\) 是否被覆盖,代价有两种:

  • \(f_i = 0,f_{i + 1} = 1\),则代价为 \(A\)
  • \(f_i = 1,f_{i + 1} = 1\),则代价为 \(\min{ \{ A,B \} }\)

如果一个点初始在 \(x\),则有 \(f_{x - d} = 1\)\(f_{x + d} = 1\),可以转化为 \(f_x = 1\)\(f_{x + 2d} = 1\)。考虑对 \(d\) 的大小分治:

  • \(d\) 比较小的时候直接状压 \(2d\) 个位置上的信息然后 DP。
  • \(d\) 比较大的时候按 \(2d\) 大小将数轴分块,然后将这些块竖着罗列起来得到了一个 \((\dfrac{V}{2d} \times 2d)\) 的矩形,现在得到的就是轮廓线 DP 的形式,每次我们填完 \(\mod 2\) 意义下相同的位置即矩形中同一列,需要记录下每一行上连续 \(0\) 的长度,以及填到了第几个 \(1\)

时间复杂度 \(\mathcal O(2^{sqrt{V}} poly(V))\)

solve2:集合划分模型,对于每一个数轴上的下标建一个节点 \(i\),割断 \(S \to i\) 表示这个点没有被覆盖,割断 \(i \to T\) 表示这个点被覆盖。依旧用 \(f_i = 0/1\) 表示数轴上 \(i\)\(01\) 状态是否进行翻转,那么图中有三种限制:

  1. \(f_i = 1\),则有代价为 \(\min{ \{ A,B \} }\)
  2. \(f_i = 0,f_{i + 1} = 1\),则有代价 \(A - \min{ \{ A,B \} }\)
  3. 如果 \(i\) 上有初始点,则 \(f_{i - d} = 0\)\(f_{i + d} = 0\)\(\infty\) 边表示防止割断。

对于一,直接将代价作为 \(i \to T\) 的边流量。第二类和第三类边不能同时存在,因为一个要求 \(f_i\) 相同,一个要求 \(f_i\) 不同。依旧对 \(d\) 分治:

  • \(d\) 比较小的时候依然直接状压 DP。
  • \(d\) 比较大的时候

C

考虑 \(2-SAT\),记 \((x,i)\) 表示兔子 \(i\) 是否在点 \(x\) 上,但是兔子可以存在的是若干个位置,2-SAT 无法表示这些位置上恰好有一个是 \(1\)。如果在序列上,可以转化为一段前缀内是否有一个 \(1\),那么对于树的情况拍到 dfn 序上再使用相同的套路,于是转化成 \((x,i)\) 表示兔子 \(i\) 是否在点 \(x\) 的子树内。

直接子树间暴力建边是 \(\mathcal O(Qn^3)\),可以使用前缀和优化。

首先建前缀点内部的连边是 \(\mathcal O(n)\)

  • 设一个点有 \(k\) 个儿子,第 \(k\) 个儿子为 \(son_k\),对于每个 \(x\)\(k\) 个点 \(p_k\) 表示兔子是否居住在前 \(k\) 个儿子中,再建一个 \(p_0\) 表示兔子是否居住在 \(x\),然后在充分关系下连边。
  • 如果居住在 \(k\) 上,即 \(son_k = 1\),则有 \(\{ son_k = 1 \} \to \{ p_k = 1 \}\) 表示出现了居住,前缀和变成了 \(1\);还有 \(\{ son_k = 1 \} \to \{ p_{k - 1} = 0 \}\),因为一个兔子只能在一个位置居住,这个位置有了那前缀上的其他位置都必然没有。
  • 如果 \(p_{k - 1} = 1\) 即改点前面的子树中已经有居住,那么有 \(\{ p_{k - 1} = 1 \} \to \{ son_k = 0 \}\),即后面的节点的子树都不能居住了;这个点的前缀同样标记出现居住状态,显然有 \(\{ p_{k - 1} \} \to \{ p_k \}\)
  • 如果出现了 \(p_{k - 1} = son_{k} = 0\) 但是 \(p_{k} = 1\),这种情况依然合法,因为我们可以判定为其居住在 \(x\) 上。

建完前缀上的节点后就可以进行 2-SAT 了。将限制转化为三项,以题目中的变量为基准,设此时以 \(x\) 为根:

  • \(a\) 和 点 \(b\) 不在同一子树内。
  • \(r\)\(a\) 不在同一子树内。
  • \(r\)\(b\) 不在同一子树内。

需要找到对于每个兔子 \(i\) 他具体居住在哪一个子树 \(x\) 内,使用换根意义下的 \(x\),以 \(1\) 为根一遍 dfs 处理完后,如果进行换根后没有子树改变那么就是 \((x,i)\),否则可以用补集表示新的子树,即 \(\neg (x,i)\)。搭配使用上面的前缀点优化,连边是平凡的,这部分是 \(\mathcal O(Qn)\)。总边数为 \(\mathcal O(Qn^2)\),时间复杂度 \(\mathcal O(n + m + Qn^2)\)

Day9

题面

A

solve1:容易算出总方案数,答案减去不连通的情况即可。不连通的话可以检查 \(1\) 所在的连通块的状态。设 \(f_{S,i}\) 表示钦定 \(S\) 连通,其中 \(1\)\(S\) 中,且选了 \(i\) 条边的总方案数,先暴力容斥,记边两个端点都在点集 \(T\) 中的边的数量为 \(cnt_T\),转移式子为:

\[f_{S,i} \]

B

C

多次查询一个区间的 \(\mathcal Z\) 函数的和。设 \(\mathcal L(i,j)\) 为原串后缀 \(i\)\(j\) 的 LCP,答案即为 \(\sum_{i = l}^r \min{(r - i + 1,\mathcal L(l,i))}\)。注意到将原串翻转后建立 SAM,fail树上 \(i\)\(j\) 的 LCA 的长度即为 \(\mathcal L(i,j)\)

Day10

题面

A

二分答案,使得问题转化成所有连续段的长度不超过二分得到的 \(len\)。事实上我们在固定 \(len\) 的长度下,总共的 \(0\) 的数量实际上是一个区间,证明如下:

  • \(s^{max},s_{min}\) 表示 \(0\) 的数量最多/少时的一种合法方案,\(a^{max},a^{min}\)\(0\) 的最多/少数量。
  • 枚举一个 \(i\),将 \(s^{min}\) 的前 \(i\) 个字符和 \(s^{max}\) 的后 \(n - i\) 个字符拼在一起,当 \(i\) 移动的时候,\(0\) 的数量最多变化 \(1\),并且这个数量一定处于 \([a^{min},a^{max}]\) 之内。
  • 这样仍有可能出现连续段长度大于 \(len\) 的情况,即 \(s_{i}^{min} = s_{i + 1}^{max}\)。考虑暴力跳过这些位置,剩下的位置里必定有解。

于是转化成了求 \(0\) 的数量最少/多是多少。设 \(f_{i,0/1}\) 表示当前在位置 \(i\),最后一段是 \(0/1\) 且所有连续段的长度小于 \(len\) 的情况下 \(0\) 的总数量最少是多少。转移是枚举当前连续段的终点,转移方程为:

\[f_{i,0} = \min_{j = i - len}^{i - 1} f_{j,1} + (i - j) \\ f_{i,1} = \min_{j = i - len}^{i - 1} f_{j,0} \\ \]

直接做是 \(\mathcal O(n^2)\) 的,可以用单调队列优化到 \(\mathcal O(n \log n)\)。构造的方法根据上面的证明,我们在 DP 的时候记一个 pre 表示是从什么位置转移来的,然后暴力枚举每一个合法的 \(i\) 拼在一起即可。

答辩分讨也能过,感到十分神秘。

B

区间要么完全包含,要么不交,所以所有的区间构成了一个树的结构。在母线段中填入一个子线段时有一下三种选择:

  • 填在母线段的子线段的子线段中。
  • 填在母线段左右两端空余出来的部分。
  • 填在母线段的另外两个子线段之间。

\(f_{i,j,0/1,0/1}\) 表示当前在 \(i\) 上,子树里面要填 \(j\) 个线段,线段 \(i\) 的左/右线段有没有填线段。设 \(g_{i,j,0/1}\) 表示考虑了前 \(i\) 个儿子,目前填了 \(j\) 个区间,填完第 \(i\) 个儿子后余出的区间有没有被填。由于要保证每一个区间都选择了子区间,所以记一个区间的子树大小为 \(siz_i\),那么这个区间最多被划分为 \(2 \times siz_i\) 个连续段,因此 \(f\)\(j\) 一维的大小限制为 \([siz_i,2 siz_i]\)。转移方程类似于树形背包,时间复杂度做到 \(\mathcal O(n^2)\)

C

Day11

题面

A

B

Day12

题面

A

B

C

posted @ 2023-04-17 15:16  LgxTpre  阅读(60)  评论(0编辑  收藏  举报