Solution Set #6

贺的以前的。

122.【ZJOI2019】语言

题意: 给定 \(n\) 个点的树以及 \(m\) 条路径。求有多少无序点对 \((u,v),u\ne v\) 满足存在一条路径同时包含 \(u,v\)

考虑对于每个点 \(u\) 统计答案,先把无序的条件去掉,最后再除以二。问题转化成包含 \(u\) 的路径并的大小。

这个会形成一个连通块,满足这是原图的一棵联通子树。这个连通块的性质是,包含它的路径端点会是叶子节点。考虑称呼这些节点为关键点。

由于这些链都交到 \(u\),两两可达。所以可以用关键点导出一个极小联通子图,包含所有关键点。和虚树类似。

假设我们已知这些关键点,我们要求这个子图上点的个数。鉴于这玩意是树,所以也可以是算边的个数。

定理:
对于树上的一个点集 \(S\),设其元素按照 dfs 序排序后分别为 \(a_1,a_2,\cdots,a_k\),那么其生成的极小连通子图的边数为:

\[|E_k|=\sum_{i=1}^k \operatorname{dep}({a_i})-\sum_{i=1}^{k-1}\operatorname{dep}({\operatorname{lca}(a_i,a_{i+1})})-\operatorname{dep}({\operatorname{lca}(a_{1\sim k})}) \]

证明: 这个式子的等价形式是:

\[|E_k|=\dfrac{\sum_{i=1}^k \operatorname{dis}(a_i,a_{i+1})}{2} \]

其中 \(a_{k+1}=a_1\)

按照 \(\text{dfs}\) 序去遍历 \(S\) 的所有点,也就是按照序列 \(a\) 的顺序,会将这个子图中的每条边经过恰好两次。

考虑统计对 \(x\) 产生影响的路径。可以树上差分,回忆如何实现一条链 \(+1\)

对每个点开桶,在 \(u,v\) 的桶 \(+1\),在 \(\operatorname{fa}(\operatorname{lca}(u,v))\) 以及 \(\operatorname{lca}(u,v)\) 的桶 \(-1\)

对于每一个点,我们考虑用桶来存储 \(m\) 条路径对所有点的覆盖情况。每次会涉及合并两个桶,但是由于桶操作的次数是 \(O(m)\) 的,所以很多桶都是空的。

考虑动态开点线段树维护。这个 trick 在 [NOI2020] 命运 中也出现过。

注意到那个统计方式是和 dfs 序相关的,点的标号就是没用。考虑对一个点 \(u\) 维护一个下标为 \([1,n]\) 的线段树表示桶,一个位置 \(u\) 的值 \(\ge 1\) 就说明 dfs 序为 \(u\) 的点 \(u^{\prime}\) 有关键点。

回到 Lemma 1 的那个式子,考虑节点区间 \([l,r]\) 表示 dfs 序为 \([l,r]\) 的所有关键点构成的虚树大小。

此时考虑信息合并。

节点与节点信息的合并,还需要维护左子最后一个关键点,右子最前一个关键点的 LCA。以及所有点的 LCA 和关键点深度和。

因此还需要维护,dfs 序在 \([l,r]\) 中关键点,dfs 序最小和最大的节点,同时维护所有关键点的深度和,以及所有关键点的 LCA。

同时需要支持查询原树上的 LCA。

考虑 \((u,fa)\) 的桶的合并。

直接将儿子节点和父亲节点的线段树合并即可,合并的均摊复杂度为 \(O(n\log n)\)。线段树维护自带 \(\log\),如果用树剖或者倍增求 LCA,会多一个 \(\log\)

使用 \(O(n\log n)-O(1)\) 求 LCA,总时间复杂度 \(O(n\log n)\)

123. 「HNOI2019」校园旅行

题意: 给定 \(n\) 个点,\(m\) 条边的无向图,每个点上有字符 0 或 1。\(q\) 次询问两点间是否存在路径,使其经过的字符组成回文串。\(n\leq 5000,m\leq 5\times 10^5,q\leq 10^5\)

回文串删掉首尾仍然回文。即存在边 \((u,x),(y,v)\)\(x,y\) 存在回文路径,那么 \(u,v\) 也存在回文路径。

考虑初始状态是长度为 \(1,2\) 的回文串。从初始状态 BFS 能得到所有的回文路径。我们只关心起终点是否合法,状态是 \(O(n^2)\),可以预处理答案。但是转移复杂度 \(O(m^2)\),需要优化。

