Exemplary Examples VII
导语见 Exemplary Examples I。
T-151 CF2174F 26-3-28 B+
限制带在度数上的树计数问题,尝试把它和 prufer 序列联系起来,因为我们知道 prufer 序列中度数为 \(i\) 的节点恰好出现 \(i-1\) 次。从而,令 \(t_i=(\mathrm{mask}_i-\mathrm{cnt}_i)\mod 2\)。一个颜色一个颜色地 dp 插入到序列里即可。定义状态 \(f_{i,j}\) 表示前 \(i\) 种颜色构成的子序列长度为 \(j\) 的方案数,得到 \(O(n^3)\) 的做法。
观察该转移是带组合数的形式,故设指数型生成函数。对于一种颜色来说显然 \(F_i=\sum_{j\mod 2=t_i}\frac{x^j}{j!}\)。想要将其翻译成封闭形式,应该如何做呢?
遇到取模,不妨单位根反演。就是说 \([x\mod m=0]=\frac{1}{m}\sum_{i=0}^{m-1} \omega_m^{ix}\)。故
于是问题变成 \(O(m)\) 个关于 \(e^x\) 的双项式相乘后的结果,那这个是允许暴力卷积 \(O(m^2)\) 维护多项式的。
T-152 QOJ13509 加强版 26-3-30 B
对所有 \(n\in[L,R]\) 输出结果,其中 \(L,R\le 10^11\) 且 \(R-L+1\le 5\times 10^5\)。
首先 \(n=(ab+1)t,m=bt\)。对于一个 \(n\) 无法枚举 \(m\),希望改换主体枚举 \(b,t\),关键在于是否一一对应。换句话说,对于一个 \(n\) 和一个 \(m\),\(m\) 的两种分解形式 \(bt=cs\) 能不能同时满足 \(bt|(n-t),cs|(n-s)\) 呢?既然这样,有 \(bt|(|s-t|)\),但是 \(s\neq t,s<bt,t<bt\) 这不可能。故问题转化为,枚举出三个数 \(a,b,t\) 满足 \((ab+1)t\in[L,R]\) 并给 \((ab+1)t\) 做一的贡献。
注意到那是三个数乘起来,而且数据范围 \(10^11\) 也提示了类根号。故只需枚举二者中较小的两个是 \(O(R^{2/3})\) 的,剩下的直接打等差数列标记即可。
T-153 26-3-30 B
记不得题了。大概是一个期望题,能够写出转移式子(如果转移式子是求和的话,那么复杂度大致是时限的千分之一),大概是 \(E_0=0,E_x=\min(E_{x-1}+1,\frac{1}{p}\sum_i (E_i+1))\) 之类的。输出八位实数。
输出实数提示乱搞。可以先按照 \(E_i=i\) 赋初始值,然后对每个 \(x\) 求出 min 式子中的后一项(按照 \(E_i=i\) 求的),并据此更新一次。迭代几百次之后输出,就过了。
迭代逼近是一种实用技巧。期望 dp 只是其中一类应用;它可以用于最短路(想象一下,最短路就是通过迭代求解 \(f_x=\min f_y+w_{x,y}\) 这一方程组)、博弈、后效性 dp 等。转移式子里面如果带 max/min 就可以尝试了。
T-154 QOJ9559 26-4-6 B
分析连续段,操作一恰好分裂一段。操作二相当于把用户为 \(x\) 的都涂成零,故想到对每位用户建立一个类并查集(将空位视作用户零)。为了支持在“空位”集合上二分、分裂某一段,所以想到对每位用户开一棵动态开点线段树/平衡树。所需要的就是线段树分裂-合并/平衡树带交并。时间复杂度可以套路地通过总节点个数势能法证明,类似 T-132。例如选择线段树分裂-合并,则每次分裂的复杂度必是 \(O(\log V)\) 且新增 \(O(\log V)\) 个节点,而合并时,每递归一次则必然删除一个节点,故总复杂度 \(O(n\log V)\)。
对于一次查询,需要询问节点 \(x\) 所在树的根节点,暴力跳即可。但问题在于,节点 \(x\) 有可能尚未被动态开点建立。可以离线所有询问并统一提前建立节点。我想也可以维护所有连续段的 \(l,r\)(对称地维护缝隙位置),每次查询时二分一下即可找出 \(x\) 所在连续段,从而对应一个线段树节点,就是比较难写。
T-155 P5473 26-4-6 A
对于前五个点,步数限制 \(O(n^2)\),暴力询问即可。这可以视为“归纳”思想的应用:每次找出 \(i\) 节点相关的所有连边。
对于性质 A,步数限制 \(O(n\log n)\),有两种方法。法一,类似 T-134 选择类分治/二进制分组的办法,只需二进制分组即可,每次花 \(O(n)\) 代价,为每个点 \(i\) 求出,它的对应点在第 \(j\) 位上是不是一。法二,尝试“归纳”,每次找出 \(i\) 节点相关的那个对应点。考虑到步数限制,故尝试二分,把一个编号上的后缀,都用操作一处理,然后用操作二询问 \(i\)。这样的话,单点 \(O(n)\) 次操作一(指针移动),\(O(\log n)\) 次操作二,无法接受。因为要做好多次二分,改为整体二分即可。
对于性质 B,对每个节点找出父亲,整体二分即可。
对于性质 C,原图是一条链。尝试性质 A 法一,即可得到每个点 \(i\) 邻域的编号异或和 \(p_i\)。然而每个点邻域至多两个点。这类似于求解一个异或方程组,可以递推,例如说求解了节点 \(x\) 的全部邻域信息,那么可以跳到这两个相邻点上,然后马上求解它们的邻域信息。只需一个触媒,我们对节点一按照“前五个点”的做法,暴力 \(O(n)\) 求出邻域信息即可。
对于性质 D,扩展性质 C 的做法。是一棵树,故尝试剥叶子。整个过程必须从“找出一个叶子”开始,换句话说整个过程就是“找出一个叶子;消除其影响”的不断循环。“消除影响”是容易的,关键在于如何“找出一个叶子”。先别管复杂度,枚举一下 \(i\) 就变成“判断 \(i\) 是否是叶子”。必然是用四种操作去判定,我们把通用的判定过程称为“解”,手动爆搜“解”是什么,也就是先枚举“解”的第一步操作,然后找出第二步操作等等。大概率操作和 \(i,p_i\) 有关。经过枚举,先操作一 \(i\),然后询问 \(p_i\),就可以判断 \(i,p_i\) 之间是否有边。如果有,那么把这条边加入到答案集合里,然后选用操作四即可判断 \(i\) 是不是叶子。
对于整道题目,选用整体二分,每轮即可为所有“尚未求出整个邻域”且往前连了奇数条边的点,找出往前的一条边。但这不能保证复杂度。只需(每轮)随机打乱一下编号就能通过了。
T-156 T-095 加强版 25-12-17 S+
其实若 \(n\le 2\times 10^5,q\le 2\times 10^5\) 也能做,略显神秘。先放缩 (*),由错解不优,注意到若 \(j\) 略不合法,只要 \([i+2,j]\) 段没有被删空,则你直接算 \(-(j-i+1)(k-f_i)\) 这个负的贡献会比实际情况还差,因此判断合法性时,只需要 \(j>i+1\) 且 \([i+2,j]\) 段没有被删空即可。那么判断这个段没有被删空,可以比较 \(b_{i+2},k-f_i\) 的关系,若第一个大,则显然未被删空;若第二个大,则 \([i+2,j]\) 最小值一定小于应该被删的次数,这个东西本来是不合法的。故“若 \(f_i\le k\le f_i+b_{i+2}\),就认为一切 \([i+2,j]\) 段是合法中缀、\([1,i]\) 是合法前缀”是正确的。注意到 \(f_{i+2}\ge f_i+b_{i+2}\) 所以对于一个 \(k\),合法的 \(i\) 只有 \(O(1)\) 个。据此做到 \(O(q\log n)\)。
T-157 原计划的 T-102-3-2 CF1852F 26-1-14 S
配对呀,没想法吗?二分图最大匹配、网络流。那么我是用霍尔定理处理的。以红熊猫为左部点、蓝熊猫为右部点,霍尔定理说,找出任一左部点子集 \(s\) 及其邻域 \(N(s)\),则 \(n-\max |s|-|N(s)|\) 就是答案。用描述法,只需记录 \(s\),则足够计算 \(|N(s)|\),对所有 \(s\) 求最值,就是答案了。
具体如何计算呢?以时间轴为横轴,位置轴为纵轴建立二维平面,则一只红熊猫 \((x,t)\) 的邻域应该是:过 \((x,t)\) 的,斜率分别为正负一的两条直线,把平面分成四个部分,其中属于右部的所有蓝熊猫。将这个“右部”称作红熊猫的“贡献正方形”。据此,\(N(s)\) 就是 \(s\) 中红熊猫“贡献正方形”并集内的,所有蓝熊猫。旋转四十五度,就变成常规平面上的问题了,不妨让“右部”旋转后变成“左上方”,初始化位置是 \((-\infty,0)\),跟 T-102-3-1 一致。
我刚才强调,要会算答案,也就是给定 \(s\) 要会算 \(N(s)\)。把 \(s\) 中的红熊猫画出来,则对计算 \(N(s)\) 有贡献的,只有右下边界的若干红熊猫,这些熊猫互不隶属于对方的“贡献正方形”。能够确定 \(N(s)\) 则剩下的都不重要。本题是最优化问题,不妨放掉“不在右下边界的红熊猫有哪些”这部分信息,选择贪一手:在右下边界确定时,其左上方的一切红熊猫都会被选择入 \(s\) 才最优。假设没有修改,容易得到 \(O(V^2)\) 的断点转移 dp。当然能改成逐步转移,不妨钦定只有“向右转移”时计算代价。也就是说转移式形如
现在加入修改,它按照原 \(x\) 坐标从小到大添点(也就是现有坐标 \(y-x\) 从小到大添点)。把“现已添完了 \(y-x\le t\) 的点”中的 \(t\) 称作当前的时刻,则本问题有三个轴,分别是两个位置轴和一个时间轴。不妨把时间轴放最外面做扫描线。虽然当时刻增加一时,似乎大多数 \(f\) 值都有所改变,但准确地写一下。(*) 你会发现,一切超出当前时间轴限定的右下三角形范围的状态,它对其它状态(在“范围”内)的作用,仅仅是一个类似“取前缀最大值”的影响。也就是说我们在扫描线没扫到该位置时,不是很用考虑该位置的 dp 值对答案的影响;而它对答案的实际影响就是,本来你只需查询全局右上角的 dp 值作为答案,现在需要改查全局最大值了。那不妨仅在扫描到某位置时才算其 dp 值,相当于在扫描的过程不断维护 \(y=x+t\) 这条直线上的 dp 值,用它去推出 \(y=x+t+1\) 的 dp 值。这个东西呢,因为值域较大,不妨维护连续段或者说维护差分数组,然后上平衡树处理一下就行了。
这个是啥道理呢,就是说我们做扫描线扫掉一个轴,譬如说扫到“该轴坐标等于 \(t\) 的位置”,90% 都是用数据结构维护另一个轴,也就是说维护一切形如 \((t,y)\) 的点的值。如果动态加点只加在某个轴的末端,就直接明示了它要扫描线。如果你的扫描线,不太像是在维护上述“另一个轴”,那肯定是你分析错了,或者直接维护“另一个轴”也是对的。反正扫描线就得搭配这个,就像一旦分块,\(O(n\sqrt n\log n)\) 就不可能是正解(带老哥的数据结构跟分块不搭)是一样的。
T-159 QOJ7324 26-3-16 S
先考虑欧拉子图计数 (*),找出连通块内任一生成树,则非树边任意取入子图/不取,这样,连通块生成树里的每条边的取/不取也能随非树边的情况唯一确定。换句话说,答案就是二的非树边次方,即 \(2^{m-n+c}\),\(c\) 是连通块个数。本题中,权值是 \(x^2\),不妨拆组合意义,改为钦定两条边并求出“包含这两条边”的欧拉子图个数。若两条边重合。如果能够找出一个生成树不包含此边,那么显然这边是自由的,答案应为 \(2^{m-n+c-1}\)。反之,此边应为割边,若选择割边,则找出任意包含它且合法的生成欧拉子图中,包含此边的那个连通块,删除该边之后,得到两个新连通块,每个连通块内所有点度数(用欧拉子图内边计算度数)之和,恒为奇数,这不可能。所以若该边是割边,则贡献为零。若两边不重合且某边为割边,贡献也应为零;若不重合且没有割边,贡献就应该是 \(2^{m-n+c-2}\) 吗?不一定,若对于任意生成树,两边中恰有一个必定在树上怎么办呢?换句话说,此两条边都割掉后,原图会新裂出一个连通块,对每个连通块,虽然有两个点的度数被外界钦定增加一,但是我们造生成树后,一个“非树边选法”仍旧一一对应一个欧拉子图。所以贡献应为 \(2^{m-n+c-1}\)(连通块个数增加一)。
那么问题转化为,求原图的大小为二的割集数目(大小为 \(x\) 的割集,其超集仍是割集,所以要把其中一条边本身是割边的方案容斥掉)。套路是,建立任一棵生成树,将非树边赋一个随机哈希权值,并将非树边两端点间的路径上树边异或这个权值。那么一个边集是割集的充要条件是,这些边的权值集合线性相关(存在某个子集,使得它的异或和为零;或者跑线性基以后,数目与集合大小不同)。当然,这种随机哈希的办法,只能处理待询问割集很小的情况。如果要精确解,需要将上述随机边权改赋成如 \(2^i\) 这样任两个非树边包线性无关的形式,但这样一来对二进制位数的要求就成了 \(O(m-n+c)\)。反正本题中,因为只询问大小为二的割集数目,相当于问边权不为零且彼此相等的对数(这样问,就不用考虑容斥掉割边的问题了),就完了。
T-160 QOJ17158 26-3-16 S
限制形如“两点相等”,若把钦定相等的点连边,则只需求出连通块数就能算答案了。但是做不到这一点,考虑按某种顺序添加限制 ()(所谓“依次添加限制”,我总结写过的。或者也可看成是扫描位置轴递归子问题?好多 dp 不都是这样,反正你就得扫描位置轴),譬如按 \(i\) 从小到大依次添加“前缀 \(a_i\) 是回文”的限制。若 \(2a_{i-1}<a_i\),那答案直接乘以 \(2^{(a_i-2a_{i-1})/2}\) 就行了;反之有点麻烦,因为在前缀 \(a_{i-1}\) 内也出现了新限制。啥限制嘞,\([a_i-a_{i-1},\frac{a_i}{2}]=[\frac{a_i}{2},a_{i-1}]\)。很聪明地注意到 (),因为 \(a_{i-1}\) 本身是回文的,所以这限制相当于 \([1,a_{i-1}-\frac{a_i}{2}]=[a_{i-1}-\frac{a_i}{2},2a_{i-1}-a_i]\)。换句话说,就是对序列 \(a\) 做操作,删除 \(a_i\) 并添加 \((2a_{i-1}-a_i)\),方案数不会变化,递归下去了。所以我们倒着做,按 \(a_i\) 从大到小扫描,每次让相邻两个元素互相消消消,直到满足某个元素大于另一元素的二倍,用除法加速一下即可。关注回文串,有时它必定会具备 border 以及相关性质。
T-161 QOJ5442 26-3-16 S*
哈哈哈(精神状态良好)。第一道 S*,后面还会有更多。我真难理解,真难理解,究竟是什么人会做这种题,这还是人吗。
我不知道你如何注意到,行列任意做互换,答案不变 (*)。甚至任意互换一些元素,最终答案仍不变。然后行列互换也可视作元素互换,故只需证明后者。把元素分配互异的编号。元素互换后,再开始操作,操作结束后可以把元素换回来(将对应编号的元素再互换一次),这样得到的盘面就跟没做互换且进行操作后的盘面一致。故,是否互换,最终盘面一一对应。
然后我不知道你如何注意到,他对行列的操作具体是什么,其实挺无所谓的 (*)。什么意思,假设把某行受到的操作,视作对该行做一个置换,就是说若行原为 12345678 则换完后为 13572468,那么 \(p_1=1,p_2=3\) 诸如此类。根据上述任意互换的理论,我们可以把这个置换中,处于同一个置换环的那些列依据置换环顺序,换到一个连续的区域。在此,置换环分别是 1->1,3->5->2->3,7->6->4->7,8->8。因此将列由 12345678 换成 13527648。行列都处理完之后,你再看。对这个新矩形的第 \(k\) 行做操作,完全相当于本行的每个列连续区域部分,各自向右循环移一位。对列操作也完全类似。
现在没有复杂的置换,只有若干次循环移位。将连续区域缩点,得到 \(n'\times m'\) 个缩合区域。称连续区域行为一个行组,连续区域列为一个列组。显而易见,无论如何操作,一个缩合区域内的元素不会跑出去。
如果忽略一些行和一些列,就是删除它们(称作关键行列,但要求如果删除一行,也要删除对应置换环中的所有行;列也类似),得到一个新矩阵,求出新矩阵的所有可能结果(盘面状态)及其对应的至少一种操作序列,根据这些操作序列,还原出关键行列如果没被删除,经历上述操作序列后的状态。也就是说,根据新矩阵的每种可能的终止盘面,可以先还原出大矩阵的一种终止盘面。可以操作此时大矩阵上的关键行列,想怎样操作就怎样操作,得到大矩阵的一个最终盘面。能够证明,这样先不操作关键行列后来才统一操作关键行列,所得到的可能最终盘面数目,与依题意直接操作得到的答案相同。
那就好办了,先把所有所在行组大小为一的行,以及列拿出来,作为关键行列。设对于一个关键行/列 \(i\),其内每个缩后区域的最小周期的 lcm 是 \(p_i\)。答案就是,把它们删除得到新矩阵的答案,乘以 \(\prod p_i\),这个最小周期可以用 kmp 求出。记录 \(\prod p_i\) 为“答案一”。
现在不存在实际长、宽有一的缩合区域。对每个缩合区域,取势能量为,将缩合区域按照某种顺序排成序列并给元素分配互异编号,序列的逆序对数。这玩意的奇偶性变化规律是啥呢?考虑任意序列,互换两个元素,则逆序对奇偶性必变化。所以如果缩合区域宽为奇数,那操作缩合区域涉及到的任一列,就会造成逆序对数不变。我不知道你如何看出,假设天底下只有一个缩合区域,那如果缩合区域的逆序对数奇偶性不可以改变,则它的可能结果数目,就是 \(\frac{(rc)!}{2}\),反之就是 \((rc)!\)。
我们来证证。考虑你玩魔方(没学任何公式之前),最常见的玩法是:
XXXX XXXX X2XX X2XX XXXX
X12X 12XX 13XX X13X X23X
X3XX X3XX XXXX XXXX X1XX
XXXX XXXX XXXX XXXX XXXX
姑且相信这个玩法,除了 1,2,3 以外的元素不会移动吧。那么用这种玩法,可以从上到下从左到右依次复原每个格子,直到左下角的两个格子。故证对了。
行,这个玩法用在天底下缩合区域极多的情况下,也并不会移动任何本缩合区域以外的元素,就可以把本缩合区域复原成你想要的样子。不妨我们把答案先记为 \(\prod \frac{(rc)!}{2}\),然后再考虑给它乘 \(2^x\) 修正得到实际答案。这就得让一些缩合区域的逆序对奇偶性改变,就应该提前操作一手,这一手可能影响其它缩合区域的奇偶性。哦不对不对。这个缩合区域呢,如果里面有值相同的元素怎么办?事实上,如果存在哪怕一对相同元素,那所有盘面都能达成,因为你可以怎么着利用这个值相同的元素呢,骗过奇偶性分析。换句话说,这些“非互异区域”不需要受到提前操作,就能达到理论上的所有可能性,而且即使提前操作影响到了它,答案也不会改变。记录“非互异区域”的理论所有可能性为“答案二”。记录“互异区域”的 \(\prod \frac{(rc)!}{2}\) 为“答案三”。
好吧,讨论“提前操作”。具体来说,对于一个“互异缩合区域”,如果其长为偶数,则操作它涉及到的任一行都能改变其奇偶性;如果宽为偶数,则操作任一列都行。称长宽没有偶数的为“零区域”,恰有一个为偶数的为“一区域”,恰两个偶数的为“二区域”。假设描述每一行组、每一列组的提前操作次数,就能直接算出每个缩合区域的奇偶性能否改变。这就是在考察自由元数目。回忆 T-113-4,所有自由元素构成集合的性质(充要条件)是,若知道这些元素各自的值,则唯一确定剩余所有元素的值(依据题目给定的限制推出);这些元素各自独立取值,无论怎样取,都不会因为和题目限制冲突而不合法;这些元素如果不是题目直接计数的元素,那么这些元素的一种取值唯一对应题目直接计数元素的一组取值。求这种集合的元素数目最大值。
取主元为行组、列组的操作次数,实际是零一变量;操作后什么都不会影响的行组、列组不算数。那么假设行组、列组全是自由元,这没什么问题,只是可能不满足最后一条要求——可能有两种行组列组的取值,对应同一种缩合区域奇偶性。不过,先记录上述行组、列组个数为 \(c\),则记录“答案四”为 \(2^c\)。
我要去重!我要直接做除法!就是说,我要算出,对于同一种合法的缩合区域奇偶性,究竟有多少种行组列组取值符合它。易知对于每个“互异缩合区域”,其奇偶性在这些取值方案中都相同。“零区域”没什么用。对于“一区域”(设决定它奇偶性的行组/列组元为“涉及元”),它实际上限制了,涉及元在这些取值方案中必然取值相同。剩下的就是“二区域”(设它涉及的两个自由元分别为“涉及行/涉及列”)。那么考虑满足下述条件的区域:两种取值方案中,涉及行取值不同。从而,涉及列的取值也必须不同。这就会传导一切涉及到“涉及行/涉及列”的区域,然后继续传导。换句话说,将“二区域”的涉及行和涉及列连边,则一个连通块就会被传导到。
你要直接做除法。把“一区域”涉及到的连通块标出,给予豁免权(事实上,这些连通块似乎必然只有一个点)。其余的连通块,就代表你该做一次除法了,除以二。综上,总答案就是,答案一乘答案二乘答案三乘答案四,再做上述除法的结果!哈哈哈(精神状态良好),好题呀,就是有点要命。这就是我们大学生比赛吗。再会!
T-162 QOJ13008 26-3-19 S
描述法就是谁选了谁没选,检查合法性就是,第一个不能有两个选了的人互相删除,第二个不能有没选的人没被删除。观察一个选了的人能删除谁,把点画到二维平面上 \((i,p_i)\),见下图容易得到 \(O(n^2)\) 的 dp。

