[CF2194D] Table Cut

已知 a+ba+b 是定值,求 abab 的最大值,那么根据均值不等式或者说二次函数的视角来看,aa 尽量接近 a+b2\cfrac{a+b}{2} 能让 abab 尽可能大。

然后,aa 也确实可以从 00 到 a+ba+b 任意取:00 指 DDD...RRR...,然后从最后一行开始往上,可以让 aa 逐个从左向右取,直到 a=⌊a+b2⌋a=\lfloor\cfrac{a+b}{2}\rfloor 为止。当然上取整也行。

AC Code。

[CF2194E] The Turtle Strikes Back

本题的核心问题是如何快速求出改了一个点后的全局最长路。

对于一般的图确实不太好做,但这是网格图,并且只能向右或向下。

对于一个点 (i,j)(i,j),我们按照 i+ji+j 给他们分类,那么每一步要么 i←i+1i\gets i+1,要么 j←j+1j\gets j+1,都会使得 i+j←i+j+1i+j\gets i+j+1。

我们只需要对每一类记录经过这一类点的最长路和次长路,然后当强制不经过点 (i,j)(i,j) 时,就查询 i+ji+j 这个类中不经过 (i,j)(i,j) 的最长路即可,这里我偷懒用了堆存储,实际上用两个变量就可以存储。

AC Code。

[CF2194F1] Again Trees… (Easy Version)

我认为本题的难点在于状态设计。

对于当前的节点 uu,切断边 (u,v)(u,v) 后,我们并不知道 uu 还和谁连着;不切断边 (u,v)(u,v),我们也不知道 vv 到底和谁连着。

但是,我们并不可能存储连通块本身的信息,所以考虑存储某些连通块的异或和。

那到底是存还与 uu 连着的连通块的异或和,还是存切掉的?

设 sus_u 表示 uu 的子树权值的异或和,那么已经与 uu 分离的部分应当是某个 bib_i,从这个角度来看,我们应当存已经切掉的异或和,这样才能保证状态大小与 kk 相关,其中 kk 是一个比较小的数。

现在又有一个问题,就是虽然 kk 很小,但是 bb 的值域并没有限制,所以我们转而用 2k2^k 的代价存储 bb 的下标出现在异或和中的情况,例如 10011001 表示 b1⊕b4b_1\oplus b_4。

那么,每一个点的初始值就是 dpu,0=1,dpu,∗=0dp_{u,0}=1,dp_{u,*}=0。转移时,枚举下标的状态 SS,然后枚举所有的边 (u,v)(u,v):

  1. 如果不断,那么枚举 vv 的下标状态 TT,有 dpu,S⊕T←dpu,S⊕T+dpu,S×dpv,Tdp_{u,S\oplus T}\gets dp_{u,S\oplus T}+dp_{u,S}\times dp_{v,T};
  2. 如果断开,那么枚举 vv 的下标状态 TT,vv 切掉异或和为 TT 的部分后应当是某个 bib_i,那么 dpu,S⊕T⊕2i−1←dpu,S⊕T⊕2i−1+dpu,S×dpv,Tdp_{u,S\oplus T\oplus 2^{i-1}}\gets dp_{u,S\oplus T\oplus 2^{i-1}}+dp_{u,S}\times dp_{v,T}。

统计答案时,我们枚举 bb 集合的所有情况检查是否合法并且累和即可,这样单次复杂度是 O(n4k+k2k)O(n4^k+k2^k),可以通过。

AC Code。

[CF2194F2] Again Trees… (Hard Version)

如果我们仍然沿用下标的逻辑,那么是无法做出困难版本的,因为没什么办法处理断开之后的那个转移。

又因为 kk 仍然是一个比较小的数,所以这里可以把 bib_i 全部插入线性基中,用线性基的坐标表示切掉部分的异或和,这样就可以控制在 2k2^k 的大小了。

对于不断开的情况,显然这里是一个异或卷积的形式,接下来看断开的情况。