事实上很多边都是没有用的。

考虑一个字符相同的大小至少为 \(2\) 的连通块,如果两节点间存在长为 \(k\) 的路径,随便走一条连通块内的边,再走回来,就得到了长为 \(k+2\) 的路径。那么长度足够大且和 \(k\) 同奇偶的途径都存在。

可以推导出一个结论,如果 \(x,y\) 之间存在两条长度不同奇偶的路径,那么任意足够长的路径都存在。

路径奇偶性的特殊性质可以想到用二分图求解。

二分图任意两个节点间的所有路径的奇偶性是一样的,非二分图因为存在奇环所以可以套环然后改变奇偶性。

考虑留下这张二分图的生成树,边数是 \(O(n)\) 的。这样做之所以对,是因为长度小的路径虽然没了,但是长度足够大的且与原图路径奇偶性一致的路径仍然存在。无法保证最短,但是可以保证存在性。

类似地,非二分图可以精简为生成树加一个奇环。

考虑所有两端点字符不同的边,必然构成二分图,同样取生成树即可。

边数降低到 \(O(n)\),然后跑 BFS,时间复杂度 \(O(n^2)\)

124. 「BJOI2019」奥术神杖

Solution Set #4 写了。

125.「联合省选 2020 B」丁香之路

题意: 给定 \(n\) 个点的无向完全图,节点 \(u,v\) 之间有长度为 \(|u-v|\) 的边。给定起点 \(s\)\(m\) 条“必经边”。对 \(i=1,2,\cdots,n\),问从节点 \(s\) 出发,节点 \(i\) 结束,且经过每条“必经边”至少一次的路径的最小长度。\(n\leq 2500,m\leq \frac{n(n-1)}{2}\)

首先 \(m\) 条“必经边”的长度肯定要全部加起来算进答案,考虑连一个 \(i\to s\) 的边权 \(0\) 的边,形成回路。接下来相当于要加总长尽量短的边使得存在 \(s\)\(i\) 的欧拉路径(允许重边)。

先加入 \(m\) 条必经边以及虚边,得出现在的度数。我们要求所有点都是偶度点且图联通才能存在欧拉路径。先不考虑联通的性质,先处理掉所有连通块中的度数限制。

对于一个连通块,度数总和为偶数,因此有偶数个奇度点。
为了连边尽量短,找出的节点只连一条边。

结论显然,按照标号排序之后,\(a_{2k}\)\(a_{2k-1}\) 的奇度点连边使其成为偶度点。

这样做是因为边权的特殊性。由于边权的特殊性,如果把 \((x,y)\) 的连边视作区间 \([x,y]\),有交的区间一定可以通过调整为不交的区间得到更小的总长。区间互不相交只有一种情况,就是把找出的节点按标号排序,然后两两一组连边。

欧拉路径还要求连通。此时度数仍是 \(0\) 的孤立点直接忽略掉。

前面我们已经将 \(s,i\) 连了 \(0\) 边权的边。现在问题变成求使若干个连通块连通所需的边最小长度和,即最小生成树,注意新加入的边答案要 \(\times 2\),欧拉路径可以重,要有往返。

然后跑最小生成树,注意去掉没用的边:只有连接标号相邻的非 \(0\) 度数点的 \(O(n)\) 条边有用。

时间复杂度 \(O(n^2\log n)\)

126.「IOI2021」分糖果

Solution Set #4 写了。

127. 【ZJOI2022】众数

Solution Set #4 写了。

128.「AHOI2022」山河重整

题意: 求有多少 \(S\in\lbrace1,2,\cdots,n\rbrace\),满足 \(\lbrace1,2,\cdots,n\rbrace\) 是【\(S\)\(01\) 背包集合】的子集。\(n\leq 5\times 10^5\)

先考虑如何判定一个集合 \(S\) 合法。考虑对于 \(\forall 1\leq x\leq n\),要求 \((\sum_{j\in S ,j\leq i} j)\ge i\)

不难想到 DP:对于 \(f_{i,j}\)\([1,i]\) 中选取 \(S\) 可以组成 \([1,j]\) 的所有数,这个状态基本不可优化,时空复杂度均为 \(O(n^2)\)

正难则反。

考虑不合法的状态较多,主要是不满足 \((\sum_{j\in S ,j\leq i} j)\ge i\) 的条件。考虑优化成,\(f_x\) 选出和为 \(x\) 且符合对于 \(1\leq i\leq x\) 满足上述条件的方案数。隐含的条件是不选取 \(x+1\)

