我的座位上有一本红楼梦
前言
如果我的座位上有一本红楼梦。
如果我每天都看红楼梦。
如果我看到了贾宝玉初试云雨情。
如果我初试云雨情??
我也要试吗??我吗??我不是贾宝玉。
如果我集训期间的座位上有一本红楼梦……
\(9.15\)
\(100+100+0+30\)
任务领取
每条边只会指定一个点,那么最后一定会剩下一个点没有被指定,所有边就构成了以该点为根的一棵外向树。
枚举根,删边时间可以等价于删点时间,对所有点的删除时间数组进行计数,发现本质上是树的拓扑序,对于给定根不难做到 \(O(n)\)。
再写个换根就过了。
染色结果
这类问题可以直接考虑对 \(c\) 计数,那么需要 \(c\) 合法的充要条件:
-
相邻点颜色不同。
-
颜色为 \(c\) 的点,其周围必须要有 \(0 \sim c-1\) 的每一种颜色。
这样的话大概就能 \(\text{DP}\) 了,但是复杂度和颜色范围关联很大。
事实上,这种和 \(\text{mex}\) 有关的题目有很多规模上的性质:
考虑一个点 \(u\) 最终颜色为 \(c\),那么其周围必须要有 \(0 \sim c-1\) 所有点,这些点周围又会递归出很多点,且点 \(u\) 对它们无法产生贡献。
那么归纳可得所有点颜色的最大值 \(\leq \lfloor \log_2 n \rfloor\)。
定根,设 \(g_u\) 表示不考虑父亲时,点 \(u\) 可能的 \(\text{mex}\) 最大值。
设 \(h_u\) 表示点 \(u\) 实际上可能的 \(\text{mex}\) 最大值,有 \(h_u=\min(g_u+1,\lfloor \log_2 n \rfloor)\)。
计算 \(g_u\) 时,将所有儿子的 \(g_v\) 递增排序,从 \(g_u=0\) 开始,每次遇到 \(g_v \geq g_u\) 就令 \(g_u\) 增加 \(1\),相当于是能力小的孩子先匹配较小的颜色。
关键性质:
考虑点 \(u\) 满足 \(g_u=k\),那么它周围就至少有大小为 \(1,2,4,8,\dots,2^{k-1}\) 的子树。
在去掉其重儿子后,它的所有轻儿子大小之和至少有 \(\sum_{i=0}^{k-2} 2^i=2^{k-1}-1\)。
那么就有 \(2^k = 2(2^{k-1}-1+1) \leq 2(\sum_{v \not= hson_u} siz_v+1)\)。
而我们知道,一棵树上所有轻儿子的大小之和是 \(O(n\log_2 n)\) 级别的。
有了该性质之后,我们能够编写一些指数级的算法,此时 \(\text{DP}\) 是容易的,根据转移时候容斥或不容斥能够得出不同的做法。
同类分段
\(\text{Part I}\)
记 \(S_{l,r}\) 表示 \([l,r]\) 内颜色构成的集合,一个三元组 \((l,m,r)\) 合法即为 \(S_{l,m}=S_{m+1,r}\),关键是这等价于 \(S_{l,m}=S_{m+1,r}=S_{l,r}\)。
一个区间可能存在多个合法的分割点,但是只能计算一次,考虑钦定一个最早的分割点。
由于 \(m\) 越小时,\(S_{m+1,r}\) 越可能合法,所以最早的分割点其实就是区间内所有数首次出现位置的最大值,记为 \(p\)。
反过来,如果沿这个位置切开都不合法,那么该区间就不可能合法,故沿这个位置切开合法是区间合法的充要条件。
具体地,\([l,p]\) 已经是全集,只需要让 \([p+1,r]\) 也是全集即可,这等同于对于所有 \([l,p]\) 中的数,其下一次出现位置都不能超过 \(r\)。
即 \(\forall i \in [l,p],nxt_i \leq r\)。
换个角度看,其实我们也可以找到区间内所有数最后一次出现位置的最小值,这是使得右半部分为全集的最优位置,记为 \(q\)。
那么区间合法的充要条件也可以刻画为 \(p < q\)。
\(\text{Part II}\)
考虑类比极小极大 \(\text{mex}\) 区间的技巧,定义一个极小合法区间为删去任意一个端点都不合法的区间。
结合 \(\text{Part I}\) 的性质,通过较为复杂的条件推导,是可以容易地用线段树求出所有极小合法区间的。
然后对于每一个极小合法区间 \([l,r]\),可以类似地用线段树求出其对应的极大合法区间 \([L,R]\),那么左右端点属于 \([L,r] \times [r,R]\) 的所有区间均合法。
这是一个矩形面积并。
当然可以发现更多地性质:若两个矩形相交,则它们对应的 \(L\) 和 \(R\) 一定相同,这样可以帮助我们简单地完成这个面积并。
\(\text{Part III}\)
直接考虑扫描线,枚举 \(r\),那么所有的 \(l\) 所对应的 \(q\) 必然是分成了很多个单调的段的。
对于每个段,\(l\) 合法需要 \([q+1,r]\) 中的数的上一次出现位置都 \(\geq l\)。
那么设该段的左端点为 \(lim\),其对答案的贡献即为 \(\max(0,min_{i=q+1}^r pre_i-lim)\)。
这个东西用单调栈或者线段树都是容易维护的。
时间复杂度可以做到线性。
日记
刘姥姥找王熙凤借到钱了。
刘姥姥为什么不找王熙 \(r\) 借钱。
刘姥姥这也太卑微了,“王熙凤拔根汗毛比刘姥姥的腰还要粗”。
王熙凤准备给丫鬟做衣服的那 \(20\) 两银子随手给了刘姥姥,百度说是普通人家庭一整年的收入,但是在贾府只能办一次螃蟹宴,还拿去做衣服,这差距也太大了。
王熙 \(r\) 能给我 \(20\) 两银子不?
晚上吃完饭回机房路上吹秋风好爽,再想到短期内可以一直学 \(\text{OI}\),感觉很幸福。
为什么我赛时没切掉这个 \(\text{T3}\),我要生气了!!!
电脑充电器坏了,不过第二天就换掉了。
为什么 \(\text{jiangly}\) 要一边想一边讲??我要走神了。
为什么新高一同学有一个那么像队长,为什么还有一个那么像张铭哲??性格和外貌上的。
\(9.16\)
\(\text{Choose Your Queries}\)
直接考虑建图,每条边选一个端点改变状态。
每个连通块分开考虑,跑出 \(\text{dfs}\) 树,在树上去调整很容易达到下界。
两年前的我还是太菜了。
\(\text{Coloring Torus}\)
按对角线构造,然后再按对角线去插入新颜色。
太神了。
\(9.17\)
\(100+25+0+5\)
\(\text{Hodge}\)
限制和最大值相关,考虑建出笛卡尔树,那么连边形式就是左子树内所有点向根连边,根向右子树内所有点连边。
在不考虑修改的情况下,可以根据这个写出一个 \(\text{DP}\)。
由于笛卡尔树本身是一棵 \(\text{Treap}\),且输入数据随机,所以我们可以使用 \(\text{Treap}\) 来维护这个动态 \(\text{DP}\)。
由这个题也可以得知随机规模为 \(n\) 的二叉搜索树的期望深度是 \(O(\log_2n)\) 的。
\(\text{Birch-Swinnerton-Dyer}\)
如果直接 \(\text{DP}\),在分配点 \(u\) 的连接情况时,若存在儿子 \(v\) 是 \(u\) 的接力,则转移是容易的,但是如果不存在就很难做了。
题解通过构造容斥系数,把答案变成了,所有接力的权值之积,而单个接力的权值是所有划分方案中块的乘积再求和。
这其实等价于全局找一个划分方案,把所有块权求乘积,再对所有方案求和。
那么直接对划分方案做 \(\text{DP}\),并乘上其对应的排列个数即可。
\(\text{Navier–Stokes}\)
\(9.20\)
\(100+100+100+9\)
蜗蜗的灯光预案
看到平方考虑完全平方公式拆开。
不过我更喜欢多项式相乘这种组合意义的说法,相当于集合里面随便选两个。
然后我们要求的是这个:
注意到操作是异或,所以考虑直接把最右边的乘积也看成多项式相乘,拆成两个位的乘积。
那么我们要求的就是 \(h_{i,j,x,y}\) 表示有多少种方案满足 \(2^x \in a_i,2^y \in a_j\),这里也可以转成概率,会更直观,也是老套路了。
下午自己想到这里的时候又痴迷于 \(\text{DP}\) 无法自拔了,想了很久没想出来怎么算,以后一定不要忘了计数可以组合啊!
考虑每个操作的影响,将所有操作关于 \(a_i\) 的第 \(x\) 位以及 \(a_j\) 的第 \(y\) 位的包含情况进行分类。
一共可以分为 \(4\) 类,而我们只在乎其中每一类选取个数的奇偶性。
每一类中,选取个数为奇数和偶数的方案数是相同的,这里可以看成是一个简单的对称性计数的 \(\text{trick}\)。
所以单个 \(h_{i,j,x,y}\) 是不难 \(O(1)\) 算出的。
总复杂度 \(O(q \log_2^2 V + n^2 \log_2^2 V)\)。
\(9.22\)
\(65+0+0+5\)
🚇
找到充要条件后,发现限制只和 \(d\) 数组的差分相关。
所以直接把 \(d\) 做差分,记为 \(c\),并且将答案改写成和 \(c\) 有关的形式:\(\sum_{i=0}^{n-1} b_i \times c_i\)。
每个 \(c_i\) 存在范围,会修改,而 \(b_i\) 永远不变。
考虑贪心,由于要保证 \(c\) 的和为 \(0\),所以每次必定会选择 \(b\) 最大的位置将 \(c\) 加 \(1\),然后把 \(b\) 最小的位置将 \(c\) 减 \(1\)。
按 \(b\) 递增排序,最终的形式一定是从某个位置 \(p\) 分开,前一半均为 \(-L_i\),后一半均为 \(+L_i\),而 \(c_p\) 是用于补成和为 \(0\) 的位置。
线段树二分即可。
\(9.24\)
\(100+50+0+15\)
钥匙环
垃圾题。
对每个颜色判断合法性,把不合法那些块全部打标记,这里需要用到虚树。
然后最后剩下的一定是一整个连通块,它们要么全部合法要么全部不合法,跑一次判断即可。
子集异或
考虑刻画 \(F(l,r)\),把区间内所有数排序,然后依次加入:
维护 \(x\) 表示当前能够凑出 \(0\sim x-1\) 的所有数,初始 \(x=1\)。
然后每次加入数 \(v\) 时,若 \(v \leq x\),则 \(x \leftarrow x+v\),否则 \(F(l,r)=x\)。
关键观察是把区间内所有数倍增分组为 \([1,2),[2,4),[4,8) \dots\),则可以证明一组内的数要么都不被吸收,要么全被吸收。
则枚举 \(\log_2 V\) 个值域区间,统计序列上所有区间的贡献即可,记 \(g_r\) 表示满足 \([l,r]\) 能够吸收当前值域区间的最大 \(l\)。
利用 \(g\) 的单调性可以双指针求出答案。
序列划分
感觉建图方式非常不人类。
若 \(i<j\),满足 \(p_i<p_j\),则连无向边 \((i,j)\)。
在得到的图上考虑每一个独立集 \(S\),则原序列合法的充要条件是 \(|N(S)| \geq |S|\),这个非常不显然。
则我们的目标是通过删点,使得 \(\exists S,|N(S)| \geq |S|\),因为 \(N(S) \cap S = \emptyset\),所以答案即为:
注意到 \(S\) 在原序列上是单调下降的子序列,直接 \(\text{DP}\) 即可。
\(9.26\)
\(100+20+0\)
这是第二题
为啥我挂了 \(40\)。
考虑子任务 \(1\) 的做法是每个白色四宫格和每个黑色四宫格本质相同,所以只需要暴力维护 \(8\) 个格子的变化情况。
但是加入了操作 \(2,4\) 之后前面的性质就不满足了。
直接把整个矩阵沿边界无限做对称,然后每个同色四宫格又本质相同了??!!!?!
\(9.28\)
\(\text{AghaBalaSar and Hamed}\)
单调栈可以求出 \(i\) 左边第一个比自己大的 \(l_i\),还可以求出 \([l_i,i]\) 中能一步到 \(i\) 的数的个数。
然后疯狂分讨就可以了。
\(\text{Kia Kio and Tree of Life}\)
考虑每个区间会在多少个方案中出现。
把整个区间当成一个点,放进原序列做二叉树划分,然后再把区间内做二叉树划分,方案数应该是两个卡特兰数乘起来,而且只和区间长度有关。
设 \(w_t\) 表示所有长度为 \(t\) 的区间的代价和。
由于代价和异或相关,不好处理,所以直接拆位。
考虑每一位对 \(w\) 的贡献,把 \(0\) 和 \(1\) 所在的位置数组做差卷积即可。
时间复杂度 \(O(n\log_2n \log_2 V)\)。
\(\text{Minister}\)
\(\text{Min Max Matrix}\)
\(\text{Astana Hard Metro}\)
\(\text{Cost of Conflicts}\)
\(9.29\)
\(100+100+25+35\)
我不管,我只是没特判而已,我只是暴力没写完而已。
牢板神了吧,还嫌题不够多吗??
我真的要做不完了。。。怎么事情这么多,有点排不过来了。。
还好,明天是摆烂日。
什么红卡后面忘了
先考虑怎么判定一个 \((A,b)\) 是否合法。
由于 \(A\) 的形式很像邻接矩阵,所以可以尝试放到图上观察。赛时觉得 \(A_{i,j}\) 必须表示 \(i\) 到 \(j\) 的边数,遂没什么想法。
呃,太唐了,\(A_{i,j}\) 就表示两端点权值和就行了。
对于每个连通块分开考虑,若块内存在奇环,则可以解出块内所有的 \(x\),否则该块是一个二分图。
对于二分图,可以将某一侧点同时加上 \(v\),然后把另一侧点同时减去 \(v\),并不会影响 \(A\) 的合法性。
尽管如此,对合法的 \((A,b)\) 计数还是非常困难,因为这个条件依然很不优美。
那么既然判定合法很难,不妨从合法的 \(x\) 出发去找 \((A,b)\)。
求满足 \(x\) 能够生成出 \((A,b)\) 的数量:
但是同一个 \((A,b)\) 会被多个 \(x\) 给统计到,而且并不好容斥。
一个很经典的想法是对于每个 \((A,b)\) 钦定一个 \(x\) 进行计数。
结合前面的分析,一个 \((A,b)\) 中非二分图的部分对应的 \(x\) 是唯一的,而二分图部分我们可以钦定必须要达到边界。
那么此时 \((A,b)\) 和 \(x\) 是一对一的关系,直接转换计数对象,统计三元组 \((x,A,b)\) 的数量,满足 \(x\) 是 \((A,b)\) 所钦定的“代表解”。
因为限制都和图的形态,即 \(A\) 相关,所以从图入手计数。
基础数据结构方法
\(10.1\)
\(100+0+0+0\)
国庆节和模拟赛过了。
\(\text{Check Max}\)
\(\text{Part I}\)
考虑单个数的时候,如果某一次取了 \(\text{chkmax}\) 之后后续又变为负数了,然后再取了一次 \(\text{chkmax}\)。
那么前一次 \(\text{chkmax}\) 根本没有用。
换句话说,每个数至多只有一次有效的 \(\text{chkmax}\),我们可以对其找到最优的 \(\text{chkmax}\) 位置。
对于每个子集,可以同理得到使子集所有数之和最优的 \(\text{chkmax}\) 位置。
于是可以容易地做到 \(O(m2^n+n3^n)\),精细时限足以通过。
\(\text{Part II}\)
\(\text{(x)}\)
\(10.4\)
\(100+100+15+100\)
局部函数
考虑充要条件,发现考虑不动。
注意到 \(4\) 这个数就很神秘,特别小,于是可以 \(\text{DP}\) 去判断合法性。
再 \(\text{DP of DP}\) 就做完了。
\(\text{rplrprq}\)
考虑区间 \(\text{lowbit}\) 相同的可以直接打标记。
通过维护区间内所有数二进制表示下的最长公共后缀可以维护出 \(\text{lowbit}\) 是否相同。
发现这样做就过了。
因为把那个最长公共后缀看作势能可以发现,每次暴力递归会使其 \(+1\)。
\(10.5\)
\(\text{Vibe Coding}\)
先考虑如果确定了每个任务是人工还是 \(\text{AI}\),以怎样的策略安排顺序是最优的。
显然可以把所有 \(\text{AI}\) 任务按 \(B\) 递增的顺序首先处理,然后才是人工任务。
考虑 \(\text{DP}\),为了方便我们把前面的 \(\text{AI}\) 任务倒过来,因为 \(B\) 较大的系数反而小。
设 \(f_i(j)\) 表示考虑前 \(i\) 个任务,有 \(j\) 个是 \(\text{AI}\) 的最小耗时。
于是我们可以做到 \(O(n^2)\)。
然后说是 \(f_i\) 关于 \(j\) 是凸的,于是可以 \(\text{slope trick}\) 优化。
参考这篇。
\(\text{Take Many ABA}\)
我们考虑固定 \(\text{T}\) 怎么求 \(f(T)\),发现最大值非常难处理,只能二分答案。
于是我们考虑 \(\text{check}\) 对于某个 \(k\),是否满足 \(f(T) \geq k\),这个可以贪心做。
所以把原式改写成:
这个可以做一个 \(O(n^3)\) 的 \(\text{DP}\),常数较小,可以通过。
\(10.6\)
\(100+0+10+0\)
不知道写啥啊,这咋办?
\(\text{T3}\) 和 \(\text{T4}\) 感觉是真不难啊,只要有一定时间的观察我觉得就能做了。
那 \(\text{T2}\) 是真的雷霆啊,不知道咋刻画出来的。。放个链接吧。
配对
\(10.8\)
\(100+10+0+15\)
\(\text{T1}\) 是析合树板子。
\(\text{T4}\)
最终序列必然单调上升,然后不妨考虑其合法的充要条件是什么。
然后如果这时直接去思考两个数 \(a_i,a_j\) 在最终序列中相邻的条件就寄了。
正确的方向是考虑每个留下来的数 \(a_k\),肯定删除掉了原序列的一段区间 \([l,r]\),那合法条件其实是 \(a_l \geq a_k \geq a_r\)。
那 \(a_i,a_j\) 相邻的条件就是 \(\exists t \in [i,j),a_t \leq a_i,a_{t+1} \geq a_j\)。
然后直接对着这个用 \(\text{CDQ}\) 优化 \(\text{DP}\) 即可。
\(10.9\)
凸优化专题。
\(10.10\)
\(100+100+30+70\)
感觉没有 \(\text{AK}\) 真的是糖丸了。
普通的开关
把操作转化为每个点的删除时间 \(t\) 数组,那么 \(\forall i,j,t_i=t_j\) 都有 \(\max_{k=i+1}^{j-1} t_k >t_i\)。
所以任意区间的最大值有且仅有一个。
于是考虑区间 \(\text{DP}\),关键在于不要一开始就把空操作去掉,因为这样就只能记相对时间,合并很麻烦。
直接记绝对时间,然后使用拉插或者二项式反演都能还原出答案。
区间完美匹配
追忆。
\(10.13\)
\(\text{RGB}\)
你把字母看成数字。
然后发现 \(f\) 可以写成运算的形式。
再对原数组做差分,发现运算本质上是交换了差分。
灯笼
随便刻画一下,不难发现本质是保序回归。
\(10.15\)
余数
由于是对本质不同的 \(f(x)\) 计数,考虑到其定义域为 \(R\),所以可以先将其按最小循环节分类,最小循环节不同的必然不同。
钦定循环节,充要条件是 \(f(x+1)\) 要么是 \(0\),要么是 \(f(x)+1\)。
对这个直接计数,但是会算重,考虑去重。
因为函数的特殊形式,所以若其存在循环节 \(p\),则其最小循环节一定是 \(p\) 的因子,跑一遍反演去掉最小循环节非钦定循环节的贡献即可。
染色
把逆序对连边,则一个区间若存在长度至少为 \(3\) 的链就无解。
否则令 \(c\) 为连通块个数,答案为 \(2^{c}\)。
考虑如何维护连通块,很重要的一个点是在排列上,逆序对连边形成的图,每个连通块都是连续的一段区间。
考虑一个分割点 \(i\),满足 \(\leq i\) 的部分和 \(>i\) 的部分之间没有边,则 \(i\) 必须满足,前面的都比自己小,后面的都比自己大。
注意到询问都是问所有子区间,所以考虑扫描线的同时用历史和线段树维护答案。
这种所有子区间,如果想用 \(\text{CDQ}\) 就可能比较乏力。
维护当前以 \(r\) 结尾的最长上升子串,再进行分讨,不难写出添加一个数时所有左端点贡献的变化。
\(10.16\)
- \(\binom n m\) 为奇数当且仅当 \(m\) 是 \(n\) 的子集。
晚上讲了等价类分治。
\(10.17\)
\(\text{01 transform}\)
这种题我们直接考虑找不变量从而推出充要条件。
由于是相邻两个位置一起变,所以我们考虑奇数位置和偶数位置分开看。
不难发现,奇数位置的 \(0\) 个数和偶数位置的 \(0\) 个数之差是不变的。
然后这个就是充要的了。
\(\text{lm}\) 说这种问题可以把奇数位置上的数全部取反,会很爽。
\(10.19\)
\(0+25+0+0\)
哈哈,喜欢挂?
重庆友谊赛。
断章的诗
考虑对前后缀都做 \(\text{KMP}\) 匹配。
然后枚举 \(B\) 中的分界点,左右直接乘会算重,转化到 \(\text{fail}\) 树上的到根的路径并。
如果你没想到虚树,就可以用启发式和树剖,\(O(n\log_2^3 n)\) 通过这道题。
虚树上到跟的路径并,可以将所有点按 \(\text{dfs}\) 序排序之后,用所有点的深度和,减去所有相邻点 \(\text{LCA}\) 的深度算出。
如果你用 \(\text{set}\) 维护虚树,就可以以 \(O(n\log_2^2 n)\) 的复杂度通过这道题。
如果你会线段树维护前驱后继,就可以 \(O(n\log_2n)\) 做完。
无限赋格
任意数能都化为用斐波那契数列表示的标准形式,类似于一种进制。
然后在标准形式上做 \(\text{DP}\) 即可。
由于有修改,所以要用平衡树维护动态 \(\text{DP}\)。
假面惊梦
因为很多博弈题本质上都是 \(\min-\max\) 的形式,所以可以考虑二分,\(\text{wxr}\) 说的。
\(10.20\)
\(10.21\)
贪心专题。
又一道纸笔问题
\(\text{Part I}\)
考虑贪心,试想对于比较靠右的列,他们在比较高的位置有值,就只能自己删,不能和左边的列一起删。
所以手玩一下不难得到如下策略:
维护 \(top_i\) 表示第 \(i\) 列的最高的非 \(0\) 位置。
每轮从 \(m\) 开始,找到最小的 \(p\),满足 \(top_p \geq top_{p+1} \geq top_{p+2} \geq \dots \geq top_m\)。
然后令 \(w=\min_{p\leq i\leq m} a_{top_i,i}\),把这个后缀每一列的最高位置都减去 \(w\)。
重复以上操作即可,该过程可用线段树维护,一共有 \(O(nm)\) 次操作,故复杂度为 \(O(nm\log_2 {nm})\)。
\(\text{Part II}\)
对于具有如下特征的题目:
-
要用若干次操作达到某目标,且一定有一种“单位操作”可以通过很多次操作达到目标。
-
两次操作之间若满足某种条件就可合并为一次操作。
另一种常见的思考方式是先全用单位操作,然后再用贪心或 \(\text{DP}\) 等等进行合并。
这道题可以用这个想法做到 \(O(nm)\)。
其实这个想法在 \(\text{Geopelia}\) 的前半部分也有出现。
\(\text{Part III}\)
这题还可以建模成网络流。
\(\text{Minimize Topological Order}\)
先考虑哪些树是能够由 \(p\) 生成出来的。
如果没有字典序限制,可以直接从左到右扫描 \(p\),每次把当前点挂到一个前面点的下面都是合法的。
但是有了字典序限制后,考虑生成 \(p\) 的过程是用一个堆来维护所有的已解锁的点。
那么如果有 \(i>j,p_i<p_j\),则要求 \(p_i\) 必须在 \(p_j\) 出堆后才能入堆。
也就是说,\(p_i\) 的祖先链,必须要有排在 \([j,i)\) 之间的点,也即 \(p_i\) 的父亲必须排在 \([j,i)\) 之间。
用单调栈不难求出每个 \(i\) 左边第一个比自己大的,那么 \(p_i\) 的父亲范围就固定了。
每次选择一个范围内儿子数最小的点挂上去即可。

浙公网安备 33010602011771号