这个 dp 是一维数组半在线形式,可以用 cdq 优化转移。当然还可能想到把一维 dp 变成两维状态逐步转移的,然后上整体 dp,但这条路我没有细究。现在看 cdq。写出 mid 左侧状态 \(f_j\) 向右侧 \(f_i\) 转移的限制:\(\forall k\in [j,i],[p_k\ge p_i]+[p_k\le p_j]=1\) 且 \(p_j<p_i\)。此限制跨过 mid 涉及分治区间的两边,与分治“两边独立”的要求不符。类似于 T-121,以 \(k\) 为主体同时考虑左右两半的贡献和要求,换句话说考虑右半元素对左半要求的贡献,以及左半元素对右半要求的贡献。左半自己解决不了的要求,需要右半来贡献,根据存在-极大对称,对 \(j\) 找出 \(k\in[j,\mathrm{mid}],\min_{p_k>p_j} p_k\) 记作 \(a_j\)。对 \(i\) 找出类似的东西记作 \(b_i\)。那么能够转移的限制就是 \(b_i<p_j<p_i<a_j\)。这是二维数点,可以单老哥解决,总复杂度 \(O(n\log^2 n)\)。
需要优化消老哥。既然有三个轴(值域,位置,dp 值),不妨改为扫描值域轴,用归并排序的方法可以得到区间内相对大小关系。如图