这样仍然难以计算,考虑去除可以表示 \([1,x]\) 的条件。先计算选取若干不同数和为 \(x\) 的方案数,容易用背包计算。注意到互不相同,所以最多选取 \(O(\sqrt n)\) 个数。这样容易做到 \(O(n\sqrt n)\)。具体实现就是倒序枚举选出数的数量,然后跑背包。

考虑加上必须表示出 \([1,x]\) 所有数的条件。令之前求出来那个和为 \(x\) 的选取方案数为 \(g_x\)

容斥计算,写出 \(f_x\) 的表达式:\(g_x-\sum_{y<x}p(x,y)f_y\),其中 \(p(x,y)\)\([y+2,x]\) 中选取若干个和为 \(x-y\) 的方案数。此时 \(y+1\) 被完美跳过,就寄了。也就是说 \([1,y]\) 都可以被表达。不难发现这样可以覆盖所有的情况。

令所有不合法但是和为 \(x\) 的集合的方案数为 \(b_x=g_x-f_x\)。考虑计算 \(b_x\)。运用拆贡献的思想,考虑 \(f_y\)\(b_x\) 的贡献。就是说 \(f_y\)\(f_x\) 的贡献的时候其余元素都要 \(\ge y+2\),并且 \(x\ge y+(y+2)=2y+2\)。枚举在 \([y+2,x]\) 集合中有 \(k\) 个数。考虑将 \(f_y\) 贡献到背包的 \(y+(y+2)\times k\) 处作为初值,然后再跑完全背包。

注意到先要求解 \(\frac{n}{2}\) 以下的 DP 值,考虑进行 CDQ 分治。时间复杂度 \(T(n)=T(\frac{n}{2})+O(n\sqrt n)=O(n\sqrt n)\)

129.「AHOI2022」钥匙

Solution Set #4 写了。

130.「联合省选 2022」填树

Solution Set #4 写了。

131.「ZJOI2022」树

题意: 生成两棵 \(n\) 个节点的树 \(T_1,T_2\):第一棵树的生成方式是:节点 \(1\) 作为树的根,对于 \(i \in [2, n]\),从 \([1, i - 1]\) 中选取一个节点作为 \(i\) 的父亲。第二棵树的生成方式是:节点 \(n\) 作为树的根,对于 \(i \in [1, n - 1]\),从 \([i + 1, n]\) 中选取一个节点作为 \(i\) 的父亲。九条可怜希望对于任意 \(i \in [1, n]\),若第一棵树中的节点 \(i\) 为叶子,那么第二棵树中的节点 \(i\) 为非叶子;若第一棵树中的节点 \(i\) 为非叶子,那么第二棵树中的节点 \(i\) 为叶子。对于所有 \(1\leq n\leq N\),统计生成两棵树的方案数是多少,任意模数。\(2 \le N \le 500\)

直接 DP 的复杂度是上天的。大概要用第一维度记录前 \(i\) 个节点,然后需要分别用两个维度描述两棵树。大概会生成一个 \(O(n^5)\) 状态的 DP,而且是跑满的。

而且这个 DP 不可优化,问题出在了:非叶子的限制条件很强,不好直接用 DP 做。

令全集 \(U=\lbrace 1,2,\cdots n\rbrace\)。考虑用容斥的角度。先着眼于一棵树的情况。

考虑 \(f(S)\) 表示 \(S\) 恰好为 \(T_1\) 叶子集合的方案数。依然不好做,考虑容斥。考虑令 \(F(S)\) 表示 \(T_1\) 叶子集合包含于 \(S\) 的方案数,由容斥原理容易有:

\[f(S)=\sum_{S\subseteq T}(-1)^{|T|-|S|}F(T) \]

同理设 \(g(S),G(S)\)\(T_2\) 的方案数。

题目相当于问

\[\sum_{S\cup T=U, S\cap T=\emptyset} f(S)g(T) \]

然后就是拿容斥展开。

\[=\sum_{S\subseteq U}\left(\sum_{S\subseteq P}(-1)^{|P|-|S|}F(P)\right)\times \sum_{(U\setminus S)\subseteq Q}\left((-1)^{|Q|-|U\setminus S|}G(Q)\right) \]