首先不难发现,如果 svs_v 本身不能被这个线性基表出,那么这条边是不可能断开的,因为断开之后这个块必然不能表示称若干个 bb 的异或和;如果 svs_v 可以被这个线性基表出,那么我们枚举所有的 bib_i,看这个状态是怎么转移的:

∀S,T,bi,dpu,S⊕T⊕bi←dpu,S⊕T⊕bi+dpu,S×dpv,T∀S,bi,dpu,S⊕sv←dpu,S⊕sv+dpu,S×dpv,sv⊕bi\forall S,T,b_i,dp_{u,S\oplus T\oplus b_i}\gets dp_{u,S\oplus T\oplus b_i} + dp_{u,S}\times dp_{v,T}\\ \forall S,b_i,dp_{u,S\oplus s_v}\gets dp_{u,S\oplus s_v} + dp_{u,S}\times dp_{v,s_v\oplus b_i}

由于我们并不能每一次都进行一遍正变换和逆变换(复杂度 O(nk2k)O(nk2^k) 太大),所以我们只能维护 F(dpu)\mathcal F(dp_u),但是公式的推导还是在未变换之前来推的。

我们希望把这个写成卷积的形式,即 ∀S,T,fS←fS+gT×hS⊕T\forall S,T,f_S\gets f_S+g_{T}\times h_{S\oplus T}。

进一步转化式子:

∀S,bi,dpu,S←dpu,S+dpu,S⊕sv×dpv,sv⊕bi\forall S,b_i,dp_{u,S}\gets dp_{u,S} + dp_{u,S\oplus s_v}\times dp_{v,s_v\oplus b_i}

构造 gsvg_{s_v} 满足 gsv=∑i=1kdpv,sv⊕big_{s_v}=\sum_{i=1}^k dp_{v,s_v\oplus b_i},其他位置 T≠svT\neq s_v 都有 gT=0g_T=0,那么就有:

∀S,dpu,S←dpu,S+dpu,S⊕sv×gsv∀S,T,dpu,S←dpu,S+dpu,S⊕T×gT\forall S,dp_{u,S}\gets dp_{u,S}+dp_{u,S\oplus s_v}\times g_{s_v}\\ \forall S,T,dp_{u,S}\gets dp_{u,S}+dp_{u,S\oplus T}\times g_{T}

此时的更新就是 dpu←dpu∗dpv+dpu∗gdp_u\gets dp_u*dp_v+dp_u*g。如果 svs_v 不能表出,那么令 g=0g=0 即可。

于是,枚举每一条边就是 F(dpu)←F(dpu)⋅(F(dpv)+F(g))\mathcal F(dp_u)\gets \mathcal F(dp_u)\cdot (\mathcal F(dp_v)+\mathcal F(g)),其中 ⋅\cdot 是逐元素乘法。

还有一个问题,这个 gsvg_{s_v} 我们如何快速求得?

我们并不能获取到 dpvdp_v 原始的值,我们只能把它尝试写成某种卷积的形式,于是:

∀bi,gsv←gsv+dpv,sv⊕bi×ebi∀T,gsv←gsv+dpv,sv⊕T×eT∀S,T,hS←hS+dpv,S⊕T×eT\forall b_i,g_{s_v}\gets g_{s_v}+dp_{v,s_v\oplus b_i}\times e_{b_i}\\ \forall T,g_{s_v}\gets g_{s_v}+dp_{v,s_v\oplus T}\times e_T\\ \forall S,T,h_{S}\gets h_{S}+dp_{v,S\oplus T}\times e_T

其中当 TT 为某个 bib_i 时,eT=1e_T=1,否则 eT=0e_T=0。

那我们可以在 O(2k)O(2^k) 的复杂度求出 F(h)\mathcal F(h),然后在 O(2k)O(2^k) 复杂度求出 hsvh_{s_v} 单点的值,进而构造出整个 F(g)\mathcal F(g)。

统计答案的方法与简单版本相似,这样复杂度是单次 O(n2k+k2k)O(n2^k+k2^k),有些卡常。

AC Code。