Typesetting math: 100%

2023.5

ARC157D

绷不住了

设行切了 x 刀,列切了 y 刀,Y 的总数为 A,那么需要有 2(x+1)(y+1)=A

进一步,如果确定了 x,y,那么行被分成的这 x+1 部分中一定每一部分都恰好有 2(y+1)Y。再进一步,对于每一种符合这个条件的行的分割方案,他们对应的列的分割方案数都是相同的。

容易在 O(H+W) 的时间内对一组 x,y 算出方案;最后需要 check 一下方案是否合法,预处理二维前缀和后枚举每一块判断就行了。

复杂度是 O((H+W+A)d(A)),其中 d 分别表示约数个数。由于 d(A)A3 因此很稳。

ABC282H

分治。算出分治中心到左右的最小值 Ai,Bi 与和 Ci,Di,那么相当于要求

min(Ai,Ci)+Bi+DiS

分类讨论,若 AiCi 相当于 DiSAiBi,否则相当于 Ci+DiSBi

典型的二维偏序模式,平衡树/权值线段树维护,总复杂度 O(Nlog2N)

ABC282G

f(i,l,j,k) 表示填了前 i 个数,Ai=j,Bi=k,目前有 l(Ai+1Ai)(Bi+1Bi)>0 的方案数。转移考虑上一个 Ai1=x,Bi1=y,用 DP-T 的技巧平移一下,分四种情况讨论即可。

二维前缀和优化即可。复杂度 O(N4)

CF17-Final J

Boruvka 之后变成:对每个点求出他到其他集合中某个点的最小距离。

做一遍换根 DP 即可,DP 的时候需要记录距离当前点最小的距离及其颜色 c,和颜色 c 中的最小距离。总复杂度 O(NlogN)。这怎么都评 Silver 啊?

20230502

链加子树和 1log。

转成 vsubtree(u)mark(v)×(dep(v)dep(u)),两个线段树维护。

P4587

很典的题,一年前口胡了但是没写。

考虑朴素算法:从小到大考虑所有 ai,设当前答案为 x,若 aix+1xx+ai,否则答案为 x+1。考虑优化,发现只需要每次把上一个 ai 到当前 x+1 的所有数一起加,这样答案至少增倍;使用主席树维护,由于答案不超过 ai 故总复杂度 O(nlognlogai)

空间复杂度是 O(nlogV),不过离线下来一起跳就可以做到线性了。orz cftm

ABC248Ex

提供一个 O(Nlog2N) 的做法,不依赖于 0K3 这一限制。

考虑分治,对于「[l,r] 有多少个子区间符合条件」这一问题,取 m=l+r2,算出跨过 m 的区间个数,把被 [l,m],[m+1,r] 包含的区间看成子问题分治下去。

ai,bi,ci,di 表示左右两侧距离为 i 的最大值与最小值,那么条件合法当且仅当

max(ai,cj)min(bi,dj)i+j+K1

枚举 i,钦定 aicjmax(ai,cj)=ai,分两种情况讨论:

  • bidj,则要求 aibiiK+1j
  • bi>dj,则要求 aiiK+1j+dj

注意到 a,c 均单调递增,b,d 均单调递减,因此 ai,bi 那两维的约束都可以表示成「j 在某个区间内」这样的约束。这样就只有两维数点了,可以做到 O(NlogN)。总复杂度 O(Nlog2N)

CTSC2006 歌唱王国

设最后的序列长度为 X,这是一个随机变量。考虑其期望

E[X]=i=0Pr[X=i]×i=i=0Pr[X>i]

因此,如果设 F(x)X 的 PGF,G(x)gi=Pr[X>i] 的 OGF,就有 F(1)=G(1)

另一方面,考虑以下事件发生的概率:在 T 次随机之后,仍然没有结束,接下来不管是否结束都新加入 m 个字符,且他们恰好为 S 的概率。不难发现这是 gT×1nm