\[=\sum_{S\subseteq U}\left(\sum_{S\subseteq P}(-1)^{|P|-|S|}F(P)\right)\times \sum_{Q\subseteq S}\left((-1)^{|U\setminus Q|-|U\setminus S|}G(U\setminus Q)\right) \]

\[=\sum_{P\subseteq U,Q\subseteq U}\left(F(P)G(U\setminus Q)\sum_{P\subseteq S\subseteq Q}(-1)^{|P|-|S|+|S|-|Q|}\right) \]

\[=\sum_{P\subseteq U,Q\subseteq U}\left(F(P)G(U\setminus Q)(-2)^{|P|-|Q|}\right) \]

\(F(S)\) 表示 \(T_1\) 叶子集合包含于 \(S\) 的方案数,\(G(S)\) 同理。

此时对着这个式子考虑 DP 加速计算就很容易了。就是要动态更新 \(F,G\),也就是钦定叶子节点的信息。

\(1\to n\) 进行 DP,放入 \(P\) 即为钦定为 \(T_1\) 叶子节点,\(U\setminus Q\) 即钦定为 \(T_2\) 叶子节点。

考虑令 \(f_{i,j,k}\) 表示:前 \(i\) 个点中 \(j\) 个点钦定是 \(T_1\)自由选取节点(不属于 \(P\)),后面 \(n-i\) 个点中 \(k\) 个点是自由选取的(即属于 \(Q\),“钦定”的意思就是不对补集做要求,真正的答案已经被容斥系数容斥出来了)。

初始状态,\(f_{1,1,i}=i\),表示 \(1\) 号节点在 \(T_2\) 的父亲有 \(i\) 种。

考虑转移。前 \(i-1\) 个节点都已经确定了。我们需要考虑 \(i\) 号节点所属的集合。

考虑枚举 \(i\) 号节点的状态:

  • \(i\in P,i\in(U\setminus Q)\),即 \(i\in P,i\notin Q\),即 \(i\)\(T_1\) 的叶子节点,\(T_2\) 的叶子节点。
  • \(i\notin P,i\in(U\setminus Q)\),即 \(i\notin P,i\notin Q\),即 \(i\)\(T_1\) 的自由节点,\(T_2\) 的叶子节点。
  • \(i\in P,i\notin(U\setminus Q)\),即 \(i\in P,i\in Q\),即 \(i\)\(T_1\) 的自由节点,\(T_2\) 的叶子节点。
  • \(i\notin P,i\notin(U\setminus Q)\),那你在搞笑,对 \(F,G\) 都没有贡献,故不讨论。

对于三种情况,从 \(f_{i-1,j,k}\) 向外转移,转移系数同时考虑容斥系数以及在 \(T_1,T_2\) 的父亲节点选取方式即可。

  • \(i\)\(T_1,T_2\) 的叶子节点,转移到 \(f_{i,j,k}\),系数是 \(-2jk\)\(-2\) 是因为 \(|P|-|Q|\) 变大了 \(1\),造成容斥系数 \(\times (-2)\)
  • \(i\)\(T_1\) 的叶子节点,\(T_2\) 的自由节点,转移到 \(f_{i,j,k-1}\),系数是 \(j(k-1)\)
  • \(i\)\(T_2\) 的叶子节点,\(T_1\) 的自由节点,转移到 \(f_{i,j+1,k}\),系数是 \(jk\)

答案统计就是只用在 \(T_2\) 留下一个根就行了,考虑 \(i\)\(T_1\) 可以接到哪里即可。

\[\operatorname{ans}_i=\sum_{j=1}^i f_{i,j,1}\times j \]

时间复杂度 \(O(n^3)\)

132.「SDOI / SXOI2022」小 N 的独立集

给你一个 \(n\) 个点的树,然后每个点的点权是 \([1,k]\),求这个树最大独立集是 \(x\) 的方案数(对于所有 \(x∈[1,nk]\) 求解)。\(1\leq n\leq 1000,1\leq k\leq 5\)

dp 的时候,我们一般会设计一个 dp 状态,然后让 dp 从某个状态向某个状态转移,最终统计某些状态最终的值。
在 dp套dp 里面,我们就将内层 dp 的结果作为外层 dp 的状态进行 dp。

在本题中,对于最大权独立集,有 dp 状态为 \(f_{u,0/1}\) 表示 \(u\) 是否选入集合。

有如下转移:

\[g_{u,0}=\max(f_{v,0},f_{v,1})+f_{u,0},g_{u,1}=f_{u,1}+f_{v,0} \]

