6 月做题记录

都退役了,做个锤子。

CF1354E


首先 1 和 2 能连,2 和 3 能连,1 和 3 不能连。
先不管数量限制,看什么时候无解。
只要不是二分图就无解。

现在可以考虑数量了,把每个连通块跑个二分图染色染成黑点和白点,先令每个连通块都是黑点比白点少。
把所有黑点染 2,如果这样 2 的数量还是太多就无解了。
对于中间的,我们把一些连通块的黑白互换,就可以增加一定数量的黑点,还是把所有黑点染 2,相当于这样会增加一定数量的,这好像就是个背包问题,然后还要记录方案。

1 和 3 有区别吗

CF643G


神仙题。
这题推广。
给出一堆数,令 (k= lfloorfrac{100}{p} floor) 每次删除 (k+1)两两不同的数,删到不能删为止,可以保证对的数不会被删掉
然后把两堆删过的直接这样合并也是可以的(把一堆里的数一个个加入另一个)要考虑被加入的那堆里是不是已经存在那个数了。
既然区间可合并于是就可以线段树了...
区间赋值就打 tag + 对应那堆改成只剩一种数,次数是区间长度
存的时候存数值 + 处理后那堆还剩下这个数的出现次数
注意细节

P3527


整体二分,只会两个 log

CF1363E


父亲节点操作的选择权包含儿子的所有操作,所以儿子节点的操作代价如果比父亲大,就等价到父亲节点操作,于是把所有节点的操作代价改成它到根一路上代价的最小值,然后代价形成一个大根堆,这样操作越深的节点越划算了。

然后再观察一个性质,就是 0->1 和 1->0 两两配对,很明显 0->0 和 1->1 如果参与 shuffle 就是白给,反正那些 0->1 1->0 都至少要 shuffle 一次。

然后统计子树里 0->1 和 1->0 数量,自下而上的处理,这题就解决了。

CF1000F


有点像 HH 的项链
维护对每一个位置,这个位置上的数上一次出现的位置 (pre),这是基本操作了。
离线右端点排序+线段树,枚举右端点 (r) ,储存每一个位置的 (pre),区间查询 ([l,r]) 最小的 (pre) 是否能小于 (l)(直接改成 INF)记得每次更新把 (pre)(pre) 移去,即对于 (i),如果 ([i,r])(a_i) 出现两次,那 (pre_i) 再小也不能被选到,这个每次移动右端点只会修改对应的一个。

这题还可以莫队硬上

CF639E


这个 (c) 明显提示二分答案了

最优顺序用邻项交换排序求出
令开始做 (i,j) 中先做的那个时已经用去了 (x) 时间。
令先做 (i) 更优,则有:

[p_i imes (1-frac{c(x+t_i)}{T})+p_j imes (1-frac{c(x+t_i+t_j)}{T})>p_i imes (1-frac{c(x+t_i)}{T})+p_j imes (1-frac{c(x+t_i+t_j)}{T}) ]

[xp_i+p_it_i+xp_j+p_jt_i+p_jt_j<xp_j+p_jt_j+xp_i+p_it_i+p_it_j ]

[p_jt_i<p_it_j ]

(frac{t_i}{p_i}<frac{t_j}{p_j})
对于 (frac{t_i}{p_i}) 相等的数可以随意交换,这样可以求出每个数最早和最晚可以放在哪个时间做完,这些数形成连续的一段,且段与段之间位置关系确定,第 (i) 个问题最早完成时间为这一段的起始时间加 (t_i),最晚就是这个段的结束时间,即这个段的起始时间加这个段中所有问题用时之和,起始时间为这个段之前所有段用时之和。

如果两问题产生了 paradox,则同时满足两个条件:
(p_i<p_j)
(p_i imes(T-cx_i)>p_j imes(T-cx_j))
(x_i) 代表完成时间。
一定考虑最坏情况是否有 paradox,所以 (x_i) 取最小时间,(x_j) 取最大时间。
先按 (p_i) 排序,把第一个式子的影响去掉。然后保存所有 (p_k<p_i)(p_k imes(T-cx_k)) 的最大值,做比较,即可。注意 (p) 是严格小于。

做这步的时候可以看出答案是有单调性的..

如果两问题处于同一段,也并不会有问题,因为在判断是否有 paradox 时,两数分别处于段的第一个和最后一个

P3320


