零些做过的题

可能和别的博客出现一些重复 qwq。


  1. CF1175G

这题看起来是一个决策单调性优化dp的板板,实际上它不具有单调性更不是版版,所以考虑用别的办法优化dp。

首先这个dp可以分成 k 层进行考虑,所以我们以下只讨论每层之内的转移。令初始时的dp数组为 f ,我们现在要求出 g

转移方程显然:

gi=minj=1i1{fj+(ij)×(maxx=j+1iai)}

这个 max 看着非常地烦人,但是我们注意到原式子的不同的max组成了若干段区间,可以使用单调栈维护,使一段完整区间内的值相同。

对于全局的问题,我们需要考虑每一个决策点 j,我们构造一条直线 kj=max,bj=fjj×max,则 fjgi 的贡献为 i×kj+bj,这个可以使用李超线段树进行维护。

但是当 max 改变时,每次被修改的点的个数将达到 O(n2),所以我们需要删除一些不重要的决策点。

考虑 fjj×max 的值,能不能消除 max 的影响?想到斜率优化。把每个决策点 j 抽象为 (j,fj) 维护一个下凸包,那么每次最后一段 max 我们可以二分斜率找到决策点,别的凸包上 max 值并未改变使用李超树维护即可。

具体到一些细节,我们进行单调栈时需要合并两个凸包,使用启发式合并容易做到 O(nlogn)。 同时合并时李超树可能会需要删除一些最新加入的线段,所以我们将李超树进行以下可持久化。

要分 k 段,所以一共要跑 k 次这个代码,时间复杂度 O(nklogn)


  1. Topcoder 14379

题意简述:

n105 个机器人玩石头剪刀布,每个机器人有一个长度为 k18 的操作序列。对于两个机器人进行比赛,他们会先对操作序列进行循环移位,然后依次按照序列出拳。定义两个机器人A,B是“稳定的”,当且仅当无论如何循环移位,他们 平局、A胜利、B胜利 的情况数相同。你现在需要求最多能有多少个机器人,使得它们两两之间都是“稳定的”。

解析:

好题啊!

石头剪刀布本质上是若干数在模 3 意义下的减法。考虑使用单位根。cnm这谁想得到啊

那么我们考虑两个操作序列 a,b,那么我们定义

Ask(a,b)=i=1kw3aiw3bi

可以证明,A与B的比赛结果不同等价于 Ask(a,b) 不相同。

我们令