纵轴是值域,横轴是位置,\(x\)(黑线)是当前扫描到的值,黑蓝绿点是已经添加的点,红点是正在添加的点。当且仅当红点 \((q,x)\) 在右边时,计算所有左侧点对 \(f_q\) 的贡献。那因为限制了所有点的高度都小于 \(x\),所以限制有一半不用处理了,另一半仅是 \(p_k<p_j\)。找到 \([\mathrm{mid},q)\) 最高点(如图红线的高度),那么左半能贡献的点就是黑红直线之间的、且在 \([l,\mathrm{mid}]\) 中是后缀最大值的那些。
查找红线高度,可以给右侧建立单调栈也就是绿点(你注意这里有一个对称,扫描的是值域,所以单调栈的判据应该是位置)均摊线性。但是查找左侧单调栈内值域高于红线的点中,dp 值最小是多少,这需要单调栈上二分外加树状数组之类的,不能做到线性。
单次查询 \(O(1)\) 意味着答案已经放在某处等你来取了,所以针对右侧单调栈的栈顶高度“顶高”(发现查找红线高度的时候,就是不断弹右栈,到最后红线就是栈顶高度),必须动态记录其对应答案。给左边加点的时候怎么办?加点涉及到弹栈和入栈,入栈简单,但弹栈如果弹掉了“顶高”以上的最小 dp 值对应点怎么办?此时必须 \(O(1)\) 计算“顶高”以上的新最小 dp 值。不妨给栈内每个点记录“从本点以下,一直到‘顶高’,其最小 dp 值是多少”,入栈时处理即可。那给右边加点时怎么办?入栈倒简单。弹栈时“顶高”下移,需要左边对应指针下移...
这太难了,下面只介绍题解做法 (*)。把左栈中的元素,按照右栈里的每个元素的高度分段,每一段都维护信息,弹右栈时相当于相邻两段信息合并,而且段不会分裂。对于一段,重要的实际只有段内的 dp 值后缀最小值(将靠左栈顶的一段称为“后”)。合并时,将两个后缀最小值数组对应合并,只需要删除一些元素,用链表实现,均摊正确。总复杂度 \(O(n\log n)\)。
记录“从本点以下,一直到段末,其最小 dp 值是多少”是我自己的想法,这个东西缩合连续段只记录拐点,就相当于所谓后缀最小值。所以体系之外的事实上只有:把左栈中的元素,按照右栈里的每个元素的高度分段。
T-163 QOJ17247 26-3-23 S
有一个 \(O(n^4)\) 的区间 dp,跟正解无关。
括号序列和二叉树可以互相转化,这个我们知道。但是其逆转化并不常见 (*)。具体来说,本题中将树 L-x-R 转化为 (L)R 的括号序列。我们对括号序列计数,翻译原有限制:将第 \(i\) 个左括号视作分配给节点 \(i\) 的,则节点 \(i\) 的中序遍历号码,就是第 \(i\) 个左括号的配对右括号。所以题目限制相当于说,钦定第 \(p_i\) 个左括号的配对,是第 \(q_i\) 个右括号。
我们知道括号序列计数,常常转化成类格路计数/取前缀和后上下震荡的模型。取后一个模型,那么强制某两个括号匹配,就意味着此两个括号处于同一基准线上,而且中间只准比基准线高。在已知的某个括号序列上(即强制匹配的那些括号构成的序列)想要 dp 做计数,需要把强制匹配的括号翻译成树形结构,先处理子树再搞父亲。做一个树形 dp,而两个儿子中间的那一段,没有什么额外限制,应该使用格路计数算方案数。其复杂度可以证明正确。
具体来说,在格路图(等价于前缀和震荡模型旋转四十五度的结果)上,以横轴为“右括号个数”,纵轴为“左括号个数”,则一对强制匹配的括号,处于同一斜率为正一的基准线上,且满足,终点横坐标为 \(b\),起点纵坐标为 \(a\)。信息不充分,还需要枚举一个额外值“长度”,就能描述这两个点了。定义状态 \(f_{x,l}\) 表示当前在新树形结构的编号为 \(x\) 的节点上,钦定其长度为 \(l\),子树方案数是多少。注意,无论如何,在 \(x\) 表示的匹配括号之间的那段折线,不得触碰基准线。
T-167 QOJ17398 26-4-7 S
若静态怎么做。首先 \(m\)(各个数字对它取模的余数相同)是质数最优。取边界元素 \(m=2\),假设当前集合大小 \(|S|\),易知答案大于等于 \(\frac{|S|}{2}\)。这是经典随机化套路:假设最优解 \(m\) 对应的集合是 \(T\subseteq S\),则任取两个 \(S\) 内元素,这两个元素同时位于 \(T\) 中的概率是 \(\frac{1}{4}\)。故只需多随几次,就能保证找出一对属于 \(T\) 的元素。
假设它们是 \(x,y\),那么 \(x=pm+r,y=qm+r\to x-y=(p-q)m\),这也是经典套路,故枚举 \(x-y\) 的质因数,并且把它当作备选 \(m\) 扫描一遍 \(S\) 即可。用这个办法解决非静态问题,算复杂度,容易求得 \(n\) 以下质因数最多的数的质因子个数 \(\omega\);每次询问的随机次数 \(r\) 应保证:\((1-(\frac{3}{4})^r)^q>1-\epsilon\)。大约是 \(O(qr\omega|S|)\) 的复杂度,其中 \(r\) 至少四五十吧,完全没有前途。
这是多个本质相同问题,尝试批处理。经典套路 (*) 是选取某个询问,找出对应的 \(S\),并将后面 \(\frac{|S|}{t}\) 个询问一并处理,例如取 \(t=4\),则集合内元素的改变个数不会超过 \(\frac{|S|}{4}\),故“在 \(S\) 中随机选两个”对任意一个本批内询问的“成功概率(这两个同时处于对应询问的 \(T\) 中)”,都至少是 \((\frac{3}{8})^2>\frac{1}{9}\)。所以处理过程是:若 \(i\) 对应集合 \(S_i\),在其中随机挑选 \(r\) 对数字,得到 \(O(r\omega)\) 个质因数,询问“上述各个质因数作为 \(m\),在第 \(i+j,j\le \frac{|S_i|}{4}\) 次询问的集合内的表现分别如何”,这容易扫描线解决。总复杂度应为 \(O(4qr\omega)\),这里的 \(r\) 要取到上百才合适,无法通过。
问题在于随机化造成的 \(r\) 无法接受。这种问题有一个经典的剪除随机化的方法 (*)。为了表述方便,以下阐述静态问题的解决方案,推广到动态问题,则跟上述方法完全一致。将 \(S\) 按照任意顺序写出(并未要求随机打乱)。然后每相邻六个分一组,组内元素连完全图共计 \(\frac{|S|}{6}\binom{6}{2}\) 条边,称边两端点都处于 \(T\) 中的是重要的边。因为 \(T\) 满足 \(|T|>\frac{3}{8}|S|>\frac{1}{3}|S|\),故 \(T\) 中元素最平均的出现方法(柯西不等式)就是每组内出现两个,这样就仅有 \(\frac{|S|}{6}\) 条边是重要的。换句话说,将每条边端点的差值 \(s_i-s_j\) 分解,得到 \(O(2.5\omega|S|)\) 个质因数,则合法 \(m\) 必须在这些质因数内出现 \(\frac{|S|}{6}\) 及以上的次数,这种 \(m\) 合计 \(O(15\omega|S|)\) 个。
所以(动态问题的)总复杂度 \(O(4q15\omega)\),能够通过。
T-168 P5811 26-4-8 S
问题与连通性有关,先建立圆方树。不妨令 \(a<b<c\),且 \(A,B\) 是要连通的两个集合。用调整法感受一下,\(A,B\) 两个集合能往各自的叶子方向不断退缩。无根树先定根,先枚举一个根,不妨钦定 \(A\) 连通块包含根。将 \(A\) 连通块选定并删去之后,图大致会分裂成若干棵子树的样子(如果删去后,各个分出的连通块仍然建立圆方树。但这并不准确),\(B\) 连通块必须完全属于上述某棵子树。换句话说,在这棵有根树上,似乎只要有一个子树内圆点个数属于 \([b,n-a]\) 即可完成构造?如果是这样,只需枚举圆方树上某条边和“边的方向”,就唯一确定一个“子树”,从而在 \(O(n)\) 的复杂度内解决问题?
并不太准确。事实上,如果所有点都不满足条件,问题仍可能有解。关键在于若一个“方子树”(以方点为根的子树,子树的根通过“所枚举的有向边指向的点”唯一确定)内含圆点个数超过 \(n-a\),那么 \(A\) 集合可能沁入“方子树”内部完成构造。我在 T-145 等处说过,先把已知变现,把已经解决的情况排除掉。现在只需讨论所有可能的子树大小,都小于 \(b\) 或者大于 \(n-a\) 的情形。
枚举该“方子树”的根方点。那么 \(A\) 集合必然选到了该点双内的超过两个圆点,且它涉及到的圆点,至多一个圆子树没有选满。这类似于将一个点双划分成两个部分,要求各自连通的问题。于是做双极定向 (*),按照定向的顺序排序,取一个前缀作为 \(B\),一个后缀作为 \(A\),由于双极定向的性质,前后缀各自连通。一个个地加入前缀的子树,某次发现计数器越过 \(a\) 时,立刻终止,然后构造。
证明正确性 (*):若存在圆子树超过 \(n-a\) 则该方点显然不可行;反之圆子树大小都小于 \(b\),所以计数器越过 \(a\) 后,至多为 \(a+b-1\),而剩余 \(c+1\) 个点留在后缀,且有 \(b<c+1\)。
虽然做完了,但是模模糊糊,跳步有点多,做法不严谨。那么另一种更准确的思路:把问题翻译到你选定的模型上。一个连通块在圆方树上的表现形如:所有属于该连通块的圆点满足,任两个圆点之间没有圆点不属于该连通块。换句话说,一个连通块在圆方树上也表现为一个连通块(把任两圆点之间路径上的方点也加入)。而两个连通块不能有交相当于:不能共用圆点。因为圆方树是圆方相间的,所以这两个连通块至多共用一个方点。
第一个,如果 \(A,B\) 对应的在圆方树上的连通块,不共用任何点怎么办呢?连通块转缝隙主体,此处的缝隙显然是一条边,而且因为是存在性问题,代价可重算。故枚举每条边,然后看它两端的圆点数目,一个要大于等于 \(a\),另一个要大于等于 \(b\),即可。
第二个,如果 \(A,B\) 恰好相交于一个方点。这意味着 \(A,B\) 集合各自选到了该点双内的超过两个圆点,且涉及到的圆点,至多一个圆子树没有选满。因为形如“点双,划分,连通性”,所以采取双极定向的方法,不再赘述。
T-169 QOJ14949 26-4-8 B+
在取模环上画出 \(a_l,...,a_r,v\)。那么必然是取一个位置断开,然后两边向 \(v\) 靠拢。换句话说答案应该是:用 \(m\) 减去“该取模环上,以上述 \(r-l+2\) 个点为断点,最长的区间长度”。
区间询问,不具备可合并性,直接排除序列分块、猫树。扫描线也不可行。只剩下莫队了。形如“往集合内插入/删除一个元素,问相邻元素之差的最大值”,超级经典的问题了。用 set 容易做到 \(O(n\sqrt n\log n)\)。
法一,带老哥莫队的优化,要么回滚,要么二次离线。痛恨加入操作,喜欢删除(可以环状链表),所以回滚莫队。我来介绍一下(按照痛恨删除喜欢加入的常规方式来说的,本题中需要反着理解):回滚莫队比较沙比的一点是,它虽能规避删除操作,但(例如按询问左端点分块处理)左端点所在块,必须能够维护“撤销上一步”操作(莫队过程:同一块内,\(r\) 不停增加,但 \(l\) 保持在当前块的右端点 \(B_r\)。每次询问时,令 \(l\) 减小直到合适位置,然后查询。查询完后 \(l\) 要归位)。如果做不到“撤销上一步”,就应该考虑 \(l\) 减小时不影响原数组的值,也就是把 \([B_r,r]\) 的状态复制一遍,在上面做正常修改(还是只加的),然后查询,之后把这个复制出来的数组丢弃。常见的做法不是上面那个,而是通过某种方式使得在不修改 \([B_r,r]\) 状态的情况下直接算出 \(l\) 减小一后的答案。注意回滚莫队和定期重构基本相同,其关键都在于,如何“添加最后 \(\sqrt n\) 个修改”,一般而言因为是每个查询添一遍,查询之间互不影响,所以这些修改的添加顺序是可以任意指定的。并且,因为你是对一个块扫一遍全局,所以甚至可以针对当前正在哪个块,而个性化地指定其扫描全局的方式——常见办法形如,把本块内的操作涉及元素高亮标出,特殊处理;或者据这 \(\sqrt n\) 个修改涉及的关键元素进行全局分段等。可对照 T-070。线段树分治又何尝不是这样,需要能够撤销上一步操作。
本题中不需要那么麻烦,因为“撤销上一步”是可以办到的。维护一个栈,记录几个信息即容易恢复链表的状态。至于每次查询时特殊的 \(v\),它只会影响一个段,所以只需动态维护当前最长段和次长段信息(包括长度、端点位置等)。特殊情况是“最长段、次长段被某次‘删除’合并了”。(*) 注意到如果发生这种情况,那么新最长段必然长于当前任意段的二倍,因此直接令新次长段为空段即可(如果没有新并段,那么无论 \(v\) 的位置,必然是最长段,或者最长段分裂后的两段,给答案贡献);后续删除节点并段的时候,再更新出“新次长段”的值。
法二,用回滚莫队加“操作涉及元素高亮标出”的办法,据这 \(\sqrt n\) 个修改涉及的关键元素(也就是指,回滚时本块的元素)进行全局分段,则每段内维护一个链表即可维护分段内的最远值;还有就是相邻段间对答案造成贡献的情形,每次查询时,遍历那 \(\sqrt n\) 个分段即可处理出“距离最大值”。但仍有小问题,\(v\) 怎么办呢:可以直接算出“若无 \(v\),则距离最大值,距离次大值及取到段的信息分别是多少”,依然存在法一所谓的“特殊情况”,类似地处理一下。
法三,用回滚莫队加“操作涉及元素高亮标出”的办法,进一步高亮标出块内修改涉及到的 \(v\)。这就需要带权回滚莫队:将 \(l=x\) 的查询次数记录到 \(a_x\) 处,从左往右扫计数器对 \(a_i\) 累计求和,每当计数器大于 \(\sqrt q\) 就新开一个块;每当本块长度大于 \(\sqrt n\) 也要新开一块。如果存在某个 \(a_x>>\sqrt q\),那么对 \(l=x\) 的询问们特殊处理,扫一遍真正的“只删除莫队”(无需撤销上一步)即可。这种做法不会出现“特殊情况”。
法四,不需要回滚,直接莫队但用压位 trie 查询元素的前驱后继也可,常数略大些。压位 trie 板子要背过啊。
总结一下:如果查询时存在临时修改,但无法真正在数据结构上做修改。因此直接查询出的最大值,可能不是所求的最大值(改后就可能不再是了)。如果修改涉及到的元素很少。那么同时维护最大值、次大值、... 即可。
T-170 QOJ14944 26-4-8 S+
和 T-031 有所类似。这种自由度比较高、对局面掌控力强的问题(构造、博弈。尤其是博弈),先把跟构造方案/决策方式有关的隐性限制去掉,只关心“构造方案/决策方式超级优秀”的前提下仍出现的一切限制,在最优化问题中相当于得到某种下界。得到“下界”的下一步就是证明能够达到下界;但即使达不到,也有助于你的思考。
() 我刚才说限制和决策无关,那么只和初始牌堆有关。对给定的初始牌堆,如何分析“下界”呢?关注已知的东西,和决策无关的东西,或者一定会被决策的东西。如果你要完成任务 \(i\),那么必然打出 \(a_i\),这张牌得等恰好 \(n\) 才转回来。() 这意味着什么呢?这意味着什么呢?是不是,是不是,是不是,下一个满足 \(a_j=a_i\) 的任务完成时刻必须比第 \(i\) 个任务的完成时刻要晚上 \(n\)。
所以设出第 \(i\) 个任务的完成时刻下界 \(f_i\),则 \(f_j=1+\max(f_{j−1},f_i+n)\)。边界情况(某种数字第一次出现)需要额外讨论。(*) 证明这个下界能够取到:每次如果能够完成当前任务就完成,否则打出离下一次投入应用的最远的牌。由题意根据鸽巢原理,时间间隔大于等于 \(2n\),远大于 \(n\)。
然后期望拆贡献,枚举 \(k\) 之后,求使得 \(f_m\le k\) 的初始排列数目。可以根据转移式往前倒推对 \(f_i\) 的限制(形如 \(f_i\le t\)),推到边界情况处,就得到“第 \(i\) 种数字的第一次出现位置要早于 \(p_i\)”的限制。做到 \(O(nm)\)。
我们能够写出 \(p_i=k+c_i\) 的通式(\(c_i\) 是常数)。所以时间复杂度降至 \(O(n^2+m)\)。
T-171 QOJ4892 26-4-8 B+
复杂限制,考虑图论。对元素取值的复杂限制,如果不是加和形的(提示差分约束),不是做差形的(提示切糕模型),那就是本题中的 2-sat。
这种 2-sat 的建图方法是:对于元素 \(x\) 拆 \(O(V)\) 个点表示 \([x\le a]\) 的零一性。复习一下,2-sat 的逻辑是把每个零一变量也拆成两个点,把限制翻译成“若 \(x=1\) 为真,则 \(y=0\) 也为真”(举例说),就让 \(x_1\to y_0\)。由逻辑推理,显然还需连反边 \(y_1\to x_0\)。所以,建立上述 \(O(V)\) 个点时,令 \(x_{a-1,1}\to x_{a,1}\),反边是 \(x_{a,0}\to x_{a-1,0}\),从而构成链式结构。
本题如何翻译呢?若 \(a_i>x\) 则 \(a_j\le x,a_k\le x\),对称地写三个式子。不过值域可能很大(值域大?拉插。离散化。证明只有很少的数字有用)。关注到,对于元素 \(i\) 的所有限制都与 \(x\) 有关,而这个 \(x\) 必须在某个要求 \((i,j,k,x)\) 中出现。所以总点数和边数都成线性的了。
T-172 QOJ17186 26-4-8 S+
我不懂啊,这是啥啊。
只需描述每个元素的深度序列 \(d_i\),容易发现 \(d_i\) 关于 \(w_i\) 单调。深度序列合法的条件是 \(\sum 2^{-d_i}=1\)。而我们希望按深度拆贡献,有经典结论 \(\sum\sum_{j=1}^{d_i} 2^{-j}=n-1\) (*)。换句话说,将元素按照 \(w_i\) 排序后,画出一个 \(n\times d\) 的表格,我们要选出若干个格子,使得重量等于 \(n-1\),代价最小。格子 \((i,j)\) 的重量等于 \(2^{-j}\),代价为 \(w_i\)。要求:每行必须选择一个前缀;每列也是选择一个前缀。
(*) 关注最后一列,显然必须选择偶数个。那么把第 \(2t,2t-1\) 个元素分成一组,则最后一列所选取的前缀,只会在某个组的间隙处终止。故把同组的两个元素视作“一个重量为原来之和、代价为原来之和元素”,把这些元素归并到倒数第二列里面去,问题不变。因此对于一个确定的 \(d\),递归执行上述过程,复杂度仅 \(O(nd)\)。
(*) 感受了一下,哈夫曼树的最优深度为 \(O(\log nV)\)。因此我们可以 \(O(n\log nV)\) 预处理(执行上述归并过程 \(i\) 轮后(只记录代价,不记录重量),直接求代价前 \(n-1\) 小的元素的代价之和,存到 \(\mathrm{ans}_i\) 中即可,询问的时候直接返回 \(\mathrm{ans}_d\) 就行了)。
T-173 QOJ17427 26-4-8 S
(*) 首先令 \(p_i\gets p_i-i\) 那么每次企鹅可以视为和目标企鹅重合。不过如果某个企鹅掉到洞里,那么洞到下一个企鹅的距离必须增加一。注意到没有保证 \(\sum n\),所以大概率是 \(O(n^2)\) 预处理。改主体拆贡献,对于两个企鹅之间的路程,它被经过的期望次数,只跟企鹅数目有关,但跟路程实际长度无关。
我们需要求解:现有 \(n\) 只企鹅存活,从现在到游戏结束,从左往右第 \(i\) 段路程(第 \(i,i+1\) 两只企鹅之间的路程)的期望经过次数是多少。用递推和解方程混合求解。对于 \(f_{n,i}\),有如下几种可能:第 \(i\) 段左侧企鹅往右走;第 \(i\) 段右侧企鹅往左走;第 \(i\) 段左侧企鹅往左走;第 \(i\) 段右侧企鹅往右走;有企鹅掉洞;无关企鹅行动。
至于边界“每次掉洞,距离加一”的问题,可以特殊处理:定义状态 \(g_i\) 表示现有 \(i\) 只企鹅存活,设从当前状态一直到游戏结束,离散随机变量“左洞掉洞次数 \(X\)”,则 \(E(X(X-1)/2)+E((i-X)(i-X-1)/2)\) 是多少(也就是 \(E(X^2/2)+E((i-X)^2/2)-E(i/2)\))。这个可以按照高次期望的常规手段 \(E_1(x^2)\gets E_0(x^2)+2E_0(x)+1\) 解决:\(g_i=g_{i-1}+\frac{1}{2}(f_{i-1,0}+f_{i-1,i-1})\)(导致存活数减少的那一次运动,是左边还是右边企鹅掉洞,概率相等为二分之一。换句话说,在 \(i\) 只企鹅的 \(X\) 分布列下,向 \(i+1\) 只企鹅的分布列递推时,有二分之一概率 \(X+1\)。如果 \(X\) 增加一,那么因为 \(E((X+1)^2/2)+E((i+1-(X+1))^2/2)-E((i+1)/2)=E(X^2/2)+E((i-X)^2/2)-E(i/2)+E(X)=g_i+f_{i-1,0}\))。
T-174 QOJ17426 26-4-9 S+
用描述法,只需描述一棵有根、叶节点有标号的满二叉树(每个节点要么两个儿子,要么为叶子),以及所有非叶节点的黑白两色(表示与还是或)。尝试调整法,第一个是试图在不改变结构的情况下改换颜色。从小的开始,一次调整如果只涉及一个节点,难以观察。如果涉及两个节点,我们希望两个节点关系比较大,不妨设为父子关系。换句话说,对于 ((A op1 B) op2 C) 的一棵树(A,B,C 都是子树),如果调整 op1,op2 会发生什么?先考虑不劣调整(代价不变,也就是说或点数不变的调整),例如 (A&B)|C --> (A|B)&C。拆位转零一序列,那么只需证明对于 \(2^3\) 种 A,B,C 的取值,均有前者大于等于后者。你会发现我所给出的例子确是不劣调整。因此没有任何与操作处于任何或操作的子孙位置。换句话说先或再与不劣。像这种两个操作的问题,有时确有类似的结论,需要注意。
扩充一下:这种对二元相邻元素的操作问题,转化为有根、叶节点有标号的满二叉树后,如果希望运用调整法改变结构呢?使用 treap 的 zig-zag 操作试试看!经过证明,平衡树 zig-zag 能够将任意上述树变成任意其它树,所以是一个非常优秀的调整。为了防止忘记,我把 zig-zag 贴在这里 ((A op1 B) op2 C) <-> (A op1 (B op2 C))。注意 A,B,C 依旧代表子树。
先或再与,不妨分两步“逐步”描述,先描述或操作进行结束后的结果,就得到若干连续段;而与操作就是把这些段与起来。故只需描述“或连续段的划分方法”即可。对这个描述法,有一个 \(f_{i,j}\) 的 dp 表示恰好将前 \(i\) 个元素划分为若干连续段,使得“连续段内元素或值”的与结果为 \(j\) 的情况下,最小代价是多少。
我认为 dp 中非常重要的一个概念是转移 dag,只要能够按 dag 的拓扑序,快速地描述所有边,就能处理转移。对于本题,一条边形如 \((i,j)\to (k,l)\) 满足 \(j\ \mathrm{and}\ \mathrm{or}_{x=i+1}^k a_x=l\)。为了描述所有无论优劣的边,本质上需要 \(i,j,k\) 三个元素。为了加速转移,注意到经典结论 \(\mathrm{or}...\) 随 \(k\) 变化 \(O(\log V)\) 次,故将上述结果一致的 \(k\) 们合并受贡献(“贡献”相同,并段),在线的区间取 min 单点查询最小值,得到 \(O(nV\log V\log n)\) 的一个做法。更进一步地,因为区间左端点单调递增,查询点编号单调递增,而且查询点永远比当前所有已知的区间左端点都要大,用单调队列做到 \(O(nV\log V)\)。
注意到答案很小,考虑状态和答案互换,但是没有单调性。想到删除无用状态,对一个 \(i\) 而言,无用状态 \((i,j)\) 的标志是存在 \(k\subseteq j\),但 \(f_{i,k}\le f_{i,j}\)。想到删除无用转移边 (),一个转移 \((i,j,k)\)(用 \(i,j,k\) 描述的,形如 \((i,j)\to (k,l)\) 的转移边,\(l\) 能够通过 \(i,j,k\) 算出,\(l=\mathrm{cal}(i,j,k)\))无用的前提是存在 \((i',j',k)\) 满足 \(f_{i,j}\ge f_{i',j'}\),但 \(\mathrm{cal}(i',j',k)\subseteq \mathrm{cal}(i,j,k)\)(称这种情况下 \((i',j',k)\) 优于 \((i,j,k)\))。我推荐大家在考察无用状态/无用转移边的时候,选择弱化可能性,只允许一两个维度灵活变动然后看“弱化版条件”带来的性质(像做调整法时减少可能性那样):考察转移边 \((i,j,k)\),如果只在定下 \(j,k\) 的范围内观察是否存在比它优的边,它是有效边的弱化版条件,又是什么:因为 \(l\) 随 \(i\) 单调,所以只要 \(\forall i'\le i,f_{i,j}\le f_{i',j}\) 则 \((i,j,k)\) 是弱化版有效边。() 而任意时刻,对于给定的 \(j\),沿 \(i\) 一维后缀最小值的数目不超过两个(因为若只转移弱化版有效边,则 \(i<k\to f_{i,j}+1\ge f_{k,j}\) 满足。否则根据上述定义,转移 \((i,j,k)\) 必优于任何 \(i',j'\) 满足 \(\mathrm{cal}(i',j',k)=j\) 造成的转移 \((i',j',k)\),从而这些 \((i',j',k)\) 都不能是弱化版有效边),做到 \(O(nV)\)。
所以说,成天嚷嚷的“dp 数组要注意观察单调性”其实就是“寻找有效转移边”的一个侧面。我们定下状态以后,应该先考察哪些是(弱化版)有效状态(状态与答案互换也被这一步骤严格包含了),再据此考察哪些是(弱化版)有效边。有效状态当且仅当不存在状态比自己优秀(状态之间存在某种偏序形如 \(x\le y\),如果 \(x\le y,f_x\le f_y\) 一定成立则状态 \(x\) 比 \(y\) 优秀);边 \((x,y)\) 有效当且仅当一切以 \(z,z\le y\) 为目标的转移 \((w,z)\),都满足 \(f_x+c_{x,y}\le f_w+c_{w,z}\)。但是注意,一定要对条件大胆弱化(弱化就相当于改变 \(x\le y,f_x\le f_y\) 的定义。例如原本状态 \(x=(a,b)=aN+b\) 是 pair 型数据,偏序为 \((a,b)\le (c,d)\to aN+b\le cN+d\),可弱化其偏序为 \((a,b)\le (c,d)\to a=c,b\le d\)。还可以更改 \(f_x\le f_y\) 的定义为数值上的 \(f_x=f_y\) 等等),直到“弱化版有效状态/弱化版有效边”的组合意义特别明显时才足够。
T-175 P15950 26-4-13 B+
关注无解性,考虑到“无解性”是在把一类图变现,这类图将不再值得考虑,因此值得考虑的图将具备良好的性质(这就是分类变现的意义所在,如 T-168 等所述)。所以大胆猜测,无解的图非常广泛,例如有环。而有环的图真的无解:一个图无解的定义是,存在另一个图,与它无法通过询问操作区分,换句话说任意询问操作,两个图的回答都一样。只需将某个有环图的一个环边方向翻转,则新图和旧图无法区分。现在只需考虑 dag,猜测 dag 都是有解的。
对于 dag 选用归纳构造,自然是拓扑排序,需要逐步找到入度为零的点,而判断一个点当前入度是否为零很容易,只需将“当前未删除的点都涂成高压”与“除了待检查点,其他未删除点都涂成高压”做比较。只需像真正的拓扑排序那样,每次删边 \(x\to y\) 就检查 \(y\) 的零度性并酌情入队,是 \(O(m)\) 的。关键在于找出 \(x\) 的所有出边,允许带老哥。那不是二分就是分治,核心都一样:需要判断某个集合 \(S\) 是否被 \(x\) 连了出边,而且保证 \(S\) 都是未被删除的点,\(x\) 是刚被删除的点。那还不容易,“未被删除的但不属于 \(S\) 的涂高压”与“未被删除的但不属于 \(S\) 的、\(x\) 都涂高压”比较一下就行了。二分就是二分编号的前缀,分多次找出“现在的第一个被 \(x\) 连向边的点”。分治就是类似势能线段树的搞法,如果子区间内有点就递归下去。
T-176 QOJ15437 26-4-13 B+
T-116-2 指出,图论题目的要点,第一是找出题目图的特殊性质(题图是不是:树/仙人掌/dag/竞赛图/平面图/广义串并联图/弦图等等;题图经过缩点处理后,一个分量内部是否具备良好性质,考察一个分量内部的性质,可以利用耳分解-子图添点方法),第二是尝试缩点,第三是利用生成树,第四是采取广义的广义串并联图方法,第五是采用数量关系(点数/边数/度数)来关心图的状态,第六是尝试归纳(按照某种顺序逐渐添点和边,或者逐渐删点和边,递归成规模恰好小一的子问题)。
本题采取生成树办法。编码器按照给定环为根建立 bfs 生成树,然后对于每条边令“距离环近的”连向“距离环远的”(至于环边,按照环的顺时针/逆时针连)。这样大概率得到了一个 dag,但是一条边的两个端点距离环一样近怎么办。不妨钦定“距离环一样近”则按照节点编号比较,定向的结果一定是 dag(不考虑给定环)。
解码器则需要找环了,编码器发出的图是不是只有一个环呢?不是,因为如果原图的给定环上点之间有边,则这些边必然造就新的环。然而发出图只有一个大环和其上的一些弦边。那怎么办呢?介绍一下找环的算法:求一个环用 dfs/bfs,求一群环用 tarjan/广义的广义串并联图方法(在此就是拓扑排序啦)。选择拓扑排序方法,即可找出大环的点集本身,然后随便做就行了,比如说对大环导出子图随意建立一棵 dfs 树,把横叉边都加上(对应删除一条树边,就是横叉边末端点与它父亲之间的那条),返祖边和前向边都删去即可。或者将边的方向都取消,然后应用广义串并联图方法,每次删一度点,缩二度点,叠合重边。
顺带一提,环的常见动作还有:破环为链。有向图里常常体现为 \(x\to y\) 的一条边和 \(y\to x\) 的一条路径。
T-177 ARC165E 26-4-13 B
期望拆贡献,求每个点被涂黑的概率之和。枚举点 \(x\),它能否被涂黑(类似于零一权值)取决于第一次选择它时所在连通块的形态,描述这个形态。
则第一次选择 \(x\) 时,边缘外一层的 \(a\) 个点都被涂黑了,内部的 \(b\) 个点都是白色。只关注元素的第一次选择时刻,则这些时刻的相对顺序构成了一个排列,不同排列出现概率完全相同,且问题只和排列的形态有关。因此能够涂黑 \(x\) 的充要条件就是:第一,所描述的连通块大与等于 \(k\),第二,边缘处 \(a\) 个点在排列中位于 \(x\) 之前,内部 \(b-1\) 个点位于 \(x\) 之后(因为所描述连通块内的任何点,只要位于 \(x\) 之前,那么它当初就一定被涂黑),其概率是 \(\frac{a!(b-1)!}{(a+b)!}\)。
用树形 dp 去描述包含 \(x\) 的所有连通块的内部点数和边缘点数,就是两维树上背包,还得枚举根节点 \(x\),复杂度 \(O(n^5)\)(容易证明,树上背包复杂度是 \(n\) 的“维度乘二”次方,“维度”是指与背包容量等地位的状态维度)。权值的计算(零一、概率)只依赖连通块形态,故更改主体为连通块。套路说,主体是连通块时,常常以“深度最浅节点”为代表元计入该连通块的贡献。因此任取一个根做上述 dp,每个状态 \((u,a,b)\) 给答案做 \(f_{u,a,b}[b\ge k]b\frac{a!(b-1)!}{(a+b)!}\) 的贡献即可,做到 \(O(n^4)\)。
T-178 QOJ9798 26-4-13 B
刻画单调且高度和为 \(V\) 的直方图,有两种办法:从左到右依次“逐步”描述每个点的值;往直方图的末端添一个初始高度为一的柱子,或让直方图当前所有柱子增高一。通过根号分治平衡这两个:要求前一种办法里,每个点的值都低于 \(\sqrt V\),要求后一种办法里,每个柱子的初始高度都是 \(\sqrt V\)。最后用组合数卷积,把两个 dp 数组合并即可,总复杂度 \(O(nV\sqrt V)\)。
T-179 ARC148E 26-4-13 B
排列计数/序列计数问题。法一,从左往右逐一确定当前位置的值在前缀中排第几大,有一维状态是,当前元素在它和它前面的序列里排第几;法二,对已知的前 \(i-1\) 个数间“相对关系构成的小排列”,在它的末端(下标为 \(i\) 的位置)添加一个值为 \(i\) 的数字,然后决策这个 \(i\) 应该改为插入到原排列的哪两项之间(原排列分裂放两边);或者是决策这个 \(i\) 应该与原排列的哪一项做交换类似于错排问题。法三,值域轴放外面。每次确定值等于 \(i\) 的位置是谁,可关注连续段,这个连续段可能就是合法段,最终是要求整个排列都合法;或者是实时描述值小于等于 \(i\) 的所有元素构成的子序列形态。
本题中,值域轴放外面比较合适。关键在于 \(a+b\ge k\) 的限制与元素的和有关,这就不好直接扫描。不妨将一个指针从零开始扫到 \(i\),另一个同时从 \(k\) 扫到 \(k-i\),直到两个指针重合。也可认为是 \(a\ge k+(-b)\),通过一个变换 \(t_x=k-a_x\),把元素的和限制变成了相对大小限制。
T-180 AGC020F 26-4-13 A
判定合法性,只需询问:是否存在一个排列使得 \(r_{p_i}>l_{p_{i+1}}\) 等等。由此可见,判定性问题只和端点间的相对大小关系有关,这涉及到整数部分和小数部分的联合比较。实数轴上的相对大小问题,有一个经典扩倍的思路 (*),就是把每个单位长度分成 \(c\) 份。
\(O(n!)\) 枚举各个小数部分的相对大小关系。然后从原点开始顺时针转一圈,考虑哪些圆弧已经起始,当前的所有圆弧向后最多覆盖多少,不过还需枚举“跨过原点的圆弧最多向后覆盖多少”这一数值,做到 \(O(n!2^n(nc)^3)\),无法通过。
我不知道如何 (*) 想到把最长的线段的起点拿出来当作原点,这样的话,因为不存在包含它的线段,所以无需考虑“跨过原点的圆弧”的贡献。做到 \(O(n!2^n(nc)^2)\),可以通过。
T-181 P8522 26-4-13 A
显然要倍增。因为能力值值域过大,所以采用以步数为状态,值域为答案的倍增。可以维护:从 \(x\) 开始连着输 \(2^t\) 次,带来的收益,还有所需的最高初始能力值。这个做法能够通过 sub 2,因为每输一次,当前能力值必然翻倍,所以只会有 \(O(\log V)\) 段极长的赢/输段。
考虑 sub 4,\(O(5)\) 扫描值域 \(i\),维护若当前能力值大于等于 \(i\) 但小于 \(i+1\)(离散化后),则倍增的情况如何,此时不用讨论输赢,因为跳的结果已经注定,只需计算从 \(x\) 开始连着跳 \(2^t\) 次带来的收益,据此判断跳多少以后就该升级了(令 \(i\) 增加)。
对于整个题目,介绍倍增分块。它适用于“对块 \([B^k,B^{k+1})\) 内元素的特殊操作,元素必然增加 \(B^k\),故暴力进行特殊操作能够接受”的情形。按照 \(s_i\) 的值域进行倍增分块,如果某个 \(s_i<B^k\) 则必然赢,如果 \(s_i\ge B^{k+1}\) 则必然输,将这些边强制建立;反之,只要赢非强制赢的一局,能力值就增加 \(B^k\) 及以上,因此在本块内套用 sub 2 的做法即可做到 \(O(B\log V)\) 处理一块。总复杂度 \(O(n\log_B V\log V+qB\log_B V\log V)\)。
顺带一提,把特殊操作拿出来分析,往往发现它进行的次数不太多,比如老哥或者根号量级。
T-182 QOJ7203 26-4-13 A+
离线和在线都能做。不依赖 \(a,b,c,d\) 的值域。
对每个询问,只需找出第一个不等于它的,和最后一个不等于它的位置。
法一,本题有三个轴,时间轴,四个编号轴和值域轴(与位置轴重合)。选择每次询问二分值域轴,转化为平衡树上二分,只需判定本节点的子树内有没有不等于 \((a,b,c,d)\) 的节点 \((a',b',c',d')\)。神秘的转化 (*),因为复杂限制不好处理,尝试转化为数值问题(对数据有亲和力),尤其是可以加和的数值问题。那么 \((a-a')(b-b')(c-c')(d-d')\) 的和就是一个好的数值。只需把 \(abcd\) 构成多项式的系数维护出来,就能方便地求出一个节点子树内上述值的和,如果和为零,则没有不等于询问四元组的节点。不过有点问题,因为加和可能存在抵消的状况,只需对每个节点赋一个随机值 \(w_i\) 使之权值为 \(w_i(a-a_i)(b-b_i)(c-c_i)(d-d_i)\) 即可。
法二,这类问题的通法是,构建决策树:对 T-003 的重要修正。例如求最小值时,决策树先维护出全局最小值四元组,需要判断询问四元组和它是否相等。如果不是那么输出;反之按 \(abcd\) 顺序找出第一个相等的位(例如 \(b\) 位),则我们的决策树需建立“\(b\) 位不和全局最小值相同的四元组中,最小的四元组是哪一个”,并递归到这个节点(称为“次级节点”)去。如果这个询问四元组仍和该节点相等,那么按照 \(acd\) 顺序找出第一个相等的位(已知 \(b\) 位正确了。故无需找它;假设这回是 \(c\) 位),决策树需建立“\(b\) 位不和全局最小值相同,且 \(c\) 位不和次级节点相同的四元组中,最小的是哪一个”。只要实时维护这棵树就够了,一个 \(d\) 维决策树的大小 \(f(d)=df(d-1)=O(d!)\),每次暴力重构即可。如果 \(d\) 较大,因为痛恨修改操作,可以改成分块定期重构。
T-183 P9152 26-4-13 A+
静态 dp 只需维护 \(f_x,l_x,r_x\) 表示以 \(x\) 结尾的 dp 值,以 \(x\) 为最浅节点的极长笛卡尔树上向左链 dp 值的和,还有向右链的和。对于数据随机,考虑莫队,若新添/删除叶子节点 \(x\)(\(l\) 一边的操作)则暴力 \(O(\log)\) 更新到当前根(\(x\) 的当前存在的最浅的祖先);若 \(r\) 一边操作,则 \(O(1)\) 计算自己的 dp 值即可。
初始化变来变去的套路:逆建转移图。若只有 \(l\) 一边操作,可以通过矩阵和树剖,算出从当前根到修改节点的逆转移“贡献矩阵”,然后直接给答案加上这个值,这只能保证答案时时刻刻是对的。但是还有对 \(r\) 的操作,而无法处理当前所有 \(l\) 侧修改节点对 \(r\) 侧操作的贡献和影响。采用回滚莫队,使得 \(r\) 始终向大扫描,那么操作 \(l\) 时也就只需处理它对当前根 dp 值的影响,这也容易。注意 dp 值指代那个三元组,需要矩阵计算。
不过树剖的复杂度还是太可怕了。(*) 矩阵可以求逆,从而采用到根链差分的办法。这就做完了,\(O(n\sqrt n)\) 带一点常数。

浙公网安备 33010602011771号