于是考虑 dp套dp,就是设 \(dp_{u,x,y}\) 表示使得 \(f_{u,0}=x,f_{u,1}=y\) 的独立集的选取方案数。

转移就是考虑子树合并,有:

\[dp_{u,x,y}\times dp_{v,p,q} \to g_{u,x+\max(p,q),y+p} \]

状态数就是 \(O(n^2k^2)\) 的,时间复杂度为 \(O(n^3k^2)\),卡卡常可能有 \(80\) 分,主要是跑不满。

这个状态没前途。主要是我们存储了太多的无效 dp 状态。

假设 \(p\ge q\),那么转移可以直接写成 \(g_{u,x+p,y+p}\),无论 \(p\)\(q\) 大了多少,\(q\) 的值都是无意义的。

我们需要换一个内层 dp 状态。

内层 dp 改成 \(f_{x,0/1}\) 表示 \(x\) 是否强制不选。

有内层 \(f_{u,0}\leq f_{u,1}\leq f_{u,0}+k\)。就是考虑 \(q-p\) 就多一个 \(u\) 的点值。

考虑 \(dp_{u,x,d}\) 表示 \(f_{u,1}=x,f_{u,0}=x+d\) 的方案数。

考虑合并 \(dp_{u,x,p},dp_{v,y,q}\)。当 \(u\) 不选时,\(v\) 可选可不选;当 \(u\) 选时,强制 \(v\) 不选。

有转移:

\[dp_{u,x,p}\times dp_{v,y,q} \to g_{u,x+y+q,\max(q-p,0)} \]

解释:不选 \(u\)\(v\)\(x+y+q\);选 \(u\) 不选 \(v\)\(x+p+y\),取差即可。

注意结合子树大小求解,复杂度类似树上背包。时间复杂度 \(O(n^2k^3)\),跑不满。

133. 「联合省选 2022」卡牌

子集覆盖方案数是 NPC 问题,别去想 \(\operatorname{polylog}\),差不多得了。考虑这道题的性质。

注意到很小的值域,考虑对质因子根号分治后小质数会很少。考虑对质数分为两类,\(\leq \sqrt {2000}\) 的和大于的,分别称为小质数和大质数。

注意到 \(43\times 47>2000\),所以 \(43\) 可以被放到大质数。

这样做的好处是每个数中最多有且仅有一个大质数(注意特判 \(43^2\),这个和 \(43\) 本身就是等价的。),而小质数的好处是一共集合大小只有 \(13\)

\(A=290,B=13\),分别为大质数和为小质数的集合大小。

提取出询问集合中所有的小质数,记录为集合 \(S\)。合法集合中,大质数都要出现,小质数或起来是 \(S\) 的超集。

对于每个大质数,预处理 \(f_{i,S}\) 表示大质数给定下,前 \(i\) 个数,小质数集合恰好为 \(S\) 的方案数。

记录 \(T\) 的出现次数 \(c\),然后考虑对于一个小质数集合 \(T\) 的转移:

\[f_{i,S}=\sum_{P\cap Q=S}f_{i-1,P}\left( [Q=\emptyset]+[Q=T]\right)(2^c-1) \]

注意到这是一个或卷积的形式,可以用 FMT 优化求,对于一组大质数可以做到 \(O(B2^B)\) 的复杂度。

考虑询问,小质数求下超集和就行。

考虑每选中一个大质数,就是钦定在大质数集合不能选空集,所有卷过的点值都要 \(-1\)

考虑先去掉这个集合的贡献,\(-1\) 后再乘回来。

通过原先取到 \(S\) 为小质数集合的方案数 \(f_S\) 来更新即可。

时间复杂度 \(O((\sum_{c_i}+mB)2^B)\),容斥做法简单得多。

134.「WC2023 / CTS2023」楼梯

本题最巧妙也是最关键的一步转化:考虑用轮廓线描述这个楼梯。

轮廓线描述时,考虑令 \(1\) 表示向下,\(0\) 表示向左。这样得出的是一个 \(01\) 序列。

再思考一下,最棘手的是询问操作。

考虑处理查询。考虑令轮廓线的 01 序列为 \(s[1:n]\),子楼梯事实上就是 01 序列上的一段区间 \([l,r]\),边界格数就是区间内 \(1\) 的个数加上 \(0\) 的个数,一共要求有 \(q\) 个。问题等价于寻找 \(r-l=q\),满足 \(s_l=1,s_r=0\)