另一方面,这种情况下实际的结束时间 X 一定在 [T+1,T+m] 之间,考虑 Pr[X=T+i](这里使用 X 而非原来的 X,是因为这个变量和原来的变量并不相同),发现首先要在 T+i 时刻结束,第二要满足 S[1i]=S[mi+1m],第三要满足后面那些刚好凑上 S

不难发现这三个也是充分条件。

因此,Pr[X=T+i]=Pr[X=T+i]×isborder(i)。有

gT×1nm=i=1mfT+i×isborder(i)×1nmi[xTnm]G(x)=i=1misborder(i)×[xT+inmi]F(x)=i=1misborder(i)×[xT+inmi]F(x)xi1nm×xmG(x)=i=1misborder(i)×xmiF(x)×1nmi

x=1 带入即得 F(1)=G(1)=i=1misborder(i)×ni

变式

求随机变量 X 的方差。

考虑到方差即 E[X2](E[X]2),有

E[X2]=i=0Pr[X=i]×i2=i=0Pr[X=i]×i(i1)+i=0Pr[X=i]×i=F(1)+F(1)

因此方差即 F(1)+F(1)(F(1)2)。考虑 F(1) 咋算,由 fi=gi1gi,f0=0 可得

[xi]F(x)=[xi1]G(x)[xi]G(x)(i>0)F(x)=xG(x)(G(x)1)F(x)+G(x)=xG(x)+1

两边求二阶导有

F(x)+G(x)=xG(x)+G(x)F(x)+G(x)=xG(x)+G(x)+G(x)

x=1,有 F(1)=2G(1);另一方面,由

xmG(x)=i=1misborder(i)×xmiF(x)×ni

两边求导有

mxm1G(x)+xmG(x)=i=1misborder(i)×(xmiF(x)+(mi)xmi1F(x))×ni

带入 x=1 即得

G(1)=mF(1)+i=1misborder(i)×(F(1)+mi)×niF(1)=2G(1)=2i=1misborder(i)×(F(1)i)×ni

2018 年集训队论文指出

F(k)(1)=ki=1mainij=0k1(1)j(k1j)(i+j1)!(i1)!F(k1j)(1)

其中 ai=isborder(i)。该结论容易通过归纳得出。具体地,我们把以下二式同时求 k 阶导

F(x)+G(x)=xG(x)+1G(x)=i=1misborder(i)×xiF(x)×ni

即可得到上式。

ABC241Ex

考虑随便选的时候(即没有 Bi 这个约束)答案是啥,发现是(我应该没推错)

[xM]i=1N(1+Aix+Ai2x2+)=[xM]i=1N11Aix

这东西......总之可以暴力算出 F(x)=(1Aix),然后求逆。

我不会多项式科技怎么办!只会暴力写求逆递推式然后矩阵快速幂 O(N3logM) 啊,自闭了。

考虑拆一手,待定系数

i=1N11Aix=i=1Nci1Aix1=i=1Nciji(1Ajx)

依次取 x=A11,A21,,AN1,我们就可以得到

ciji(1AjAi1)=1(1iN)

这样就可以 O(N2) 时间内解出 ci 的值。接下来就有

[xM]i=1N11Aix=i=1NciAiM

然后考虑容斥,钦定 S 以内爆限制,发现只需要把 M 减去 iSBi 然后乘上 iSAiBi 就行了。

总的时间复杂度为 O(2N×NlogP)

实际上你可以发现容斥干的事情无非是把原答案的多项式

[xM]i=1N1AiBi+1xBi+11Aix

的分子展开了而已!和生成函数做法没啥区别的!!

ABC241G

考虑 1 能不能成为 winner。显然应当先让 1 剩下的边全部都连向对面。设此时 1 的胜场数为 A

现在算出来剩下所有点当前胜场数 xi,相当于对每条未确定的边 (u,v),你要选择一个方向,然后让 xuxu+1 或者 xvxv+1。要求最后 xi<A

想了若干贪心都假了。

