巇崄沆漭,邅途兮何妨,吾道自爌炾
最近在听祖娅纳惜的歌,在怀疑她是几个人,以及她是不是人。
SolutionSet for June Part One
CF280E Sequence Transformation
模拟赛遇到了,写了 \(O(n^2)\) 的做法。下来后发现原题可以过,所以写写题解。
考虑使用调整法。初始时,我们把相邻两个 \(y\) 之间的差设为 \(a\) ,然后进行调整达到最小化答案的目的。
考虑我们把相邻两个位置的差增大一个极小量 \(\delta\) 会对答案带来怎样的影响。我们设每个位置 \(i\) 的代价 \((x_i - y_i)^2\),则增加一个位置 \(p\) 的与上一个位置的差分值 $\delta $ 对答案的影响为:\(\Delta = \sum\limits_{i=p+1}^n (x_i-y_i-\delta)^2 - (x_i-y_i)^2 = \sum\limits_{i=p+1}^n 2(x_i-y_i)\)。其实就是求导。
于是我们的策略就是每一步选择一个影响量为负且最小的可修改位置(如果有多个显然选择最右边的更优),将其增加一个 \(\delta\)。实际操作实际上就是将这个位置增加到不是最小值或者超过限制为止,加的数值显然可以 \(O(n)\) 算。注意到,每个位置只会被进行这样的一次操作,所以总复杂度 \(O(n^2)\)。
不知道为什么,这个做法好像比较吃精度。
\(O(n\log n)\) 的正解不会,但累了。
「20230601 模拟赛」 铲雪
类似树上道路铺设,但比树上道路铺设简单多了。
考虑和树上道路铺设有什么区别。发现如果权在点上,那么一个子树很有可能一条路径也上不来。
但此时,一个子树内往上连的路径条数是完全确定的,我们只需要检查如何合并这些路径即可。
更进一步地,每个点处考虑的贡献是完全独立的,我们在合并路径的时候的需求就是最小化以当前点为端点的路径条数。
稍微讨论一下不难发现,就是若最大边权超过一半,则贡献最大边权的两倍减去总边权次,否则贡献总边权的奇偶性次。
观察性质,发现对路径修改,大部分的点都是被改了两条边。如果两条边中包含最大权,则该点贡献显然不变。如果不包含,但最大边权不超过一半,则该点贡献也不变。我们在线段树上删去不变的点,用树剖维护。定义最大权在父边和重边上的,或者最大边权不超过一半的为不变点,则每次修改路径之后有 \(O(\log n)\) 个不变点变成会变点。暴力在线段树上修改这些点即可。
「20230601 模拟赛」 海盗
直接可行费用最小流可以创到 \(40pts\)。
考虑 \(l = r\) 怎么做。题解说这很经典。
定义 \(x_i\) 表示 \(i\) 给 \(i + 1\) 的金币数。则 \(a_i - x_i + x_{i-1} = l\),即 \(x_i - x_{i-1} = a_i - l\)。
然后我们就得到了 \(x\) 的差分序列。然后取中位数的相反数即可。
考虑特殊性质 \(\forall i \geq \lfloor \frac{n}{2} \rfloor\),\(a_i = l_i = r_i = 0\)。
这个相当于破环成链,吃面的时候想到了。
我们的一号海盗不会向 \(n\) 号海盗传递任何金币。
考虑 dp
。设 \(dp_{i,x}\) 表示考虑到前 \(i\) 个海盗,前 \(i\) 个海盗都已经满足限制,此时 \(i\) 向 \(i + 1\) 传递了 \(x\) 个金币,传递次数总和的最小值。
这个由于向左和向右的传递都确定,因此可以直接确定当前的金币数,这个一定是从一段区间转移,可以用单调队列优化,复杂度 \(O(n \sum a_i)\)。
继续优化,维护 \(f_i(x) = dp_{i,x}\) 的函数。本质上是进行如下三个操作:
- 对于任意 \(x\) ,取 \(f(x) = \min_{x'=x}^{x+t} f(x')\)。
- 将 \(f(x)\) 沿 \(x\) 轴平移 \(t\) 长度。
- 令 \(f(x) \leftarrow f(x) + |x|\)。
第二个操作直接整体上 tag,第一个操作实际上是叠加一个 \(y = |x|\) 的凸函数。
所以 \(f(x)\) 是一个凸函数。
那么第一个操作就很简单了!只用找到最小的位置,然后断开,将左半部分向左平移 \(t\) ,然后插入水平直线即可。
具体地可以用两个堆维护,均维护斜率转折点。然后一般情况就三分一下 \(1\) 号向 \(n\) 号给的金币就好。
CF1310C Au Pont Rouge
按字典序二分一个字符串出来,检查有多少种划分方式使得每个子段都大于当前字符串。
即定义 \(f_{i,j}\) 表示前 \(i\) 个数分成 \(j\) 段的方案数。然后检查 LCP
,做一个差分转移。
黄玫瑰
即要求构造有向无环边权图 \(G'\) 使得其与有向无环点权图 \(G\) 的极长路一一对应。
我们只用考虑极长路径,也就是说起点只会是入度为 \(0\) 的,终点只会是出度为 \(0\) 的。
有些路径会被另一些路径碾压,这个的甄别感觉与拓扑排序有关。要先删除一些边。
感受了一下,对于任意两个终点,它的起点的集合交集要么为空要么完全一样。
起点应该同理。那么就可以划分一下起点终点集合。
啊!不止,所有终点的入边集合应该也要相同。
算了,不会构造。
看看题解,确实就是要把不可能合法的边删除。
然后,之前想到其实也没有错,就是两个点能到达的点集要么相同,要么没有交集。
听狗狗讲,因为能到达一个点的两个点的可达点集一样。所以我们可以采用下述构造方法:
将每个点拆成入和出两个,如果两个点在原图中有边,则在构造图将对应的两对点的起点和终点合并!合并完了就可以直接连边。但怎么判断有没有解呢?可以直接构造,看构造合不合法,合法就有解,不合法就无解。
那怎么判断是否合法,可以定义一条极长路的权值是随机赋权的乘积,然后我们判断所有极长路径的权值和是否相同即可!
ABC304 Ex - Constrained Topological Sort
用优先队列做拓扑排序?每次选出一个入度为 \(0\) 的 \(R\) 最小的点,然后为它选一个满足条件的最小的值?
不对,可能会导致一些没解锁的解锁后无值可选。
哦!我们把每个点的 \(R\) 变成可达点中最小的 \(R\) 即可!
害。
【UR #12】密码锁
第一个结论就把我锤爆了。
竞赛图缩点是一条链。链的点数可以变换成前缀个数。
根据期望的线性性,答案就等于每个点集的点向外连的边都向外连的概率的和。
然后我们试图将指数变到 \(m\) 上。
那么就是对连通块枚举!每次枚举一个联通块内的点集,做一个背包就好了。
UOJ Round #25 设计草图
感觉好经典,这种题真没人出过?
首先一定要是偶数长度的。不妨考虑怎么判断一个子段是否合法。
从左往右扫,积累左括号和问号数量。维护一个当前是右括号的问号数量,遇到右括号考虑削一个左括号或者将一个是右括号的问号变成两个左括号。
然后,我们应该就有了一个神秘的 \(O(n^2)\) 的做法。
结合特殊性质能拿 \(45pts\)。
考虑没有 )
怎么做。
考虑从后往前做,记录一个从第 \(i\) 个位置开始,可以形成多少个合法区间。
然后每个位置只用找到能形成的第一个区间位置即可。
那么对于全局情况是否可以扩展?
只有当我的问号被消耗完的那一刻,前后才能够独立。消耗完指全部转化为左括号。
那我把他们先全部当成左括号,然后检查分界点。那么在此之前的任何一个时刻,我都一定有是右括号的问号存货!
在这段区间内,我把问号视作 -1
,那么是前缀最小值并且是非正偶数的位置可以形成合法括号序列!
考虑实现就是一个单调栈?再给到一个树状数组算一算。
UOJ Round #25 见贤思齐
每个人有一个内卷对象,这些内卷关系形成了一个基环树。
存在一个时刻,每个人都卷了一次。那么下个时刻每个人还是会都再卷一次。
那么这个时刻过后,每个人每个时刻能力值都会增加 1
。
如果一个人和他开卷的对象能力相同了,那么他的能力时刻不小于对象。
考虑这个基环树的核心,也就是环的状况。
环上的数趋于相同。
不如看看眼前的链吧。\(n\) 肯定会一直涨下去。会不断带动一些后缀一直涨下去。
我们维护一下每个元素在哪个时刻开始无穷增长,以及此时他的能力值。
那我实际上只用维护每个连续上升段的最后一个元素的无限增长时间?有点乏了,写点暴力先。
看看 zhoukangyang 怎么写的!
首先有一个暴力的式子:
然后我们下面做一些讨论!
因为 \(v_i + t > v_i\),所以容易发现:
不妨做一点迭代。
继续讨论:
- 如果 \(v_i + t < v_p + 1\),则答案已经被确定!显然就是 \(v_i+t\)。
- 否则,这个 \(\max\) 又可以被展开到外面去!
然后这个式子就可以被抽象成:
其中 \(l < r\),我们不断展开后面的部分,当 \(l \geq r\) 的时候答案显然就确定了。当展开完了都满足条件,那么答案显然就是 \(r\)。
这个东西很好倍增维护!
UOJ Round #25 装配序列
就是求一个循环数列的前 \(x\) 项的严格最长上升子序列。
哦,\(x\) 太大过后答案就会收敛。而且 \(a\) 是一个排列。
好讨厌!怎么严格 \(O(n^2)\) 做!
哈!这里有一个类似于平移势能的东西。我用桶存就好啦!
关于 \(m=1\) 并且 \(x\) 是 \(n\) 的整数倍的情况怎么办呢?
我可以算出至少要多少轮,答案才可以达到 \(n\)。
他的 \(O(n^2)\) 做法好像与我的不大一样。直接代码赏析。
先把值和下标交换一下!从小到大枚举值。
我相当于在维护一个 \(f_i\) 表示前 \(i\) 个位置的最长上升子序列,然后维护这个 \(f_i\) 的差分值在 \(c_i\) 上的累积。
知道这个显然就可以快速算答案。
假设已经考虑了值为 \([1 ,i-1]\) 的位置,现在新考虑值为 \(i\) 的位置。
对于原始位置在 \(i\) 右边的,他们的贡献位置显然可以被 \(i\) 完全替代。将他们完成替换即可。
对于原始位置在 \(i\) 左边的,相当于去替换那些比他大了一轮的!但是第一轮别人显然不能被替换,所以要去 +1
。最后再将其自己的值 +1
,因为其最后还可以再贡献一次!
终于把高级暴力理解了,但我觉得题解其实说的更清楚。
然后,高级暴力读懂,直接用线段树找到那些该交换的位置直接就复杂度正确了。
因为每种 \(c_i\) 只会被找出来交换一次。对于小于 \(B\) 的只有 \(O(B)\) 次查询,而大于 \(B\) 只有 \(O(\frac{n}{B})\) 个,所以复杂度完全正确。似乎有更加精细的方式可以分析出这个复杂度是 \(O(n\sqrt n)\) 的。
「20230605 模拟赛」 哈密顿路
觉醒了状压 dp
卡常水平,考场上 \(n^2 2^n\) 的爆冲 \(n=23\)。
但是极限了。事实上,因为是无向图,所以两个点之间有哈密顿路等价于两个点到 \(1\) 有不交的两条路径。
想到这里就做完了。
「20230605 模拟赛」 统一省选
这个是对题目套路很不熟悉。考场上写了个 \(O(n\sqrt n)\) 的,但写 wa
了 15
分,只拿了 70
,不是很懂。
事实上,这个可以用函数复合维护。考场上想了用半群运算复合维护,但现在看见半群运算复合维护只能想到矩阵乘法,完全没有使用分段函数复合的意识。
「20230605 模拟赛」 模拟赛
这题我会!感觉可以作为一类通性通法积累!
这个就是说,我们每次做 FWT
的元素非常少,我们每次都花 \(O(m2^m)\) 的开销去做这么一件事是非常浪费的。那么怎么办捏。考虑手动 FWT
,因为过程中,我们相当于是在做一个高维前缀和。简单观察可以发现其实只有很少的元素种类。实际上只有 \(2^k\) 种,然后我们把这些数拉出来再处理一下。
最后再做一遍高维前缀积就完成了对最终结果的 FWT
值的计算。最后再做一遍 IFWT
的计算即得到答案!
「20230605 模拟赛」 Chomp Game
第一问想必是相当简单的。就是每个位置被选到的概率,也就是 \(\sum \frac{1}{xy}\)。
随便算。
第二问我是真不会。这里有一个很经典的组合意义,就是说,第二问的答案等价于每个点单独被选的概率加上两个点同时被选的概率乘以二。
现在,我们考虑另一种组合意义,就是说,我可以将一个排列写在这些位置上,表示的是选择顺序。我按照每个位置的值从小到大去选择这些位置,如果选到了已经被删除了的位置则不管。
那么容易发现,如果两个元素互相包含,那么他们的概率独立,同时被选中的概率是 \(\frac{1}{ijxy}\)。
否则,可以去枚举哪个位置先选,设两个位置左下角的面积总和是 \(Tot\),则答案是 \(\frac{1}{Tot} \frac{1}{ij} + \frac{1}{Tot}\frac{1}{xy}\)。
那么做一些预处理就可以实现 \(\max(n,m)nm\) 的复杂度了。
「20230605 模拟赛」 MOMO
积累了不少关于 bfs
树的性质,挺好,这都是之前没有接触过的。
对于树,可以构造一个如果 \(x\) 到 \(1\) 的路径上含有点 \(y\),则将其标为 M
否则标为 O
。
考虑一般图!我们继续尝试将其转化到树上!由于题目中大量涉及最短路的性质,我们优先尝试使用 bfs
树进行一轮构造。
我们的构造需要以最短路为核心,但很可惜,我们的两个点之间的最短路径不一定是 bfs
树上的路径,我们直接按照树上构造的话,会导致不同的字符数量大于需求值。
怎么办?我们还有一种字符没有使用过。我们尝试使用 _
进行替换,使得一些本来会不同的位置变得不再贡献。考虑这个替换量:我们定义 \(c_{i,j}\) 为 \(i \rightarrow j\) 的最短路与他们在树上路径长度的差值。
考虑这个 \(c_{i,j}\) 在树上的性质,如果 \(j\) 是 \(i\) 的祖先, 则显然 \(c_{i,j}=0\),否则 \(c_{i,j} - c_{i,fa_j} \leq 2\)。
一个想法是将路径上的 \(c_{i,p} \in [1,c_{i,j}]\) 的位置都标为 _
。
但是从 \(lca \rightarrow j\) 的路径上可能只有 \(\frac{c_{i,j}}{2}\) 种取值。
因此对于一个点对 \((i,j)\),不妨令 \(dfn_i<dfn_j\),考虑将这个 _
的负担分摊到两端上面。一端摊偶数,一端摊奇数。如果没有的话,则可以把相邻的数取一个(因为变化量 \(\leq 2\),所以必然存在)赋为 _
。
那么就刚刚好力!感觉难点是考虑使用 bfs
树和使用 \(c\) 来完成对构造的规范。
HDU-6636 Milk Candy
我们要去限制 hints
能解出每个位置的值。这个得倒过来,考虑哪些位置不选。
而每个 NPC
的恰好选 \(k_i\) 个可以用额外权限制成至少怎么怎么样。
所以定义拟阵 \(M_1 = (S , I_1)\),其中 \(I_1\) 表示考虑哪些位置不选后仍然能解出方程的集合。
定义拟阵 \(M_2 = (S,I_2)\),其中 \(I_2\) 表示考虑哪些位置不选后,每个 NPC
不选的 hint
的个数不超过 \(c_i - k_i\)。
同时,我们把每个 \(w_i\) 加上一个大常数 \(C\),然后跑一个最大费用拟阵交!
显然,这两个拟阵是同时满足遗传性和交换性的!
现在这个问题是如何判断去掉这些东西后能不能解出方程。
哦?就是 check
是否联通?
Gym102156D Pick Your Own Nim
异或,选出来后所有向量线性无关!经典拟阵。
先给 Alice
选的堆做一个线性基,如果已经不是线性无关了 Bob
直接就输了。否则以这个线性基为初状态。
然后定义两个拟阵:
- 设 \(M_1 = (S,I_1)\),其中 \(I_1\) 表示每个盒子选择了不超过 \(1\) 个的选法集合的集合。
- 设 \(M_2 = (S,I_2)\),其中 \(I_2\) 表示选择的向量均线性无关的集合的集合。
然后现在显然就是求一个最大拟阵交,检查其是否满足了每个盒子都要选的条件。
做完了。
「20230608 模拟赛」 差
奶奶滴,读错题了。先看后面的。
不会做,但牛宝教我做。因为第一个元素是不重要的,所以我们应该去想到差分!
我们把问题转化为求解 \(a\) 的差分数组 \(d\)。我们先对 \(d\) 取个绝对值,最后再去考察它的正负性。
我们把差分数组与原问题做关联得到 \(b_i = \max(d_i , d_{i+1})\) 或 \(b_i = d_i + d_{i+1}\)。
前者两个 \(d\) 符号相反,后者符号相同。因此对于 \(d_i\) 有一个限制是 \(0 \le d_i \le \min(b_{i-1},b_i)\)
我们考虑使用一个 dp
去运算出这样一个合法解。定义 \(f_{i,j}\) 表示考虑到第 $i $ 个位置,能否选择元素 \(j\)。
考虑转移:
- \(\forall j \le b_{i}, f_{i,j} \rightarrow f_{i +1 ,b_{i}}\)。
- \(f_{i,j} \rightarrow f_{i+1,b_{i}-j}\)。
- \(\forall k \leq \min \{b_i,b_{i+1}\},f_{i,b_i} \rightarrow f_{i+1,k}\)。
牛宝说可以用 set
维护,但我不太明白。
哦?在同一时刻实际上只会有一个区间存在。因为每次要不加单点,要不相对对称中心翻转。而且只有小的翻转,所以删除大的然后打标记即可捏。
宝子宝子宝子。然后怎么构造方案捏?
或者说怎么回退操作。能执行第三类操作的地方打个标记。表示此时执行了三操作。
执行一操作的记录是从哪儿转移来的,同时记录个可以用一操作。否则都是二操作。
「20230608 模拟赛」 贼
第一反应后缀排序。然后可能是什么扫描线。
在后缀数组上面扫描线,然后做个 segmentbeats
就好了?
但查询没有势能给我满足。
那不如分块,块内修改有势能啊,就是元素种类数。然后维护一个递增序列。
每个块最多会被重构 \(B\) 次,最大值单独拉出来排个序列,其他的排一遍序维护着。
然后同时维护最大值和次大值。做完了。
重构的复杂度可以用归并排序缩到 \(O( B)\)。
所以复杂度可以平衡到 \(O(n \sqrt{n \log n})\)。
你说的对,但我块长平衡到 420
时最快,可能是重构块的次数是查询的好几倍。
「20230608 模拟赛」点
牛牛题。
部分分有启发性和提示性,但因为部分分不多,所以容易被忽略。
首先题目可以转化为每个点可以不动,或者向右移动 \(2d\) 个单位。
具体地,对于 \(d\) 很小的情况,我们可以直接向前状压 \(2d\) 位,看这些位置有没有被覆盖复杂度 \(O(poly(m)2^{2d})\)。
对于 \(d\) 很大的情况。我们对所有点 \(\bmod 2d\) 分组,然后容易发现我们可以将这个数轴分为 \(\frac{m}{2d}\) 组,然后每轮转移将每组向右推一步。状压 \(\frac{m}{2d}\) 个位置,表示每一段最靠右的位置是否被选。由于 \(\bmod 2d \equiv 0\) 和 \(\bmod 2d \equiv 2d - 1\) 的位置是连着的,因此还要记录没段第一个位置的覆盖状况。复杂度 \(O(poly(m)4^{\frac{m}{2d}})\)。
平衡一下复杂度就是 \(O(poly(m) 2^{\sqrt{2m}})\)。
「20230609 模拟赛」梦
好怪好怪,感觉比较的类数位 dp
。
先考虑 \(c=1\) 的 case
。那就是 \(b\) 进制数位 dp
?
定义 \(f_{i,j}\) 表示从高到低第 \(i\) 位,当前可选值为 \(j\) 的方案数。\(j\) 这一位显然是有一个上限的,超过了之后 \(n\) 就一定选不满了!我们就把溢出的部分先钦定成到最后都不选就好力!这个上限不超过 $ mb$,显然估的很松,因为怕犯错。
然后如果 \(c \not = 1\) 的话就加一维,看看当前哪些数处于自由态。
状态好像有些爆炸?注意到每个位置实际上只有 \(O(m)\) 个有效状态!所以复杂度 \(O(m^4)\)。
「20230609 模拟赛」战舰
考虑按每一列战舰数量根号分治。
如果一列战舰大于 \(\sqrt n\) 个,则在每一行修改时直接维护,否则则在行处打懒标记,查询列时扫一遍所有行查询。
同样地,也对一行战舰进行根号分治,操作类似。咋天天写根号算法。
嗯!\(p\) 也是非负数,感觉更加正确了!
好 ** 难写啊?根号算法都是答辩吧?
要控制不能有重复的位置,好烦呐!
赛后:真调不出来,真不知道哪儿 wa 了。
调出来了,插入当前较大的时候忘记把当前枚举的元素加进去了。
ABC304G- Max of Medians
整体上,感觉要从高位往低位决策,那么问题变成了当前有一个权值 \(w\),中位数是否有可能大于它。
唔,感觉和字典树有些关系。而且序列 \(A\) 的长度是偶数诶。
?读错题了,怎么是异或啊?那么显然就有在字典树上高位 1
配 0
,然后递归运算。
于是我们显然就只用往一边子树递归。直到与 \(w\) 最高位吻合。于是当前其实救只用对这两个子树进行讨论了。
显然只能左树跟右树匹配。哦把这些数拉出来,连边显然就是一个点连一车子树。然后我想模拟最大流之类的。
别搁这连边了,想想别的。考虑继续递归?如果是 \(w\) 下一位仍然是 1
,则只能 0
跟 1
配,1
跟 0
配。
如果不是,则可以直接配穿一些,但必须是不同边的向下递归。那限制呢?
我可以先递归,回上来看他们之间最多可以匹配多少对,然后先满足上层最大化再尽可能满足下面的匹配。
然后是不是就做完了捏。相对于 OR
,好像 XOR
的情况更少。
「20230611 模拟赛」 高维游走
每个维度正向行走次数显然是 \(t_0\) 的子集才有贡献。
我们很容易把那个疲劳值算重了,怎么办捏?
接下来是一个很奇怪很奇怪的 dp
。我们从小到大考虑,\(dp_{i,s}\) 表示考虑了前 \(i\) 位,对 \(2^{i+1}\) 的进位情况为 \(s\)(即若 \(s\) 的第 \(k\) 位为 \(1\),则可以有进位 \(k2^{i+1}\))的种类数。相当于是我们把一段前缀相同的数压在了一起,同时给这段前缀算出了能组成这个前缀的所有情况中的进位情况,转移就是讨论新加的那一位是 \(0\) 还是 \(1\)。大概就是这个样子。
「20230611 模拟赛」 过山车
考虑二分图染色,然后每个点能往外连两条边就是合法的。
考虑把每个点拆成竖直和水平两部分,如果一个点同时选水平和竖直则有贡献。
于是考虑算补集。做完了。
「20230611 模拟赛」 木棍
考虑判断一套放木棍集合是否可行。可以用霍尔定理判断。
然后发现与 \(m\) 个限制类似,我们可以用前缀和和差分约束来限制这个东西。
因为这些限制都是形如区间内最多有多少根木棍,最少有多少根木棍。
然后离散化一下创就好了吧?但是,\(O(n^3)\),但是跑的快 T
了直接输出 No
就可以过。
但还是看看眼前的 \(O(n^2 \log n)\) 吧。
「20230612 模拟赛」 序列壹
显然从小到大考虑每一个数,如果这个数被选定了,那么直接断开当前连续段。否则统计答案即当前连续段长度,然后将当前连续段长度减一。
「20230612 模拟赛」 接水果贰
考虑可以从接完一个水果到接另一个水果的要求:\(b_i - b_j \geq |a_i - a_j|\)。绝对值展开一化简,就是一个三维偏序结构。
可以直接分治,然后李超树维护转移,复杂度 \(O(n \log^2 n)\),但跑的很快。
「20230612 模拟赛」 字符串叁/可爱多的字符串
显然可以转化成 \(\sum\limits_{i=l}^r S_{\min(r,lcp(l,i)+i-1)}\)。
考虑 \(r=n\) 的情况。考虑从后往前建立后缀树。
考虑一个询问的 \(l\)。找到他对应的后缀的对应节点,其他 \(i > l\) 与其的 lcp
显然就是与它的 LCA
的 len
值。
这个可以树剖处理。类似陈亮舟题,可以将贡献转移到重链和单点上。由于 \(r = n\),所以贡献位置只用考虑起点,所以重链上轻儿子的贡献可以直接 dsu
处理,而单点怎么算呢?
可以从前往后再建一个后缀树,找到这个询问节点在该树上的位置,那么统计贡献 lcp
的终点位置的贡献和,这个相当于询问子树信息,随便怎么做都可以。而且这个部分是不依赖 \(r = n\) 的。
现在我们考虑如何在 \(r \not = n\) 的情况解决重链上轻儿子的贡献。
那这个就是从一个限制变成两个限制,就是说变成了矩阵数点。可以先做到 \(O(n \log^3 n)\)。
实际上,我们不用限制贡献点所在轻子树在询问剖出来的点的上面。多算的可以减去。
CF1830F The Third Grace
显然,有一个很平凡 \(O(n^2)\) 的 dp
做法,即直接记 \(f_i\) 表示前 \(i\) 个点必选 \(i\) 的最大贡献和 。
摸一摸性质,发现 \(\forall i \in [1 , n)\) 若 \(p_i < p_{i+1}\),则选了 \(i\) 必选 \(i + 1\)。就是每段上升子段我会选一个后缀或不选。
不止如此,结论可以更强,更普遍。每个位置如果被选择了,那他后面第一个比他大的位置也一定会被选择。
但这其实可以形成一种右向树,即每个点向右边的第一个比他大的点连边。这个是真的选爹了。但树本身的性质不强。
换成特殊一些的,最大的位置必选。次大的位置如果在他左边也必选。换而言之,前缀最大值必选。
两个前缀最大值之间的选择情况则是与整体完全独立的子问题,每一段单独考虑。
考虑选上后的影响,会替换掉上一个前缀最大值的部分支配区间,换上较小的值,但也会把被完全包含在这个区间里的区间赋予权值。注意到我们只用考虑右端点在里面的区间捏。
能否模仿对全局的划分子问题来处理我们的子问题呢?
区间被反复被替换支配值太累人了,注意到我们保留的区间的右端点其实形成了一个前缀,我们枚举哪个前缀的支配值还是上一个前缀最大值,
剩下的右侧一小段又可以按照前缀最大值必选的方式划分和计算贡献了。我们形成了另外一种合理的子问题划分方法,但难以形成合理的做法。
但这个结构与区间 dp
很类似,更具体地,这与我们将每个点向右边第一个比他大的连边形成的树在结构上具有极强的相似性,我们每一次询问的子问题都可以用树上的一条直链表示。
由于我们的子区间划分的答案之间具有极强的独立性,这直接告诉我们,我们的状态数其实只有 \(O(n)\) 个,即我们只用算出每个点到他右边第一个比他大的点这个区间的答案即可。
我们考虑按这个区间长度从小到大依次计算。我觉得这个思路不可算啊!嗯?分治可算吗?我好像可以获得一个基于分治和取最值的 \(O(n \log^2 n)\) 的做法?萎了。
贺题解!
首先,有一个显然的 \(O(n^2)\) 的 dp
: \(f_i\) 表示考虑前 \(i\) 个点,第 \(i\) 个点必选的最大花费。
转移显然有 \(f_i = \max\limits_{j<i} (f_j + S_{j,i} \times p_j)\),其中 \(S_{j,i}\) 表示包含 \(j\) 不包含 \(i\) 的区间数量。
我们尝试一次性去维护所有的 \(f\),从小到大依次考虑每种转移,一次性维护,于是可以得到一个刻意的定义:
定义 \(F_{i,j} = \max\limits_{k \leq i} (f_k + p_k \times S_{k,j})\)。显然 \(f_i = F_{i-1,i}\)。所以我们的目标是 \(F_{i,*} \rightarrow F_{i+1,*}\)。
式子中和 \(i\) 其实没有任何关系,因此我们尝试用数据结构直接去维护这个东西。
我们不妨研究这中间发生了什么变化:由于 \(i \rightarrow i+1\),所以 \(f_i\) 进入转移集合,我们现在需要考虑 \(f_i\) 对 \(F_{i+1}\) 的影响。相当于是对于所有 \(j\) 进行一个 \(F_{i+1,j} = \max(F_{i,j} , f_i + p_i S_{i,j})\)。
不妨先考虑 \(S\) 如何维护。
先考虑 \(S_{i,j} \rightarrow S_{i+1,j}\) 的变化。我们需要减去 \(r=i\) 的区间,加上 \(l=i+1\) 并且 \(r < j\) 的区间。
因此对于 \(S_{i,*} \rightarrow S_{i+1,*}\) 我们只需要进行均摊 \(O(1)\) 的后缀修改。并且 \(S_{i,*}\) 也是单调不降的。
现在我们考虑如何维护这样一个东西。注意到我们的 \(S\) 是单调不降的,而取 \(\max\) 操作时又是使用一个关于 \(S_i\) 的一次函数转移。所以我们考虑使用一个作用于 \(S_i\) 的李超树。每次插入一个直线即可。
但是,我们的 \(S\) 是会不断改变的,有可能会改变一个后缀。
假设我们需要对后缀 \([x,n]\) 进行区间加,不妨改变我们李超树的形态,即我们将所有覆盖了 \(x\) 的线段下传,使得所有线段覆盖范围内要么全部加,要么全部不加。
总结一下,我们只需要在李超树的每个节点上维护直线的基本信息,以及左右中间端点的 \(S\) 值,因为我们的转移式的原因,所以已经插入的直线相对支配关系不会改变,所以我们可以直接对线段打标记。
时间复杂度 \(O(n \log^2 n)\)。
「20230613 模拟赛」 简单的签到题
找到每一个有同一个最小值的连通块。这些连通块的大小和显然是 \(O(n)\)。
二分这个连通块顶部加上的值,线段树判断一下是否合法即可。
「20230613 模拟赛」 简单的字符串题
没有注意分析两个字符串相交带来的性质,只去想了一些高级结构去维护,大概是受了昨天模拟赛的影响。
注意到,两个相交的字符串相同,那就必然会形成周期。我们不妨枚举每个周期的大小。
这一下子相当于将整个字符串划分成了 \(\frac{n}{d}\) 段,然后相邻两段之间产生贡献。算出 \(kd\) 和 \((k+1)d\) 之间向前匹配和向后匹配分别可以匹配多少步。
然后我们就可以知道相隔为 \(d\) 的两个后缀 LCP
是多少。做完了吧,大概。
这样做的本质是直接将那些完全不会交的后缀对给排除了,因此在计算时可以直接进行代数运算。
「20230613 模拟赛」 简单的 bzoj 题
对斜率凸包什么的一直不是很敏感,当然也可能是今天精神状态不好,恍恍惚惚的。
明显是个上凸壳。考场时间不够,感觉不太能线段树闵可夫斯基和维护,跳过了。
实际上是可以的,维护完就 WQS
二分,然后 \(O(n\log^3 n)\) 暴力查就好了。
CF1830D Mex Tree
好怪的题目捏。不如转化一下题意,改为确定方案使得 1
联通块大小平方和的两倍与 0
连通块大小的平方和的和最小。这样真的好做吗?好做!
因为可以二分图染色,所以答案的上界是 \(2n\)。所以我们直接做背包,背包大小就是 \(O(\sqrt{n})\) 的!
可以直接做了。
ABC301G - Worst Picture
上述做了二维空间的解法,但已经删了。
完蛋了,怎么是三维空间???
但还是可以跟二维空间一样,找到所有由 \(x\) 最小的位置引出的所有有意义的共 \(O(n^2)\) 条直线。
然后怎么算交点捏?爷要会算交点就做完了。而且可能没有交点。
哦,直接在一个平面上的投影找交点,然后在拉回来检查一下是否确实相交了。
那这道题不是就做完了?打火机题,还开个三维,纯属恶心人,不会出题可以咬打火机。
「BJOI 2016」 打字机
有没有人告诉我最后一个部分的正解是什么?在我知道之前我把这道题定性为垃圾题。
先建一个 AC
自动机,那么就可以定义 dp
,即设 \(f_{i,x,p}\) 表示按了 \(i\) 个键了,当前在 AC
自动机上的 \(x\) 号节点,已经按错过 \(p\) 个键了,之后最坏最多能得多少分。
这个显然是一个可以用矩阵乘法优化的过程。至少在 \(p\) 不变的情况是这样的。
那么至少可以做 \(k = 0\) 的情况了。
你是拼盘题原来。 然后 \(m \leq 500\) 的情况也可以直接算。
这就已经 80pts
了。然后是对于 \(a_i \leq 1\) 的情况,对于 \(a_i = 0\) 的情况当然可以忽视。
?什么东西?最优比率环是什么东西?不知道,乱搞算了。
「2020-2021 集训队作业」Tom & Jerry
先缩点,准没错。然后考虑 Jerry
什么时候会寄。当且仅当他在一个双联通分量时,Tom
把他去其他双联通分量的路给堵住,并且可以一步到达这个双联通分量的所有点。
如果一个双联通分量内没有一个点使得其可以到达所有点(我们不妨称这样的点为关键点),那么 Jerry
可以一直在这个分量内绕。
若 Tom
的起点不是这样的一个点,那么 Jerry
被抓住就要求整个图都满足所有双联通分量都有关键点,并且双联通分量之间的边按照指向关键点定向后,是一棵外向树。即每个点只有一个入度,否则爆炸。
否则,如果 Tom
踩在关键点上,首先如果上面条件成立那肯定还是能抓住。否则相当于将整个图裁去一部分,然后检查上面那个条件能否成立。
分析的不太对,不该是用边双分析,而该用点双分析。
类似地,建立圆方树,设 \(a\) 为根,如果去掉 \(a\) 后 \(b\) 所在连通块的所有圆点到其下面所有点双都有边,则 Jerry
一定会被抓住。或者以某个点为根,所有圆点到其下面所有点双的点有边,则 Jerry
也一定会被抓住。
但是怎么计算捏?考虑换根 dp
。一个算子树下面,一个算上面。
「20230615 模拟赛」 教唱
首先可以预处理 min-max
容斥,算出完成指定的 \(k\) 个课程期望需要多少时间。
然后现在有 \(n - m + 1\) 种结束课程的方式。我们对这些再进行一次 min-max
容斥,求出最先被达到的状态期望要用多久。
一个方式是直接枚举这些课程的集合。
另一个方式是考虑我们只需要知道我们要上多少课程,但是不同的结束状态课程可能有重复,所以我们状压向前 \(m\) 种结束状态的选择情况集合。
平衡一下复杂度即可。
「20230615 模拟赛」 奇艺线段树
这个就是研究我们覆盖区间的特点。
发现他们总是一大车右儿子加上一大车左儿子。我们考虑将问题变成寻找一条形如从右儿子到右儿子,一次从右儿子到左儿子,从左儿子到左儿子的路径。首先就可以看做路径覆盖,网络流可以跑。
其实可以做一个线性的贪心!
我们只需要维护有最少多少条右儿子路径和左儿子路径,然后在每个节点处合并左子树的右儿子路径,右子树的左儿子路径!但是有可能反悔,因为在父亲处有可能可以拉一个节点过来合并一个路径,这样就可以少合并一次,将答案减少 1
。
然后就做完了。
「20230615 遗弃的模拟赛」 yww 与树上的回文串
先做个点分治,毕竟是在路径统计。然后字符集大小为 \(2\) 能不能利用起来呢?
哎呀,沙耶讲的 border 理论又忘记了!
就是说,一个回文串所有的回文前缀可以被表示为 \(O(\log n)\) 个等差数列。
然后点分治,建立 AC
自动机,然后 dfs
扫一遍,找到每个串所具有的 \(O(\log n)\) 个回文前缀,挂在 fail
树上。接下来就是在 fail
树上搜,然后阈值分值,如果公差小于 \(B\),则维护一个 \(c_{i,j}\) 表示 \(\bmod i = j\) 的前缀个数有多少。如果公差大于 \(B\) 则直接暴力扫查深度权值。
但听说 \(B = 2\) 时跑的最快,因为不好卡。