注意到题目中 \(q\mid n\) 的特殊性质。

如果不存在答案,就是让所有 \(1\) 的位置 \(+q\) 仍然为 \(1\),但是 \(s_1=1,s_n=0\) 说明了这是不可能的。

所以 \(q\mid n\) 是一定有解的。

这启发我们,在 \(s_1=1,s_n=0\) 的性质上做点事情。考虑提取出序列 \(s_1,s_{1+q},s_{1+2q},\cdots,s_n\)。在这里面寻找答案。其中 \(s_1=1,s_n=0\)

从后往前找,如果倒数第二位为 \(1\),那么有解;否则考虑倒数第三位。

优化查找过程,考虑二分答案。

记当前二分到了第 \(x\) 位,如果第 \(x\) 位为 \(1\),那么右边一定有满足的,反之亦然。

此时考虑怎么维护这个轮廓线,注意到 \(a\leq 10^9\),并且修改关于行的很多,其实可以考虑以行,也就是序列中的 \(1\) 去思考。

设原本有无穷多个 \(1\)。对于轮廓线序列的修改:

第一种操作是在第 \(a\)\(1\) 后面加入 \(b\)\(0\)

第二种操作是去掉最后 \(b\)\(0\)(可能更少),然后在第 \(a\)\(1\) 后面加入 \(b\)\(0\)

这个楼梯的轮廓线可以通过维护相邻两个 \(1\) 之间有多少个 \(0\) 完成。前三种修改操作可以通过可持久化以及线段树二分完成。

每次二分答案都可以在 \(O(\log V)\) 的时间判定是否合法,时间复杂度 \(O(n\log^2 V)\)

135. 「春季测试 2023」密码锁

\(k=1,2\) 的情况是容易的。

看到最小化最大值,可以去想二分答案 \(x\) 是否可行。

考虑 \(k=3\) 的做法。钦定全局最大值在第 \(0\) 行,设全局最小值在第 \(R\) 行。设两个最值分别为 \(mx,mn\)\(R=0\) 时一定不优,因此 \(R\in[1,2]\)

考虑限制条件:第 \(0\) 行要求 \(a_{0,i}\in[mx-x,mx]\)。第 \(R\) 行要求 \(a_{R,i}\in[mn,mn+x]\),剩余行 \(T\neq R,T>0\) 要求 \(a_{T,i}\) 极差 \(\leq x\)

枚举当前列 \(B\) 转了 \(p\in[0,2]\) 次,产生新的三元组,也就是新的 \(0,1,2\) 行在第 \(B\) 列。考虑在第 \(0,R\) 行符合条件时,第 \(T\) 行备选的值就已经产生。

鉴于判定是关于值域上的极差,可以对于每个值 \(x\) 进行考虑,我们记录 \(x\) 可以出现在第 \(T\) 行的哪些列,然后找一个值域区间 \([l,r]\),使得这里面的所有位置的并恰好是 \(\lbrace 1,2,\cdots,n\rbrace\)

可以双指针维护这个长度 \(=x\) 的滑动窗口。时间复杂度 \(O(n\log A)\)

\(k=4\) 依然是考虑二分答案,钦定全局最大值在第 \(0\) 行,设全局最小值在第 \(R\) 行。设两个最值分别为 \(mx,mn\)\(R=0\) 时一定不优,因此 \(R\in[1,3]\)

但是剩下的备选点对是两个,记录为 \((P,Q)\),设当前是第 \(i\) 列。考虑剩下两个未出现的行分别是 \(t_1,t_2\)

那么将 \((P,Q)\) 设为一个颜色为 \(i\) 的点,我们需要判定是否存在一个 \(x\times x\) 的矩形可以覆盖所有的 \(n\) 个颜色。

\(k=3\) 是所以容易是因为要判定的不是矩形,是一条线。

点去找矩形是个很困难的事情,考虑将点转化成长度为 \(x\) 的正方形。

考虑将所有的点 \((P,Q,i)\) 转化为颜色为 \(i\),左下角为 \((P-x,Q-x)\),右上角为 \((P,Q)\) 的矩形。我们要做的是找一个点,使得其被 \(n\) 种颜色覆盖。