考虑网络流,设有 m 个未确定的边,建 n+m 个点,每个 1imui+m,vi+m 连边,容量为 si 连边,容量为 w。每个 i+mt 连边,容量为 Axi1。最后满流就有解。

ABC240G

N<|X|+|Y|+|Z| 时无解。

否则,考虑先算出将 a 步分配到一个长为 b 的维度上,发现方案数是

(aa+b2)

不妨考虑两维的情况

F(N)=x=0N(Nx)(xx+X2)(NxN+Yx2)=x=0NN!(x+X2)!(xX2)!(N+Yx2)!(NYx2)!=N!(NXY2)!(N+X+Y2)!x=0N(NXY2)!(N+X+Y2)!(x+X2)!(xX2)!(N+Yx2)!(NYx2)!=N!(NXY2)!(N+X+Y2)!x=0N(NXY2xX2)(N+X+Y2N+Yx2)=(NN+X+Y2)(NN+XY2)

那么答案就是

z=0NF(Nz)(Nz)(zz+Z2)

做完了。

写个 EGF:

fX(x)=n01(2n+X)!(2n+Xn)x2n+X

我草了,这个东西的封闭形式是 IX(2x),其中 Iα第一类修正贝塞尔函数,好高深!

ABC226H

由于

E[X]=0Pr[X=i]×i di=0Pr[X>i] di

考虑使用 minmax 容斥,有

E[maxK{Xi|i=1,2,,N}]=T(|T|1|T|K)(1)|T|+KE[miniTXi]=T(|T|1|T|K)(1)|T|+K0100Pr[miniTXi>v] dv=0100T(|T|1|T|K)(1)|T|+KiTRivRiLi dv

我们可以算出

f(v)=T(|T|1|T|K)(1)|T|+KiTPr[Xi>v]

考虑 Pr[Xi>v],发现他是一个分段函数:

Pr[Xi>v]={0,vRiRivRiLi,Liv<Ri1,v<Li

因此,最终的 f(v) 将是一个不超过 2N 段的分段函数,对每段分别计算并积分即可。

具体来说,f(v) 的每一段都可以表述为

abi=KN(i1iK)(1)i+K[xi]i=1N(1+(kiv+bi)x) dv=abi=KN(i1iK)(1)i+Kgi(v) dv=i=KN(i1iK)(1)i+Kabgi(v) dv

其中,gi(v)=[xi]i=1N(1+(kiv+bi)x),这是一个不超过 i 次的多项式。

如果每次朴素计算 g0N,时间复杂度为 O(N4)

考虑到每次移动一次区间,只有 O(1)kiv+bi 会发生改变,因此我们只需要做一次背包删除和背包插入。这样时间复杂度就是 O(N3) 了。

ABC301Ex

简单题。考虑先建一个最小生成树出来。

  • 如果修改的边 (u,v) 不在树上,显然对答案没有影响。
  • 如果修改的边 (u,v) 在树上,考虑新的最小生成树,发现应当选取一端点在 u 这边,一端点在 v 这边的所有边中边权最小的边。可以转 DFS 序后二维数点,但复杂度至少为 O(Nlog2N);对每条非树边在 u,v 处分别修改,然后线段树合并即可。这样时间复杂度为 O(NlogN)

所以其实可以任意修改边权的。。

P3513

求将一个图 G=(V,E) 划分为一个独立集 S 和一个团 T 的方案数。

考虑两种划分 (S1,T1),(S2,T2),注意到:

  • 至多存在一个 xS1,使得 xS2

这是因为如果有两个 x,yS1,那么必有 (x,y)E。但另一方面,由 x,yS2x,yT2,因此必须要有 (x,y)E。这是矛盾的。

这样一来,一旦我们求出了一组合法解 (S,T),那么所有的合法解一定可以通过以下三种步骤得出:

  • S 中删掉一个点放进 T 中。
  • T 中删掉一个点放进 S 中。
  • S 中删一个点 x 放进 T,再从 T 中删一个点 y 放进 S。并且进一步地,如果存在这样的方案 (Sx+y,T+xy),那么所有的方案一定形如 (Sx+z,T+xz) 或者 (Sz+y,Y+zy)

这样一来,总共的方案数只有 O(n) 种。我们完全可以枚举每一种方案并一一判断,做到 O(n2);也可以通过维护加点与删点时两侧边数的变化来做到 O(n+m)

最后说一下怎么获得一组合法解。比较简单的方法是采用 2-SAT:对每个点 i,我们设 pi{0,1} 表示 i 是否在独立集内,那么只需对每个 (i,j)E 连边 pi=0pj=1,以及对每个 (i,j)E 连边 pi=1pj=0 即可。直接连边需要 O(n2) 条边, 不过我们可以用线段树优化建图,做到 O(n+mlogn)。这样总的时间复杂度就是 O(n+mlogn)

UOJ449

首先有一个 minmax 容斥的做法:注意到如果要算一个 |T|=iE[miniTti],那么最多 i×k 次就会结束,因此可以做一个简单 DP 算出期望。具体来说,Pr[X>v] 就是将 v 粒玉米分配到 n 只鸽子头上,且每只鸽子只能分 <k 个。设 dp(i,j) 表示前 i 个分 j 粒玉米即可,复杂度 O(n3k),NTT 优化可以做到 O(n2klog(nk))。貌似 O(n3k) 卡卡常也能过?

但说实话,你注意到本题的模型类似「每只鸽子都得超过 k 个」,min-max 容斥之后变成「每只都不许超过 k 个」,但本来较好算的就是前者。。因此我们容斥反倒把本题变难了orz

摁推!!不会推,摆了。

ABC302Ex

简单题。考虑一组询问咋做,把所有 (Ai,Bi) 连边建图,显然答案是点数减去是树的连通块个数。

如何维护形态为树的连通块个数?可以用并查集维护,对每个连通块额外维护连通块内边数即可。

树上咋做?dfs 一遍,用可撤销并查集维护即可。O(NlogN)

带撤销并查集写了个路径压缩,调了一年

ABC302G

简单题。考虑算出 1,2,3,4 各自的个数,然后把序列分成四段。设 ai,j 表示在第 i 段中 =j 的元素个数,其中 1i,j4。我们的目标是让所有 ijai,j 都变成 0

显然,同一段内的操作是没用的。每次操作如果交换了两个数 x,y,他们分别在 i,j 这两段里,那么对 a 的影响就是:

  • ai,xai,x1,ai,yai,y+1
  • aj,xaj,x+1,aj,yaj,y1

然后对每行依次考虑,发现最优策略一定是先把形如 (i,j)(j,i) 这样的位置消成 (i,i),(j,j),然后剩下的再匹配。由于 Ai4,就算是第一行在匹配的时候也必然会在某一侧只留下一个非零元素,因此匹配方案是唯一的,可以保证最优。

LOJ2292

两年前 qbxt 就讲过的题怎么现在才来写啊

每次都抽取连续的一段,考虑区间 DP,f(l,r) 表示删空 [l,r] 的最小 a×k+(maximini)2

考虑咋转移,发现最后一次删除可能是原区间的一个子序列,因此可以设 g(l,r,x,y) 表示将 [l,r] 删到只剩值在 [x,y] 中的数至少需要多少代价。那么有转移

g(l,r,x,y)={g(l,r1,x,y),wr[x,y]minli<rg(l,i,x,y)+f(i+1,r),wr[x,y]f(l,r)=minx,yg(l,r,x,y)+b×(yx)2+k

离散化一手,时间复杂度就是 O(n5)

ABC301F

f(i,j) 表示前 i 个字符,恰好和 DDoS 类字符匹配上了前 j 个,没匹配上 j+1 的方案数。

转移就随便做一下,对于 f(i,1) 还需要多记录一下第一个 D 目前已经攒了多少种。看上去为了处理不是 ? 的位置我们需要状压一手,但实际上只需要记录一下当前非 ? 的位置已经出现了多少哪些元素,在遇到一个新的字符 c 时,若 c 确定出现过,那么一定是 f(i,1,x)f(i+1,2,x);否则设非确定的位置已经攒了 x 种,c 不确定是否出现过,前面确定出现了 y 种,那么就是实际上可以把 f(i,1,x) 分成 (26yxy) 种,其中每一种的方案数都相等。这其中有 (26y1xy) 种接不上,而

(26y1xy)(26yxy)=26x26y

于是有 f(i,1,x)×26x26yf(i+1,1,x+1),f(i,1,x)×xy26yf(i+1,2)

时间复杂度 O(n|Σ|)

CF587D

感觉这题远远不到 *3100 啊

考虑一种颜色咋做,发现首先要满足每个点的度数不超过 2。这样一来,每个连通块就只可能是环或者链。进一步地,每个环都必须是偶环。不难发现,这也是充要条件。

这样一来,每个连通块必然是「选」与「不选」的边交替出现,因此只有两种方案。

对于多种颜色的情况,我们对每种颜色找出所有连通块,设所有颜色一共有 k 个连通块,我们的变量 x1,x2,,xk{0,1} 就代表第 i 个连通块选哪种方案。对于两种异色连通块,他们之间可能有若干交点,这意味着某个 xi=axj=b。发现转化为 2-SAT 模型,可以在 O(n+m) 时间内求解。

对于原题,只需要二分答案一次,发现相当于钦定了某些 xi 的取值,仍然只需要做 2-SAT。

时间复杂度为 O((n+m)logV)

QOJ5020

fx,d 表示 x 子树内x 距离 d 的点数,gx,d 表示 x 的轻儿子的所有子树内与 x 距离 d 的点数。

不妨先来考虑 yx 祖先的情况,考虑如何算出此时 y 子树内有多少个点与这条链距离 d。发现这其实就是链上的点数,加上,链上每个点 u 的其他儿子的子树内,与 u 距离 d 的点数,之和。

考虑这条链 yx,发现链上的大部分边都是重边,只有 O(logn) 条轻边。这也就意味着,如果我们要计算与这条链距离 d 的点数,对于大部分点,都只需要计算他们轻儿子内的信息;只有 O(logn) 个点需要特殊处理重儿子的信息。具体来说,设这些轻边分别是 (u1,v1),,(uk,vk),其中 viui 的父亲,那么答案就应该是链上所有点的 g,d 之和,减去 fui,d,再加上 fhson(vi),d

考虑到 f 那部分一共只有 O(logn) 项,而在 O(logn) 时间内计算单点的 f 自然是简单的,于是这部分容易做到 O(nlog2n)。现在考虑如何计算一条链上所有点的 g,d 之和。

考虑差分成 1x 链上所有点的 g,d 之和,我们注意到每个点的所有轻儿子的子树大小之和为 O(nlogn),这允许我们从根开始往下 DFS,每次遇到一个点,就遍历他的所有轻儿子的子树内的所有点,并计算他对 g 的贡献。具体来说,我们动态地维护序列 Gi=upath(1,x)gu,i,每次新进入一个点 x 时,暴力扫他的轻儿子的子树内的每个点 v,并令 Gdis(v,x)Gdis(v,x)+1。则查询只需查询前缀和,使用树状数组维护即可,时间复杂度 O(nlog2n)

最后,由于实际距离 d 的点可能在子树外,我们还需要使用某些树分治算法进行一遍树上邻域数点。这部分也容易做到 O(nlog2n) 以内。

最后的最后,我们实际上询问的并非祖先-后代链:设实际询问的是 xy 这条链,z=LCA(x,y),我们分别对 zx,zy 算出 z 子树内与这条链距离 d 的点数,那么多算的部分恰好就是 z 子树内与 z 距离 d 的点数,即 fz,d。最后加上 z 子树外与 z 距离 d 的点数即可。

127 指出本题可以使用科技做到 O(nlogn),并把这题搬到了模拟赛。

ABC220H

实在是听不懂 127 的 O(N3/w) 做法,但是 O(N×2N2) 做法还是挺简单的!

首先转成补图,变成取一个导出子图,那么现在要求点集内边的奇偶性和 M 一致。

N 个点平均分成两部分,分别求出 f(S),g(T) 表示左侧的 S 点集与右侧点集 T 内边数奇偶性。

现在考虑拼接两个集合 S,T,发现会有若干跨过去的边。枚举左侧集合 S,设 S 延伸到右侧的若干边的另一端点构成集合为 T0,那么相当于要在右侧选出一个 T,这个点集 ST 的导出子图内的边数奇偶性就是 f(S) xor g(T) xor x,其中 xS 延伸过去的边数的奇偶性。

我们仔细想一下这个延伸过去的边数到底是啥,发现只有 T0 中与 S 中连边个数为奇数的点能造成贡献。设 c(S) 表示所有满足 xS 中连边个数为奇数的点构成的集合,那么跨越两端的边数的奇偶性就是 popcount(c(S) and T) 的奇偶性。

看着就很像 FWT 对吧!套路地把这个奇偶性变为 12(1+(1)popcount(c(S) and T)),然后就成功凑出了 FWT 的形式。具体来说,我们按照 f,g 的奇偶性分成四类,以 f(S)=0S 为例,首先求出 h(S) 表示满足 c(S0)=SS0 个数,那么对于右侧的 T,根据 g(T) 的值就可以知道我们想要的 popcount(c(S) and T) 的奇偶性。

如果想要 popcount(c(S) and T) 为偶数,那么左侧能和 T 拼上的 S 的数目就是

ans(T)=f(S)=01+(1)popcount(c(S) and T)2=12(f(S)=01+Sh(S)(1)popcount(S and T))=12(FWT(h)[T]+f(S)=01)

发现只需要给 h 做一个 FWT 就可以了。总的时间复杂度为 O(N2N/2)

QOJ4549

f(u) 表示 u 子树的 SG 值,那么转移相当于选一个 v,删掉这条链后必然会形成若干子树,该后继的 SG 值就是这些子树的 SG 值的 xor 和。最后还需要对这些东西取 mex。

考虑所有这些后继状态,发现如果我们设 S(u) 表示 u 子树的所有后继状态的 SG 值构成的集合,实际上对于一个点 u,设其儿子分别为 v1,,vk,那么他的 S(u) 就是:将每个 S(vi) 异或上所有 jif(vj),然后再取并集,再插入所有 f(vi) 的异或(表示第一次操作删除了 u 自己)。

那么我们就是要用数据结构维护一个集合,支持全局异或,插入,合并,查询全局 mex 这三种操作。

使用 01trie 维护即可,单组数据复杂度 O(nlogn)

举办乘凉州喵,举办乘凉州谢谢喵 in 1log

上回书说到,我们把这题分成了三部分:计算 O(nlogn) 次某个 fu,d 的值,计算 O(n) 次某条链上 gu,d 的和,计算 O(n) 次与某个点距离 k 的点数。下面我们分别把这三部分优化至 O(nlogn)

  • O(1) 计算 fu,d:设 size(u) 表示点 u 的子树大小,那么 fu,d 其实就是 size(u) 减去所有 ud+1 级儿子的子树大小之和。于是我们只需要计算某一 DFS 序区间内深度 =d+1 的点的 size 之和,可以简单用前缀和做到均摊 O(1)
  • O(1) 维护 Gd=upath(1,x)gu,d:同理,只需要维护单点加单点求值,开桶维护即可。
  • O(nlogn) 进行邻域数点:点分治后维护前缀和即可。

综上,本题在 O(nlogn) 的时间复杂度内得到解决。代码待补

posted @   云浅知处  阅读(225)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示