pi={w30sa[i]=Rw31sa[i]=Sw32sa[i]=P,qi={w30sb[i]=Rw32sb[i]=Sw31sb[i]=P

那么我们考虑

Askd(a,b)=ijmodk=dpiqj

F(x)=d=0k1Askd(a,b)xd

则我们可以使用循环卷积表示 F(x)

F[d]=i+(j)modk=dpiqj

F=PQR

考虑原问题在多项式上的体现方式:F[i]=F[j] 对所有 i,j 成立。

F[i]=IDFT(DFT(P)DFT(QR))[i]

考虑IDFT的本质,IDFT与DFT都是对一个多项式进行点值计算,代入一堆点值都指向同一个数,所以 “A,B 稳定” 等价于 DFT(P)DFT(QR) 除了常数项以外的项的值都为0

所以我们考虑对 PQR 进行DFT,得到 DFT(P)DFT(QR),那么我们令 D(A)=i=1k12i×[DFT(i)=0],那么问题转化为 D(P)D(QR)=0

接下来我们又注意到,对于同一个 A 生成的 D(P)D(QR),它们一定是相等的。具体证明可以考虑让每一个机器人与自己进行对战,根据对称性可以感性理解。

综上所述,我们对于每个机器人,生成一个长度为 k1 的二进制数,我们要找到一个最大的集合使其不交。

考虑状压dp。我们令 dpS 为交集为 S 时最多选了几个机器人,对每个生成的二进制数开个桶进行统计,转移是显然的。

时间复杂度为 O(nm2+3m)。DFT的计算可以用分治优化到 O(mlogm),但是没必要。

【总结】

  1. 模意义下的加减法判定性问题有时可以考虑使用单位根进行刻画,因为单位根自带取模特点。
  2. 循环移位的特点可以考虑FFT的卷积过程进行刻画。
  3. 此题让我对DFT与IDFT的本质有了更深刻的了解。DFT和IDFT都是对多项式进行插值操作,并且互为逆运算。

  1. loj2461

听说是PKUWC的原题


  1. P9248

可以看出,题目分成了两个部分:求出“完美集合”的价值之和,以及计算最终答案。

首先对于计算价值的部分:

朴素的背包dp是 O(nm2) 的,瓶颈在于合并两颗子树是 O(m2) 的。但是如果只加入一个点只是 O(m) 的,这引导我么考虑设计状态使得每次转移时只考虑单个点的选择情况。

题目中有一个条件:选出的点必须是联通的。针对树上连通块问题,我们可以使用dfs序进行优化。令 dpi,j 表示当前考虑到dfs序为 i 的点(还未选择),总重量为 j 的最大价值。那么有转移:

dpi,j+vidpi,j+wi

dpi,jdpi+siz[i],j

---未完待续---


  1. CF506E

咕咕咕


  1. P6624

无向图生成树个数想到矩阵树定理,但是这个gcd看着让人不舒服,考虑把它反演掉。

因为

x=d|xφ(d)

所以原式可化简为:

d=1wmaxφ(d)(T[d|gcd(we)](we))

此时我们枚举 d,将所有边权为 d 的倍数的边保留,那么原问题转化为求一个无向图中所有生成树的边权和。

但是众所周知,矩阵树只能求

Twe

所以我们需要把加法转化成某种形式的乘法,这使我们想到生成函数

所以我们对于每条边附一个多项式权值 Wi=(wix+1),那么一个生成树的边权和就可以表示为所有 We 乘积的一次项系数。

上一次多项式在 mod x2 的加减乘除是简单的,所以根据矩阵树定理计算行列式即可。


P4067

首先这题我们可以先转化一下题意,求以下两个式子的值:

f(n,m)=i=0nj=0m[ijk]

g(n,m)=i=0nj=0m(ij)[ijk]

那么答案即为 g(n,m)k×f(n1,m1)

考虑数位dp。我们从高到低枚举位,那么根据经典套路,我们需要记录 i,j 分别是否存在限制,以及 ijk 的条件是否已经可以确定。

代码实现是简单的,没有多少细节。


CF582D

注意到 pα|(   mn+m)vp((   mn+m))α

把组合数暴力拆开,得到:

vp((   mn+m))=vp((n+m)!)vp(n!)vp(m!)=i=1n+mpinpimpi

考虑这个式子的意义:xpi 表示 xp 进制下去掉后 i 位的值。所以 n+mpinpimpi=0n+m在第i位上不进位

所以原问题转化为,求有多少对二元组 x,y 满足 x+yA 并且 x+yp 进制下进位至少 α 次。

由于有进位要求,所以从低位到高位转移更方便。设计数位dp:dpi,j,lim,jw 表示当前考虑前 i 位,已经进位 j 次,是否要顶住限制,上一位对该位是否有进位。

虽然 α 的范围很大,但是答案不为0时 αlogpA,所以暴力转移即可。

【总结】

Tips:前文公式中证明的其实是Kummer定理。

此题是数位dp中比较有趣的题目。数位dp既然是讨论某进制下数位的情况,我们在这种题上的思考方向应该往与数位有关的问题上转化。这再一次体现了转化与刻画题目给出的条件的重要性


CF710F

首先注意到答案具有可减性,所以删除操作与加入操作本质相同。

所以我们现在只考虑加入操作:

查询待匹配串在一大堆模板串里的出现次数,考虑使用AC自动机。

AC自动机必须先知道所有串串,然后建立Trie树,所以不支持在线插入操作。

AC自动机的建树时间复杂度为 O(|S|),查询时间复杂度为 O(|T|)

所以我们肯定是要维护若干个AC自动机,然后在某些时刻暴力重构。考虑使用二进制分组。我们维护若干个AC自动机的集合,每次向这个集合里插入一个大小为1的AC自动机,如果出现两个AC自动机大小相等就合并它们。

显然,每次合并的集合大小都会翻倍,所以每个串最多只会被合并 O(logm) 次,同时在某个时刻集合里最多只会有 O(logm) 个元素,可以接受。

当然这题使用根号重构也可以过


P8497

首先这题我们需要能够判定单个局面的可行性。

首先对于题目中给的两种操作方案,我们可以进行如下简化操作

  1. 不会进行重复的区间加操作,否则可以用若干次单点加操作代替
  2. 区间长度大于等于 3,等价于区间长度等于 3,4,5,因为更长的区间可以拆成若干小区间来代替。
  3. 不会有三个区间以同一个点为起点,因为可以将较长的两个区间长度减一,用一个单点操作代替。
  4. 不会有超过四个区间包含同一个点,如果一个位置被分配到了太多段,那么这些段的长度都会比较长,一定可以通过分裂区间来舍弃一部分—— _RSY_的题解

所以对于一个给定的序列 a,我们可以设计一个状压dp。令 dpi,x,y 表示已经考虑完所有右端点位置小于等于 i 的操作,满足 ai1=x,ai=y 的可行性。因为剩下的区间操作右端点位置都大于 i,所以 xy,且 x,y[0,3],状态数为 10n

至于转移,我们考虑枚举第 i+1 个数会被操作成什么。根据前面的推导,我们最多只需要枚举 [0,3] 内的数即可。这样我们就在 O(n) 复杂度内实现了对一个序列的判定问题。

开始统计答案:

先考虑 li=ri 的部分分,有一种感觉,如果说我手上抓 k 个石子可以完成,那么我有 k>k 个石子有很大概率可以完成。经过分类讨论后可以发现,除了 {0,0,,0}1,1,1 这两种情况,剩下的石子排布方案总能找到一个 k0 满足当 kk0 时一定满足题意。所以此时我们可以求出最小的 k0,判断 kk0 的大小关系即可。

那怎么求出 k0 呢?

我们令 gi,x,y 表示使得 dpi,x,y=1 所需要添加的最小石子数,转移是差不多的。

【思考】这一步是如何想到的呢?“恰好”是转化题意的关键,我们一般喜欢用“至多”或“至少”来代替“恰好”。这是一种条件的弱化,那么我们就需要消除这种弱化的影响。在这题里这种弱化几乎没有影响qwq

现在我们考虑 k=0,但是 liri 的情况。

注意到,我们在 dpi 的每一层转移中都只有 10 个状态,所以我们可以令

咕咕咕


P5386

首先,题目给定的四个条件太多了,我们考虑先固定住一些条件,然后解题。

固定住 l,r 时没有什么有用的性质,考虑固定 x,y

当我们固定住 x,y 后,我们令 bi=[xaiy],那么一次询问 (l,r,x,y) 的答案可以看做是 [l,r] 中所有 bi=1 的极长连续段的贡献和。这个我们可以用线段树维护。

x,y 变化时,因为我们已经维护了一颗线段树,所以不能对其进行跳跃性过大的修改。因为给定的 a 数组是个排列,我们考虑莫队。由于左右端点一共跳跃了 O(nn) 次,所以时间复杂度为 O(nnlogn)

考虑优化。我们发现线段树是个 O(logn)O(logn) 的数据结构,但是修改和询问的个数上有较大的差别。此时我们可以考虑根号平衡。我们希望找到一个东西,能在 O(1)O(n) 的复杂度内完成此操作。

这让我们想到了分块。分块算法直接让查询的复杂度有了 O(n) 的保证,我们现在只要让单点修改变成 O(1) 即可。

我们在线段树上要记录 4 个量:区间的长度、该区间的答案、前缀极长 1 段长度、后缀极长 1 段长度。不难发现,当我们将某个数从 0 变为 1 时,我们其实需要找到这个 0 的前驱与后继,那么答案更新是简单的。所以可以使用链表维护 0 的位置。当然在链表上凭空插入一个元素不是 O(1) 的,所以此处我们的分块算法只支持插入,不支持删除 的数据结构,将枚举 x,y 的莫队改为回滚莫队即可。


AT_agc025_e

好题。

我们令一条边的经过次数为 ce,那么答案有一个显然的上界 min(ci,2)

当我们找到了一个答案的上界后,我们不妨猜测一定存在一种情况达到这个上界,这可以通过观察大样例有一个初步的判断。

那接下来我们就来证明可以达到这个上界,考虑使用数学归纳法,将整棵树缩为一棵树。

单个点的情况是平凡的。所有的边都没有意义,自然满足题意。

假设原命题对 n 个点成立,下证原命题对 n+1 个点成立。

我们找到树上的一个叶子 u,记这个叶子的父亲为 v

首先对于起点与终点相同的路径,他们的方向不重要,随便定一个就好。

考虑将 u,v 合并:

如果 c(u,v)=0,那么 u 点没用,直接缩掉。

如果 c(u,v)=1,那么这一条从 u 连出的路径一定会对 (u,v) 产生 1 的贡献,所以也可以将 u,v 缩起来。

如果 c(u,v)2,那么考虑两条从 u 连出的路径 (u,x)(u,y)。假设两条路径的分岔处为 z,分岔后的部分等价于一条新路径 (x,y),所以可以将原先的两条路径拆成两条 (u,z) 和一条 (x,y),然后缩点 u,v

综上,我们构造出了一种方案使得答案达到上界,原命题对于 nN+ 成立。

至于构造一种可行方案,我们可以考虑从叶子节点开始拓扑排序,记录一下边与边之间的依赖关系,然后输出即可。

【总结】有一种最优化题目,可以先计算得到最优解上界,再通过构造达到上界。只是出题人不想***难人罢了/ww

这题有一点像广义串并联图中的“删一度点,缩二度点,叠合重边”的操作,都是将原问题简化为规模更小的子问题,得到最简化形式的答案后进行反推。


P4684

首先,对于一个已知的宝石集合,我们肯定会尽量选择若干长度小的鱼,再用一条最长的鱼把它们都吃掉。这引导我们去将小鱼和大于分开进行讨论。所以我们有一种策略:先计算出若干小鱼的方案数,再计算出用大鱼吃掉它们的方案数,最后合并答案。

对于小鱼,由于小鱼之间没有吃与被吃的关系,并且我们只关心鱼肚子里的宝石,所以我们可以对于每种宝石分开处理。

先将小鱼长度离散化。考虑 dpi,j 表示前 i 种宝石,其中最长鱼长度为 j 的方案数。可以将dp数组滚动后使用线段树进行优化,需要支持单点加、区间乘操作。

对于大鱼,大鱼能否造成贡献只和选出的最长的小鱼有关,所以本质不同的可选择的大鱼的宝石集合个数为 O(k),直接统计然后和前面求出的dp数组乘起来就行了。

这是wjq一开始的想法,然后他发现他不会去重,于是遗憾重构。

咕咕咕


CF1580F

好题!

先将所有数字分为两类,一种数小于 m2 记为“小数”,其余数记为“大数”。显然,如果相邻两个数都是小数,那么他们之间互不影响。

以下我们定义大写字母表示其对应小写字母表示的数列的 OGF。

所以我们可以将环断成若干条链,使得它们都是“小大小大小”的形式,即开头结尾都是小数,中间小大交替。我们定义这样的链为奇链。我们设长度为 i 的奇链的答案为 ai,那么长度为 i 的链的答案为 ti,那么求出 OGF 后可以发现

T=i=0Ai=11A

所以对于奇环分类讨论一下,答案为 tn+i=1n1tniai。问题转化为如何求 a

此处有一个很牛的trick:因为大数小数的位置固定,所以我们可以将每个大数减去 m2,那么这条新链的相邻数的和小于 m2。相当于说m 为限制的奇链的情况与以 m2 为限制的链的情况一一对应。当然这需要对长度为 1 的链特判。

对于一条链而言,它有可能是以大数开头,形成 “大小大小”+若干奇链+“小大小大” 的形式。所以在这个需求下,我们定义“偶链”为满足开头是大数,结尾是小数,中间小大交替的链。特别地,偶链的长度可以是 0,这样子也适应了奇链的情况。

记长度为 i 的偶链答案为 bi,长度为 i 的链答案为 fi,那么有:

F=B21A+A

对于计算 A,B,我们可以发现 am,i=bm,i=fm2,iam,1=m2bm,1=m2+1。所以我们可以根据 Fm2 先算出 Am,Bm,再通过 Am,Bm 算出 Fm。时间复杂度为 O(nlognlogm)

当然,如果 n 为偶数,可能出现一整个环根本没办法分割的情况。同理,我们可以将大数减半,转化为 m2 的子问题的答案加上合法分割的答案。


CF1093G,P1648

涨见识了,绝对值原来可以这么玩。

先考虑二维情况下怎么做。dis=|x1x2|+|y1y2|,但是这个绝对值很灵性,我们要考虑把它去掉。

注意到 |x|=max(x,x),所以 |x1x2|+|y1y2|=max(x1+y1x2y2,x1y1x2+y2,x1+y1+x2y2,x1y1+x2+y2)

这个形式是好刻画的。我们考虑两个 k 维点 PQ,那么 P,Q 的曼哈顿距离就是 PQ 的每一位随意选择一加一减的最大可能答案。这样我们就可以考虑状态压缩:

FP,S=i=0k(1)Sixi

dis(P,Q)=maxS(FP,S+FQ,US)

这个方法貌似只适用于求最大值的情况qwq

通过以上方法就能处理 P1648。至于CF1093G这个修改操作套 2k 个线段树处理询问即可。

【后记】:原来这个办法是曼哈顿转切比雪夫的拓展。我还是太菜了


P4859

因为药片和糖果的能量互不相同,所以问题转化为恰好k=n+k2 对组合满足 ai>bpi

像这种关于大小关系的计数问题一般可以先对两个序列进行排序。

对于一个 ai,考虑将其与某个 bj 配对。有以下两种情况:

  1. bj<ai 因为 ai 递增,可以记录前面的 ax 选了多少个 bj<ax。能够与 ai 组合的 bj 个数是好算的,这部分可以考虑 dpi,j 表示前 i 个数,选了 j 个的方案数。有转移 dpi,j=dpi1,j+dpi1,j1×max(0,cntij+1)
  2. bj>ai 这部分不好算,因为当前的选择具有后效性,所以我们先不填,最后再考虑。

“恰好”的问题不好做,考虑把它弱化为“至少”,然后用二项式反演消除影响。

我们令 gi 表示至少有 i 对的答案。所以 gi=dpn,i×(ni)!,即保证了有 i 对组合的方案数为 dpn,i,剩下随意乱填的方案数为 (ni)!,乘在一起就是答案。

我们令 fi 表示恰好有 i 对的答案。假设我们求出了 fi,可以发现 figj(ji) 的贡献是 f 中的 i 对在被 g 中被钦定的 j 对中出现的次数,也即 (ij)

那么有

gk=i=kn(ik)fi

二项式反演得到

fi=i=kn(1)ik(ik)gi

预处理组合数,然后跑 O(n2) dp,最后合并答案,时间复杂度为 O(n2)


bzoj4361

题意简述:给定一个长度为 n2000 的序列 a,如果 a 不是非降的,就选出 a 中一个元素删掉,否则停止。问有多少种不同的操作方案,操作方案不同当且仅当操作顺序或操作次数不同。

考虑枚举整个序列剩下什么东西。令 fi 表示长度为 i 的非降子序列个数。这个可以用BIT优化dp做到 O(n2logn)。那么有一个初步的答案为 fi×i×(ni)!

但是这样有一个问题:我们可能删到某个时刻就已经满足 a 非降,此时我们多算了若干步。只要减掉这多余的部分即可。

考虑最后一步删了什么元素,也就是统计不删这个元素这个序列已经非降的情况数。假设当前的序列长度为 l,那么上一步剩下的序列长度为 l+1,非降,此时有 l+1 中不合法的删除情况,总共需要减去 fl+1×(l+1)×(nl1)! 种情况。

所以我们的最终答案为:

i=1ni×(fi×(ni)!fi+1×(i+1)×(ni1)!)


P4707

好题。

这道题和P3175有一定相似度。我们套路地令 xi 表示第 i 中原料的出现时间,那么答案即为 E(minkxi)

根据出题心理学,这个东西肯定不好求,但是我们可以通过 min-max 容斥将 k 去掉。

发现 E(miniTxi)=miTpi 是好求的,所以我们可以先将 knk+1 转化为求 E(maxkxi)

先把拓展 min-max 容斥式子写下来:

maxk xi=TS,|T|k(1)|T|k(|T|1k1)miniT{xi}

将这个 min 拆开,套一层期望得到:

E(maxk xi)=TS,|T|k(1)|T|k(|T|1k1)miTpi

注意到 m 是不变的,前面那一坨式子只和 Tpi 有关,所以有一个很naive的dp设计:令 dpi,j,siz 表示考虑到前 i 个数,选了 siz 个数,它们和为 j 的方案数,转移显然。但是这种方法是 O(n2m) 的,无法通过。

所以这里有一个非常巧妙的思路:我们需要少枚举一些东西!

如果不管 pi,那么我们需要求出所有可能情况的 p 的倒数和。我们发现这个倒数在新加入元素时非常令人难受,遂放弃。

如果不管 |T|,那么就需要考虑当 |T||T|+1 时的事情:

(1)|T|k+1(|T|k1)=(1)|T|k+1((|T|1k1)+(|T|1k2))

left=(1)|T|k(|T|1k1)+(1)|T|(k1)(|T|1(k1)1)

这个好像是可以进行dp的。注意到这个式子中第二项里的 k 变成了 k1,所以还需要在 dp 中记录当前的 k 值。令 dpi,j,t 表示在 k=tpi=j 时,所有 (1)|T|k(|T|1k1) 的和。

根据前面推得式子,转移是比较简单的:

dpi,j,t=dpi1,j,t+(dpi1,jpi,t+dpi1,jpi,t1)

至于边界条件,让 dp0,0,0=1 ,其余数组都设置为 0 即可。当然这题的空间比较紧,所以需要用滚动数组把 i 滚掉。代码反而更简洁了


P5643

套路min-max容斥,考虑 dpi,S 表示从 i 出发走到 S 中任何一个点的期望步数。

那么有:

dpi,S={1degi(dpfai,S+dpv,S)+1iS0iS

这个dp具有很强的后效性,似乎需要高斯消元。但是!树上随机游走问题可以通过将儿子的dp值设为关于父亲dp值的函数来避免高斯消元!

考虑令 dpi,S=Ai×dpfai,S+Bi,那么因为根节点没有父亲,所以 dpx=Bx

修改一下式子:

degi×dpi,S=dpfai,S+(Av)×dpi,S+Bv+degi

整理系数可得:

Ai=1degiAv

Bi=degi+BvdegiAv

根据 min-max 容斥,有

max(S)=TS(1)|T|1min(T)

这是一个或卷积的形式,FWT整上去就做完了。


ARC101C

首先我们发现,钦定某些边强行不选可能是简单的。

考虑 f(S) 为钦定 S 中的边没有被染色的方案数,答案即为 SE(1)|S|f(S)

考虑令 h(x) 表示 x 个点随便匹配的方案数。那么有

h(x)={i=1x2(2i1)x0(mod2)0x1(mod2)

f(S) 的值可以认为是 S 将树分成的若干连通块的 g(siz) 之积。

考虑dp。因为 f(S) 与连通块大小有关,所以我们令 dpu,j 表示 u 子树中,与 u 相连的点的个数为 j ,忽略包含 u 的连通块时对答案的贡献。那么可以列出转移:

dpu,jdpu,j×dpv,k×h(k)

dpu,j+kdpu,j×dpv,k

O(n2) 的树形dp即可。


[2018雅礼集训1-16]方阵

题意:给出一个 n×m 的矩形,每个位置上填上 [1,c] 中任意一个正整数。要求填好后任意两行任意两列不等价。求方案数。

我们注意到如果只限制行不等价是好做的:f(n,m) 表示答案,那么有:

f(n,m)=(cm)n_

考虑加上列的限制:g(n,m) 表示答案,那么考虑枚举等价类的个数,有递推式:

f(n,m)=i=1n{ni}g(n,i)

由斯特林反演,得到

g(n,m)=i=1n(1)ni[ni]f(n,i)

时间复杂度 O(n2)


BZOJ4671

题意:定义两个图的异或图为这两个图的邻接矩阵每个位置分别异或得到的新矩阵对应的图。现在给定大小为 m60n10 个顶点的无向图集合,问有多少个子集的异或图为连通图。

好题!

我们发现如果钦定了某些节点不能放在一起,那么方案数可能是好求的。

考虑将 n 个点划分为 k 个集合,集合内的点随便连,集合间的点不能连,那么这样我们得到了至少 k 个连通块。

考虑“至少”与“恰好”的转化:令 fk 表示至少 k 个连通块的方案数,gk 表示恰好 k 个连通块的方案数。gi 中所钦定的连通块在 fk 中可能会再一次被合并,所以 gifk 的贡献为 {ix},于是有

fk=i=1k{ix}gk

反演得到

gk=i=1k(1)ki[ix]fk

考虑计算 f。我们枚举每一种划分情况,那么相对应地会出现若干限制:每种限制要求一条边的出现次数为偶数。

我们将“限制边”的出现情况压成一个二进制数,那么问题转化为:有多少个集合满足集合内所有数的异或和为0?

这是线性基板子题,将所有东西插入线性基里,假设此时线性基里有 s 个数,那么答案即为 2ns


P10013

这题肯定是对于每个 x,提取出 x1 的路径计算贡献。

dpu,i 表示当前考虑到 ux 前面有 i 个数的方案数。那么有

dpfau,j+kdpu,j×(j+k1j)×(sizfaujk1sizvj1)×C

其中 C 表示 fau 除去 u 子树外的拓扑序数量。

转移一次的时间复杂度为 sizu×(sizfausizu),对每个 x 求出答案的时间复杂度为 O(n2),总时间复杂度为 O(n3),考虑优化。

可以发现,对于每个 x 做dp时,是从 x 开始dp,在根节点计算贡献,同时每个 x 的dp的转移具有很强的相似性

如果说我们能够按照传统树形dp的方法,从根节点开始dp,在每个节点计算贡献,那么时间复杂度就可以缩减到 O(n2),可以认为是对所有 x 同时dp以减小复杂度。

那我们能把dp反过来做吗?其实是可以的。考虑转移可视化,我们可以将dp状态的转移看做有向图,转移系数看做边,那么原先的dp相当于计算从 S 出发,到达 T 的所有路径的边权之积的和。那当我们将这个有向图反过来,那就等价于交换了起点和终点,得到:

dpu,j+k×(j+k1j)×(sizfaujk1sizvj1)×Cdpv,j

总时间复杂度为 O(n2)


P4220

算是一道用来复习各种树上科技的好题吧。

一共三颗树,主要的思路肯定就是不断化归,将问题转化为两棵树……一棵树,最终解决问题。

树上路径问题先考虑点分治或边分治。点分治的子树太多没什么好的性质,考虑边分治。当我们劈开这条边后,整棵树被分成了两颗子树。假设这条边为 (u,v),那么答案可以表示为:

disT1,a,u+disT1,b,v+depT2,a+depT2,b+depT3,a+depT3,b2depT2,lca(a,b)2depT3,lca(a,b)

w(a,u)=disT1,a,u+depT2,a,那么答案可以进一步简化为

w(a,u)+w(b,v)2depT2,lca(a,b)disT3,a,b

我们在第二颗树上把第一课树上的点拎出来跑虚树,枚举LCA,那么 depT2,lca(a,b) 就变成了定值。

w(a,u)+w(b,v)disT3,a,b

考虑拆点,在 T3 中新建边 aa,边权为 w(a,u),那么这个值可以认为是 dis(a,b)。在代码中其实不需要建出这个新点,这里拆点的目的只是证明加上边权之后仍然满足可合并的性质。

如此这般,我们将题意转化为“给定两个集合,求这两个集合中点的距离最大值”,同时支持对集合的合并操作,这就是树的直径问题。

根据非负边权树的直径的可合并性,保存下直径的位置后,我们可以在 O(1) 时间内合并两个集合并找到新的直径。

LCA可以做到 O(nlogn)O(1),点分治有一只 log,求虚树为 O(nlogn),总时间复杂度为 O(nlog2n)

代码实现非常恶心。


CF1239E

这题应该是恶评,真实难度大约上位紫。

首先我们注意到,如果第一行存在逆序对,那么交换这两个数一定不劣。所以最终的棋盘形式一定是第一行递增,第二行递减。

因为 (1,1) 和 (2,n) 这两个位置一定要走,那么我们可以将 (1,1) 和 (2,n) 放上最小的两个数。

令向下走的时刻为 x,那么因为第一行单增第二行单减,所以在 x 时刻往下走的答案是下凸的,进而答案可以表示为 a1,1+a2,n+max(a1,i,b2,i)

我们现在将问题转化为:给定 2n 个数,要求将其分为两个集合,使得这两个集合中所有数的和的最大值最小。这就是一个可行性背包,用bitset优化,然后输出方案即可。


CF1188D

考虑枚举最终的数与原序列最大值的差 x,那么答案可以表示为 popc(x+amxai),令 aiamxai,那么答案可以表示为 popc(x+ai)

x 不会大于 260>1017,因为我们令 xxmod260 不会使答案更劣。所以考虑对 x 进行数位dp。

数位dp中的加法运算肯定会涉及到进位问题。显然不能存储每个数当前是否进位。但是我们会发现,当 pimod2t 增大时,能够使 pi 进位的 x 在不断变多。所以我们只需要记录有多少个,就能知道哪些数有进位。

从低到高做数位dp即可。时间复杂度 O(nlog2n)


CF1372E

有点意思。

这题第一想法是网络流,但是时间复杂度 O(n5) 有点高,所以应该要用别的算法。

首先我们发现,因为平方数的性质,我们应该尽量把 1 堆到同一列上。所以我们可以枚举某一列尽可能把 1 堆上去,把经过这一列的连通块叉掉后往左右两侧递归。

考虑区间dp。dpl,r 表示仅考虑横坐标严格包含于 [l,r] 范围内的答案,枚举上述过程暴力转移,答案为 dp1,m,时间复杂度 O(n4)


P7897

假设加的数为 x,那么显然有dp柿子

dpu=au+x+vmax(dpv,0)

考虑将转移可视化。如果 dpv>0,那么就连边 (u,v),所有连边组成了一个森林。显然 x 越大,连边越多,并且本质不同的连边情况只有 O(n) 种,所以考虑维护这个森林,那么答案就是子树的权值和加上子树大小与 x 的乘积。

那么先对 x 排序,问题转化为只有加边操作。

对于一个点 u,它能够和它在原树上的父亲连边时需要满足 xvalusizu,连边操作只会影响它父亲所在连通块的阈值,所以连边过程是 O(nlogn) 的。

同时,当我们加入一条边 (u,v) 时,对 valsiz 的修改可以认为是链加单点求值得操作,用树上查分转化为单点加子树求和,可以用dfs序+树状数组维护。


AT_arc160_f

好题!获得了一个全新的trick!

这题 n15,考虑 2n 有关做法。

在排序问题中,可以将排列转化为01串以简化问题。考虑将一个排列转化为 n 个01序列,满足第 i 个01序列中小于 i 的数为 0,大于 i 的数为 1

这样转化有什么好处呢?我们考虑在 n 维空间的路径 (0,0,,0)(1,1,,1),每一步让一个 0 变成 1,那么每一个排列与每一种路径一一对应。

我们定义一个01序列是合法的,当且仅当经过 M 步操作后,可以变成前0后1的形式。那么原问题等价于统计满足每一步形成的01序列都是合法的行走方案数。这个可以通过状压做到 O(n2n)

但是操作次数 m 很大,但是我们发现对于每个排列,逆序对数在不断减小,所以能够造成任何一个排列交换的操作(下称“有效操作”)只有 O(n2) 个,别的操作忽略即可,那么现在 mn2 同阶,但是需要维护哪些操作是有效的。

那么我们进行dp的时间复杂度为 O(nm2n),考虑维护哪些操作为“有效操作”。显然,操作 (x,y) 进行后,只会改变 (x,t)(y,t) 的有效性。所以对每个改变的操作进行 O(m2n) 的判定。总时间复杂度为 O(nm2n)=O(n32n)


P8283

挺不错的一道题。

为避免歧义,题面输入中的 l,rL,R 指代。

先考虑刻画题目条件,感觉这个对于区间的要求非常苛刻。集合 S 在异或操作下封闭,考虑线性基。我们设 S 的线性基大小为 k,那么可以得到 |S|=2k

考虑固定 y,那么能对答案造成贡献的左端点为 O(logn) 段区间组成。因为当 x 左移时,|S|k 单调不降,所以可以通过跑 O(logn) 次双指针来确定 x 的范围。

做到这一步时我们已经可以用二维数点来暴力了,但是时间复杂度可能不够优秀。考虑固定 k,设当 y=i 并且忽略 L,R 条件的 x 范围为 [li,ri),那么答案即为

i=xymin(ri,R)max(li,L)

考虑把这个min拆掉,发现这是个区间求和的形式,所以套一个前缀和就好了。


P4837

首先有一个结论:所有呆河马一定实在同一天卖出的。所以在第 i 天卖出的收益 fi=pi×j=0ixj,答案即为 fi 的最大值。

但是 fi 可能很大,高精度是不可能写的,注意到 fi 可以表示为若干个数的乘积考虑使用 log 来进行这一类较大数字的比较

考虑修改操作。log(fi)=j=0ilog(xj)+log(pj),那么一次修改等价于区间加操作,线段树维护 log(fi)fimod109+7 即可。


P4271

一个点到树上另一个点的最长距离的另一个端点一定是树的直径的端点!

wjq这个傻逼总是忘记这么显然的结论。

考虑离线建出整棵树,转化为合并两个点集的直径,暴力并查集+lca即可。


P4686

好题!

考虑给每个传送门拆出两个点:内点和外点。对于每个点找出到达它之前的上一个点和到达之后的下一个点。当我们将起点和终点缩点(记为 S)后,每个点只有一个入度和一个出度,所以整张图会由若干个环组成,答案即为包含 S 的环的大小减一。

考虑新加入一条边对图的影响。如果这条边在一个环上,那么将会分出一个环;如果这条边联系了两个环,那么将会让这两个环合并。

接下来就可以贪心了:新加入若干条边,每加入一条边可以让原图中的两个环合并,每次尽可能合并大患;如果合并之后仍然由剩余操作,那么每次先加入一条边新加入两个单点,一个并给 S,另外一个落单,然后再去加入一条边联系原本的大环和这个新点。排序+模拟即可。


P4510

首先这个贡献系数 10ln(1+A) 十分劲爆,因为 10ln(1+A)55 ,考虑直接枚举这个值,设为 T

繁衍关系只会在同一层之间出现,不同层之间会影响 A 的大小。所以我们可以令 dpi,j,S 表示当前考虑到第 i 层,血缘链上相邻异性情况数为 j,当前层性取向情况为 S 的答案。

考虑转移。既然是装压dp,肯定要枚举上一辈和这一辈链上的状态,剩下一些散点。那么当前层的取值存在若干形如“若 ai=xbi=y,那么对答案会产生 ci 的贡献”,这是一个集合划分模型,可以用网络流求出。

时间复杂度为 O(10ln(nk)n2k(Θ(Dinic)+nk2k),实际上严重跑不满,可以通过。


P10202

一道很好的区间 dp 题!

这题 n=50 的数据范围,以及删除后区间会发生合并的操作过程,可以让我们想到使用区间 dp 解决问题。

考虑记录答案。令 fl,r 表示将区间 [l,r] 删干净的方案数,那么答案即为 f1,n

考虑删除整个区间的过程。我们可以枚举最后一步删除了下标为 p1,p2,,pk 的数,那么整个区间被这些下标分成了若干子区间。那么我们的步骤必然是:删除区间 [p1+1,p21],[p2+1,p31],,[pn1+1,pn1],最后删除 p1,p2,,pn

所以很自然的需要记录第二个 dp 数组。令 gl,r 表示将 [l,r] 删到只剩下与 al 值相同的元素,并且 alar 必须保留的方案数。所以 g 数组在 alar 时没有意义,我们也不会用到此时的值。

现在让我来推导一下转移:

对于 f,因为 al 不会被右边的数所影响,所以我们考虑 al 是和那些东西一起删去的。考虑枚举上文中的 pk 的最大值。那么我们将操作分成两部分:删除 [l,pk] 直到只剩下 p1,p2,,pk,以及删除 [pk,r] 中的所有元素。

midpk,于是有:

fl,rgl,midfmid+1,r

对于 g,我们考虑枚举 p1 的位置,那么下标在 [l+1,p11] 的所有数都应当先删除,然后将 [p1,r] 中所有数删到只剩下 p1,p2,,pk

midp1,于是有:

gl,rfl+1,mid1gmid+1,r

当然 gl,r 也可以通过一步删除 p1,p2,,pk 转移到 fl,r

这里的 表示合并答案,因为这里记录的 dp 内容不够完整,我将在后文补充。

我们发现,我们此时将操作分成了互不干扰的两个部分。现在我们要讲两个部分的操作合并到一起去。所以我们还需要记录当前状态下进行了多少次操作。

fl,r,k 表示用 k 步将 [l,r] 中的数全部删掉的方案数,gl,r,k 表示用 k 步将 [l,r] 中的数删到只剩下 al,ar 和其他数值等于 al 的数的方案数。

整理转移,那么有:

fl,r,kgl,mid,kx1×fmid+1,r,x×(kx)

gl,r,kfl+1,mid1,x×gmid,r,kx×(kx)

以上能转移的前提是 amid=al

还有 g 单独转移到 f 的方案:

fl,r,kgl,r,k1

预处理组合数,然后根据式子进行 dp 即可。时间复杂度为 O(n5),但是常数非常小,可以通过。


ARC076F

首先这题可以将人作为左部点,位置作为右部点,假设最大匹配为 x,答案即为 nx。所以此题严格弱于二分图最大匹配问题。

但是这题的数据范围不允许我们直接跑最大匹配。

关于这种优化二分图匹配的问题,有两种思考方向。一种是模拟进行匹配的过程,不断寻找增光路;另一种是考虑 Hall 定理,用子集之间的关系刻画问题。本题我们选择第二种方向。

Hall 定理有两种表述:

  1. 左右点数相同的二分图存在完美匹配的充要条件为 XVleft|X||Nb(X)|
  2. 至少补充 max{0,|X||Nb(X)|} 条边能使得原图有完美匹配。

https://hydro.ac/d/bzoj/p/3936

很深刻的一道浪费生命的字符串好题。

对于第3小问,可以直接预处理height数组转化为区间最小值问题,可以用ST表做到 O(nlogn)O(1)

对于第4小问,可以用LCP和LCS进行刻画题意:存在一个 x,满足 LCP(x,l2)len2LCS(x1,r1)len1。这个时候我们可以用倍增对于 l2r1 处理出满足一边要求的 x 的范围,解不等式即可。

剩下两问没想好,先咕着。


P3960

注意到对于每一次操作,数字与数字的相邻情况几乎没有改变,可以用动态开点平衡树维护链表操作,每次将被用到的数字拆出来操作即可。

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