求出矩形后,第一反应是从左到右扫描线,线段树维护当前线上每个点被多少种区间覆盖,以及全局最大值,如果在某一时刻全局最大值为 \(n\) 那么就存在那个被 \(n\) 种颜色覆盖的点,判定 \(x\) 合法。
我们需要矩阵并和在矩阵并后的图形上整体 \(+1\)。但是直接维护是错的,很难去重。

考虑到每次转了 \(k=4\) 次,对于一种颜色会产生最多 \(4\) 个不同点对。那么我们要想保证每次时刻每个维护的都恰好覆盖了一次。考虑对每种颜色再分 \(4\) 类。

对于一种颜色,可能存在一个点被不同类别相同颜色的矩形覆盖多次,而我们需要每个点在同种颜色覆盖且只被一个矩形覆盖。我们需要去除重复的矩形。

对横轴扫描线一下,拆成 \(4\) 个矩形即可。

然后再进行扫描线就不会有重复,用线段树维护即可。

时间复杂度 \(O(kn\log^2 A)\)\(A=3\times 10^4\) 为值域。实现时可以离散化所有出现的数。

136.「NOI2023」贸易

二叉树本身就是一个非常优秀的分治结构。

对于任意两个点 \(u,v\),一定会经过其 LCA。考虑在 LCA 处计算答案。也就是钦定 LCA 为 \(u\),考虑 \(x\)\(u\) 左子树以及 \(u\)\(v\) 在其右子树以及 \(u\) 的所有点对 \((x,y)\) 的答案。

然后就随便算了。就是分别计算能到达左子树多少个点,右子树多少个点,分别到达不了多少点,和分别的最短路和。随便算就出来了。

直接跑最短路的复杂度是错的,因为可能算到子树外面去,这是无意义的。

考虑优化,只子树内的点所连的边,然后再跑最短路。每个点和边都只被访问 \(O(n)\) 次(考虑其祖先),所以 dijkstra 算法产生的总复杂度为 \(O(n^22^n)\)。这里认为 \(m=O(2^n)\)

137.「SNOI2024」树 V 图

动态的,不确定的问题通常是困难的。常见的思想是从简单的问题开始研究,我们考虑当 \(k\) 个关键点都确定了之后怎么去求 \(f(u)\)。显然可以用 dp 求解,因为有 \(f(a_i)=i\),我们不关心怎么求的,但是我们可以发现一个点的 \(f(u)\),如果 \(u\) 不是关键点,只能从邻域节点中选一个 \(x\),将其变成 \(f(x)\)。选的那个 \(x\),可以让 \(u\rightarrow a_{f(u)}\) 的路径与 \(x\rightarrow a_{f(x)}\) 基本重合,除了边 \((u,x)\)。如果考虑将关键点向外做贡献,也就是谁的 \(f(x)\) 是这个点,应该是一个染色的过程。

说了这么多,其实我们可以发掘出,对于相同的 \(\textbf{\textit{f}}\textbf{(}\textbf{\textit{u}}\textbf{)}\) 的值,应该构成有且仅有的一个联通块。

而每个连通块可以缩成一个点,我们只需要从每个连通块中选一个点作为这个颜色的关键点,我们需要将一堆颜色的关键点组合起来,让 \(f(u)\) 的取值序列恰好满足题目要求。考虑这样建立一棵新的重构树。

不难想到令 \(f[u][x]\) 表示以 \(u\) 为根的子树内的染色方案中,要求 \(u\) 节点的关键点取在原树的 \(x\) 号节点。我们可以通过求 \(\text{LCA}\) 的深度去快速求解树上两点间距离。

考虑转移:合并两个子树。我们显然不能全加上,需要判定非法情况。具体就是在新树上记录 \((x,y)\) 表示 \((u,v)\) 颜色的相接是通过原来树的 \((x,y)\) 边相接的。只要 \(x,y\) 分别都满足 \(f(x)=u,f(y)=v\) 即为合法。

时间复杂度 \(O(n^2)\)

138.【WC2024/CTS2024】水镜

容易发现对于定的 \(u\),对应最大的 \(v\) 具有单调性。那么可以双指针维护,\(O(n)\) 次判定区间是否合法。

先考虑判定一个序列是否合法。

考虑 \(L\) 的取值范围能否被取到。将每个数染成红色或者蓝色。选择原来的称之为红色,选择镜像的称之为蓝色。

容易发现,\(L\) 的取值范围只与所有相邻的数对有关。考虑相邻两个的大小关系:

  • 红色相邻要求 \(a_i<a_{i+1}\)
  • 蓝色相邻要求 \(a_i>a_{i+1}\)
  • 红蓝相邻要求 \(a_i+a_{i+1}<2L\)
  • 蓝红相邻要求 \(a_i+a_{i+1}>2L\)