把所有点按 dfs 序排序后,答案就是所有相邻两点距离之和,再加上第一个和最后一个点的距离。
每次插入点的时候找出上一个点和下一个点(当然也可能不存在)
用树状数组 + 倍增做这个,也可以用 set
写了一堆分类讨论(

P4099


(dp_{u,i}) 表示 (u) 的子树中,(u) 的拓扑序排第 (i) 位的方案数。
然后 dp,相当于每一个点维护着一个序列,先枚举 (u) 和子树的序列中 (u) 和子树的根的拓扑序,然后把子树那个序列加入 (u) 的序列。
我们已知的只有 (u) 已经被合并的所有子树中对应那个序列中 (u) 的具体位置,并不知道序列里具体每一个数是什么,但是我们知道有多少种合法序列,对以 (v) 为根的子树也是这样。我们把两个序列合并,可以看作先确定每个位置是前者还是后者,然后再确定整个序列的具体情况。
UAv4aR.png

P3240


和上一题大概是一个套路
先把上来给了等于关系的并成一个元素,然后就是每一个子树维护有多少种不同的序列,往上合并。
(dp_{u,i}) 表示 (u) 的子树里对应的序列有 (i) 的小于号的方案数。

CF587D


首先看无解,如果一个点连了三个同色边肯定无解,如果有不止一种颜色有两条边连在这个点上,那么也无解。
这样每一个点最多存在一种颜色有两条边连在了这个点上,把这个颜色找出来,用 2-SAT 两个边不同选加个限制。
然后一个点至多连一条边,可以用 2-SAT 前缀优化。
(xa_b 代表第 x_a 为 0/1,sa_b 代表前 a 个元素中是否有 1)
N9G1c8.png
二分答案,有一些边直接强制不能选,然后跑 2-SAT。
2-SAT 强制选一个数或不选:连一条边 ( eg x o x)(x o eg x)

CF587F


AC 自动机 fail 树 dfs 序上建树状数组。
根号分治一下就好了。。

CF585F


(s) 的长度 (geq lfloor frac{d}{2} floor) 的字串建出来,然后 AC 自动机上数位 dp。
找出第一次匹配上的位置,乘上剩下没填的位的方案数。最后加起来。

P4068


把能配对的数连边,连出来一定是二分图。
按数的 所有质因子 个数 之和 奇偶性 分成两类点,同一类点之间不可能连边,因为连边的两个点所有质因子个数之和相差 1.
然后就是二分图匹配问题了。

CF932E


懒得写式子了。
(k) 很小,用第二类斯特林数的性质,把指数上的 (k) 拆下来,然后二项式定理。

P4609


首先最高的那个建筑肯定看得到,我们任意选取一个方案:
aclAUI.png
把每个看得见建筑和它挡住的建筑分成一组,这样最高的建筑左边有 A 组,右边有 B 组。如果只是分组就是第二类斯特林数了,但是一组内还是可以排,一个大小为 (n) 的组,方案数是 ((n-1)!),这就是圆排列个数,可以想到枚举最高建筑的位置,然后用第一类斯特林数求解。

但这样还过不掉,需要优化。直接把除了最高的建筑以外的先分好组,然后在其中选择 (A-1) 个组在左边即可。预处理斯特林数和组合数,可以 (O(1)) 回答单组询问。

CF666E


离线,后缀数组 + 线段树合并(按 height 从小到大)
码码码

CF575A


首先考虑一步一步递推,当然会超时。
用矩阵加速,线段树维护矩阵区间乘积,从小到大依次处理每个特殊值,两个特殊值之间的部分可以加速,分类讨论一下。还需要快速幂。

这题没什么意思,就是码码码

P2868


看到平均值肯定是 0/1 分数规划没问题
对于有向边 ((u,v)) 把边权赋为 (T_{(u,v)} imes mid - F_u) 然后看有没有负权环即可,有负权环代表答案 (geq mid)

CF512D


有的点没法删,把能删的点拿出来,会形成一些有根树和无根树。
有根树意思是根节点连向了一个不能删除的节点。
(dp_{i,j}) 代表第 (i) 个树删除 (j) 个点的方案数,最后的答案就是这些树的答案合并起来。

对于有根树,设 (dp_{i,j}) 表示 (i) 的子树删 (j) 个数的方案数,自底向上转移即可。
对于无根树,每个点可以是先删完儿子节点再删的,也可以是删完 除了它子树内点 之外的所有点之后,才删掉这个点。不仅要算上面的方案,还要额外计算第二种的方案,第二种其实就是对每个点 (u) 算一遍 子树删点方案数 * 子树外删点方案数,注意删除后一定要保留 (u),也就是子树不能全删,这样就可以做到不重不漏了。

P5283


(k) 很小,一个个取就行了。
先求一遍异或前缀和 (pre_i),那么 ([l,r]) 的区间异或和就是 (pre_r oplus pre_{l-1})

先把对于每个 (r)(pre_r oplus pre_{l-1}) 的最大值扔进堆里,然后每次取出堆顶,删除堆顶,如果堆顶取出的 (r) 对应的第 (k) 大值,就把 (r) 对应的第 (k+1) 大值再扔进堆里,这样每次取出的一定是没取过的区间中,最大的区间。

用 Trie 存下所有 (pre_i) 即可快速求出与 (x) 异或的第 (k) 大的数,但是这样是没法处理 (l>r) 的情况,也就是 (l>r) 也的方案会被算进去,解决方法也很简单,(pre_r oplus pre_{l-1}=pre_{l-1} oplus pre_r),同一对数会重复计算两次,由于它们值一样,肯定是连续取出来的,所以取最大的 (2k) 个数,最后答案再除以 (2),就好了。

P2325


树分块板子。
树分块不能像序列分块一样,必须通过使得一个点能够包含在不止一个块中,才能使得每个块保证 ([B,3B]) 之间。

方法就是自下而上,对一个点,每次把子树中所有点加入栈,如果当前栈中的点数大于等于 (B) 就和根组成一个块,由于是递归操作,这个子树很大子树里就会分好块,进栈的点数不会超过 (B),所以这样一个块不会大于 (2B)
最后会剩下一些点不够组成一个块,就并进一个已有的块,所以会出现一个大小上限 (3B) 的块。

P2825


没有 # 就是车放置,典型的二分图最大匹配问题。
这题 # 可以把一行或一列分成两部分,把每行,每个连续段 . 段作为左边的点,把每列,每个连续段 . 段作为又边的点,相交的两段连边,跑最大匹配就可以了。

P3888


状压 dp,没什么意思。
要存两行的状态。

P4251


这种第 (k) 大的最小值,看着就很像是二分答案。
二分答案以后发现就是只允许选 (leq mid) 的数,能不能选出来 (n-k+1) 个,典型的二分图最大匹配模型。

P3705


0/1 分数规划 + 二分图带权最大匹配。

P3227


如果没有限制,把每个 ((x,y)) 拆点,从上往下连,选每条边代表选择 (f(x,y)=z),求最小割。
考虑怎么把限制加上,就相当于有一些边不能同时选了,而且如果把图看作分层图,这些边一定满足相差的层数 (> D)
把红边加上去就可以了,这样如果相邻两处切点相距太远,中间一定会容下一条红边,导致 S 与 T 仍然连通。
afbiOe.png

P4827


这个指数很小啊,那基本就是第二类斯特林数了?
(x^n=sum_{k=0}^n S(n,k) imes C(x,k) imes k!)

通常幂是没法 dp 的,但是组合数可以 dp,这是转成组合数的好处之一。
(这里默认 (C(a,b)=0 (b>a))
首先随便一个点当根,设 (dp_{u,i}=sum_{vin subtree(u)} C(dis_{u,v},i))

先考虑一个点往父亲转移 (sum_{vin subtree(u)} C(dis_{fa_u,v},i)=sum_{vin subtree(u)} C(dis_{u,v}+1,i)=sum_{vin subtree(u)} C(dis_{u,v},i)+C(dis_{u,v},i-1)=dp_{u,i}+dp{u,i-1})
那么转移方程就是 (dp_{u,i}=sum_{vin son(u)} dp_{v,i}+dp_{v,i-1}),自底向上转移即可。
注意 (i=0) 的情况,就是 (dp_{u,0}=sum_{vin son(u)} dp_{v,0}+1),要把 (u) 自己给加进去,(u) 到自己的距离显然为 (0)

剩下点的可以换根 dp 求出答案。
在每个点当根,计算最终答案的时候,枚举 (dp) 第二维,乘上对应的斯特林数和阶乘。

P5308


wqs 二分降维,去掉 (k) 的限制。
后面的 1D/1D dp 可以斜率优化。

CF571D


对两种集合分别建一个并查集,利用按 size 合并控制树高在 (log n) 级别,在 M 集每个点记录以这个点为根最后一次被清空的时间,每次清空都要找到根。
同时每次合并的时候要记录这个点是什么时候合并的,可以看作是记录在边上,因为会有合并之前有清空而合并后没有。

处理加操作更加复杂一点,需要每个点用一个 vector 记录操作,里面元素是按时间递增的。然后查询的时候先求出被查询的数最后一次被删除的时间,然后它的每一个祖先节点上二分查找即可。事实上只有一个点需要二分,比它更深的一定贡献为 0,比它更浅的一定所有操作都未被清空(不要忘记处理合并时间,同上)。

这里还会涉及到区间和,用前缀和就可以了,每次加入元素的时候也更新前缀和。

CF521E


显然三条路径在同一个边双联通分量中。先把割边都删掉,然后把每个连通块分别处理。把 dfs 树建出来。
最后有解肯定是长这个样子的
S 和 T 代表起点和终点
aIPsB9.png
自下而上处理,每个点维护自己所在子树里能达到的深度最浅的点以及对应的那条返祖边(因为随着深度的上升,深度更深的点可能只能到达自己了,不能到达祖先,这样这条边就没用了,而最浅的那条边是最优情况)如果一个点 (u) 有两个或更多子树有返祖边可以到达这个点的祖先,则拿出来 (u) 和另外两个边连到的点(这两个可以是同一个点),就是图中的蓝点了。

P3749


先不考虑 (mx^2+c)

这题读题有些困难,但是可以发现其实就是在一些 (d) 中让你选取一些,并且有一些"选了 a 则必选 b"的限制,每个 (d) 都只有被选或不被选两种状态,而不是可以被多次选择,后面的花费也是如此,这基本可以排除 dp 的可能性,这题就是个网络流题。

对于每个 (d_{i,j}) 建一个点,然后向它的所有子区间连边,很明显,这就是个最大权闭合子图模型。
但这样边数太多,考虑优化,([i,j]) 只连到 ([i+1,j])([i,j-1]) 就可以达成目的了。

再考虑加入 (mx^2+c)

对于每个代号单独建一个点,注意到 (mx^2)这个代号选了几种是无关的,只和这个代号选或没选有关。如果选择了这个代号的寿司则必选这个代号对应的点,这是一个限制。
然后就相当于让这个点是最大权闭合子图模型中一个收益为 (-mx^2) 的点即可。

还有 (cx),这个其实没啥用,每个寿司单独分开算就可以了,直接减到它的收益里面就行了,但我为方便起见建了两条边。

剩下就是最大权闭合子图了。
下图中省略了代表区间的点和单点所连的边
(也就是 1-3,1-2,2-3,1,2,3(d) 产生的边)

P3749.PNG

P3750


期望看起来无从下手,先尝试寻找某个局面的最优解法,就是最少花多少步可以全变 0

首先观察到一个性质,每个开关至多操作 (1),因为操作 (2k) 次等于没操作,操作 (2k+1) 次等于操作 (1) 次,这样就把答案限制在了 (leq n)
这是所有这种一个开关控制多个灯改变亮暗情况的点灯类型的题的共有性质。

但是这样还是不能做,于是观察开关 (i),改变的是 (i) 的所有约数,有的灯可以被多个开关影响到,但是 (n) 号灯一定只有 (n) 号开关能影响,因为 (n) 已经是最大的数了,不可能有它的倍数。

于是 (n) 号开关是操作还是不操作,直接就定下来了。

这样以后 (n-1) 号开关是否操作,也能确定,以此类推,每个开关操作与否直接被确定。
大多数点灯题都是能找到这样一个只被一个开关控制的灯的切入点的。

然后我们发现,到这一步之后,问题被转化了,有 (n) 个数,其中 (m) 个是 (0),剩下的是 (1),每次等概率随机选取一个数,将它变为另一个状态,求使得所有数中 (1) 的个数小于等于 (k) 的期望步数。而且这只和 (1)数量有关了,和哪几个开关是 (1) 无关。

期望一般考虑倒推,设 (dp_i) 为当前有 (i)(1) 时,期望还需要多少步才能变成全 (0)

(ileq k)(dp_i=i)
否则 (dp_i=frac{i}{n}dp_{i-1}+frac{n-i}{n}dp_{i+1}+1)

直接高斯消元不可行,但是这个式子看起来可以递推。

[i imes dp_i+(n-i) imes dp_i=i imes dp_{i-1}+(n-i) imes dp_{i+1}+n ]

[i imes (dp_{i}-dp_{i-1})= (n-i) imes (dp_{i+1}-dp_{i})+n ]

[dp_{i}-dp_{i-1}=frac{n-i}{i} imes (dp_{i+1}-dp_{i})+frac{n}{i} ]

还需要一个边界条件:(dp_{n}-dp_{n-1}=1)
就可以递推了。

最后 (dp_m) 就是答案。

原文地址:https://www.cnblogs.com/IltzInstallBI/p/13461632.html