CF1856E2
如果 \(n\le 5000\) 考虑怎么做。
首先我们对于每个节点只考虑大小关系,最后只需要从小到大标号即可。
我们考虑把答案放到 LCA 处统计。
若其只有两个儿子 \(v_1,v_2\),那最多只有 \(siz_{v_1}\times siz_{v_2}\) 个会被统计,即令 \(v_1\) 所有数大于 \(v_2\)。
若有多个儿子,就是把儿子子树的大小分成两个集合,使得两个集合差最小。
可以用 01 背包解决。然而 \(O(n^2)\)。考虑 \(n\le 1e6\),如何优化 01 背包?
可能有关 bitset。注意到背包所有元素的和是 \(O(n)\)。所以不同大小的个数是 \(\sqrt n\) 的。
不妨二进制拆分做 01 背包,复杂度是 \(O(\frac{1}{\omega}n\sqrt n \log n)\)。
此外,如果有一个儿子大小超过一半,是不用做背包的,这保证了复杂度。
所以树的 \(siz\) 是分一半最优,总复杂度可以用主定理计算。
实现的话,需要使用动态大小的 bitset,
可以手写 bitset,或提前开好所有 \(2^k\) 大小的,用的时候用一个最合适的。
这种问题有关排列,应考虑相对顺序。再转化为背包,应想到 bitset,再观察背包的性质。
CF1764F
连接 \((i,j)\),就意味着把 \(i\to j\) 的路径作为环。\(f_{i,j}\) 就是其他点到这个环的距离和。
可以求出每个点的一条出边,也就是若 \(j\) 是 \(f(i,j)\) 除了 \(i\) 以外最大的,那么存在 \((i,j)\)。
注意到若 \((X,Y)\) 包含 \((x,y)\) 路径,那么 \(f_{X,Y}<f_{x,y}\)。
显然,若环的大小越大,那么每个到这个环的距离和就越小。
所以我们可以断言原树的形态是以 \(f(i,j)\) 为边权的最大生成树。
当树的结构被确定后,那么边权也很容易。
钦定 \(1\) 是根,\(w_{i,j}=\dfrac{f(i,i)-f(i,j)}{siz_j}\)。
这种问题要联想到生成树。
CF1827C
关于回文先想到使用 Manacher 算法。
我们借助 CSP2023T2 的算法,设 \(f_i\) 表示以 \(i\) 开头的回文串数量。
\(f_i=1+f_j\),\(j\) 是 \(i\) 右边第一个满足 \([i,j]\) 回文的位置。
问题转化为求右边第一个回文的位置,即求每个位置右边第一个包括它的回文中心。
考虑从左向右扫描,然后每扫到一个回文重心,就更新前面的。
也就是区间取 \(\min\),想到可以用吉司机线段树。
然而是不必要的,考虑并查集优化,并查集维护 \(r_i\) 表示右边第一个还未更新的。
那么直接暴力即可,因为每个点只会被第一次更新。
由于只有一次被更新,所以复杂度是 \(O(n)\) 的。
这种问题需考虑 DP,以及并查集优化。
CF1887D
我们发现正面去处理这个问题是很难的。
转化题意,由于有 \(\min\) 也有 \(\max\),枚举其中一个 \(\max\)。
考虑枚举切割点 \(a_i\),使得 \(a_i\) 是左边部分的最大值,且右边都大于 \(a_i\)。
设 \(a_x\) 是左边第一个大于 \(a_i\) 的,那么 \(x<l\le i\)。
设 \(a_y\) 是右边第一个大于 \(a_i\) 的,\(a_z\) 是 \(y\) 后第一个小于 \(a_i\) 的,那么 \(y\le r< z\)。
那么这个问题就很容易地转化为了矩阵加法,可以直接扫描线解决。
那么查询就是单点查询罢了。
这种问题就是需要反方向考虑,之后就是扫描线模型了。
CF1508D
经典套路,把 \(i\) 向 \(a_i\) 连边,形成若干的置换环。
注意到我们对于一个环,可以令其变成一个菊花,即不断地对一个点操作消去出边。
如果只有一个环,那么问题轻松解决。
如果有多个环呢,交换其中两个环中的一对就可以变成一个环。
把剩下的点进行极角排序,然后相邻的两个点进行操作:
如果两个点所在的环还没有并在一起就交换这两个点,用并查集维护。
发现这样是不可能与菊花相交,因为这些边都在菊花相邻边之间。
最后再做一遍开头那个算法即可。
这种问题首先应处理排列,关于相交的问题可以用极角排序。
CF1491H
如果没有修改,我们可以借助“弹飞绵阳”的套路,分块,维护跳出这个块到哪。
先考虑查询的话,我们可以像类似树剖那样向上跳,复杂度是 \(O(\sqrt n)\) 的。
修改怎么办?对于散块来讲直接暴力重构。
整块怎么办?由于修改只有 \(-x\),如果 \(x\) 之和超过块长,那么所有元素一跳就出块了。
所以整块也暴力修改。注意到一个块只会被修改 \(\sqrt n\) 次,复杂度是 \(O({\sqrt n})^3=n^{1.5}\)。
当一个块超过 \(\sqrt n\) 修改时,直接打个标记即可。
这种大数据结构应考虑分块思想,以及考虑势能分析。