这样你就得到了 \(O(n)\) 个不等式。考虑转化成:所有红蓝对中,\(2L>\max(a_{i}+a_{i+1})\),所有蓝红对中,\(2L<\min(a_i+a_{i+1})\)。刻画成 DP 的形式,是分别最小化和最大化那两个东西。我们希望红蓝的 \(a_i+a_{i+1}\) 中最大的那个尽量小,蓝红中最小的那个尽量大。

(感受一下)注意到合法方案中 \(\min\)\(\max\) 可以同时取到。打表了确实对的。所以是相互独立的。

最优化问题转而用 dp 解决,设 \(f_{i,0/1}\) 以及 \(g_{i,0/1}\) 分别表示 \(i\) 点取原来的还是镜像的,红蓝对和的 \(\min\) 以及蓝红对和的 \(\max\)。可以写出来转移,需要对 \(a_i\) 以及 \(a_{i+1}\) 的大小关系分类讨论。

然后用动态 DP 来做,就是刻画成矩阵形式,扔到线段树上。注意到 \((\min-\max)\) 矩阵和 \((\max-\min)\) 矩阵具有结合律。大概就是 \(\max-\min\) 和顺序没关系,其具有分配律。

因此直接把 dp 改成两组列向量,然后线段树维护矩阵就行了。

时间复杂度 \(O(n\log n)\)

139.【WC2024/CTS2024】线段树

考虑将 \(\lbrace 1,2,\cdots,n\rbrace\) 分成若干个集合。

  • 按照所有区间的覆盖情况进行分类,可以用异或哈希(对每个区间赋一个随机权值)进行分类。那么想要得到 \(m\) 个区间的和,需要得知每个集合中所有的数的和。这样就会分成若干集合,可能有一个未被所有数覆盖的集合。考虑线段树的结构的特性。一个标记的节点会管辖一些叶子节点,但是会有重复。

  • 考虑将单点 \(u\):“祖先中自下而上第一个标记结点”相同的点分在一个集合中。

  • 注意到第一种分类方式中不同集合的 \(x,y\) 在第二种分类方式中不能分在同一集合,就是说要进一步拆分。

这么做之所以是对的,是因为一个集合的和是由某些互不相交的标记节点的和确定的,必要性得证。而一个节点的管辖叶子不只来自于一个集合时,无法得到唯一的和,充分性得证。

考虑树上 DP。对某个点 \(u\),确定了它的子树的选择情况(每个节点去选叶子)后,至多有一个集合的往上的第一个祖先还未确定。

可以理解成选的线段树节点往下去覆盖叶子,还未覆盖到的叶子必须来自同一集合。

结合树上 DP,考虑子树 \(u\),未覆盖到的叶子来自于第 \(i\) 个集合,子树内祖先的选择方案数为 \(f_{u,i}\),若每个叶子都有了祖先,记录为 \(dp_u\)

需要特别考虑 \(i=1\) 定义成没被任何询问区间覆盖的点的集合。

初始值为叶子节点 \(u\) 在原数列位置为 \(i\),所属于第 \(j=\operatorname{belong}_i\),有 \(dp_u=f_{u,j}=1\)。答案是 \(dp_1+f_{1,1}\)

考虑转移:

\[f_{u,i}=f_{ls_i}dp_{rs}+dp_{ls}f_{rs,i}+f_{ls,i}f_{rs,i} \]

\[dp_{u}=2dp_{ls}dp_{rs}+\sum_if_{u,i} \]

\(\sum f_{u,i}\) 是因为可以选定 \(u\) 节点。
注意到 \(f_{u,i}\) 在叶子节点只会有 \(1\) 个取值。那么其实空的值很多,我们不需要考虑值为 \(0\) 的 DP 值。

考虑用线段树合并 / 启发式合并 维护 DP 的转移,将 \(dp_v\) 视为乘法标记即可,需要同时维护 \(\sum f_{u,i}\)

若用启发式合并,需要用 \(\operatorname{std::map}\) 维护。时间复杂度 \(O(n\log^2n)\)

若用线段树合并,时间复杂度 \(O(n\log n)\)

posted on 2024-06-07 08:52  nullptr_qwq  阅读(80)  评论(0)    收藏  举报