新蔬菜专题

Page Views Count

公式

\[\sum \binom{2j}{j} \binom{2i-2j}{2j}=4^i \]


\[\prod[w_i=1]={1\over 2^n} \sum\limits_S \Big( \prod\limits_{j\in S}w_j \Big) \ (w_i=\pm1) \]


\[FWT(f)=g \Longleftrightarrow g_S=\sum\limits_T (-1)^{|S \cap T|}f_T \texttt{ 可以倒着用} \]


\[\prod {1\over 1-a_iz} = \sum c_i{1\over 1-a_iz} \Longleftrightarrow c_i={1\over \prod\limits_{j\neq i}(1-{a_j \over a_i})} \]


\[\texttt{the number of out-facing block buildings on a}\times\texttt{b}\times\texttt{c: } \det \big( \binom{a+b}{a+i-j}_{i,j} \big) (1 \le i,j \le c) \]


\[x^k=\sum\limits_{j=1}^k\Big\{ \begin{matrix} k \\ j \end{matrix} \Big\} x^{\underline{j}} \\ \Rightarrow \sum i^kf_iz^i=\sum\limits_{j=1}^k \Big\{ \begin{matrix} k \\ j \end{matrix} \Big\} \sum i^{\underline{j}}f_iz^i=\sum\limits_{j=1}^k \Big\{ \begin{matrix} k \\ j \end{matrix} \Big\}F^{(j)}(z) \]


\[(uv)^{(k)}=\sum \binom{k}{i} u^{(i)}v^{(k-i)} \\ \Rightarrow \sum G^{(i)}{z^i\over i!}=\prod\ \sum F_j^{(i)}{z^i\over i!}\quad (G=\prod F_j) \]


\[\sum\limits_{x_1,x_2,\dots,x_n>0} \Big[\sum x_i\le k\Big] (k+1-\sum x_i) \\ = \sum\limits_{a,x_1,\dots,x_n>0} \Big[a+\sum x_i\le k+1\Big] \\ = \sum\limits_{a,b,x_1,\dots,x_n>0} \Big[a+b+\sum x_i= k+2\Big] \\ = \binom{k+1}{n+1} \]


\[\texttt{let } F(x)=\lfloor f(x)\rfloor,\ G(x)=\lfloor g(x)\rfloor \\ f(x)\in (-\infty,g(x)-1) \Rightarrow F(x)\ne G(x)\\ f(x)\in [g(x)-1,g(x)) \Rightarrow F(x)\in \{G(x)-1,G(x)\}\\ f(x)\in [g(x),g(x)+1) \Rightarrow F(x)\in \{G(x),G(x)+1\}\\ f(x)\in [g(x)+1,+\infty) \Rightarrow F(x)\ne G(x) \]


\[\begin{aligned} n^k & = \sum\limits_j {k \brace j} n^{\underline{j}} \end{aligned} \]

\[\begin{aligned} \sum\limits_{a=0}^{n}a^k & = \sum\limits_{a=0}^{n} \sum\limits_j {k \brace j} a^{\underline{j}} \\ & = \sum\limits_j {k \brace j} \sum\limits_{a=0}^{n} a^{\underline{j}} \\ & = \sum\limits_j {k \brace j} {1 \over j+1} (n+1)^{\underline{j+1}} \end{aligned} \]

\[\text{Can be used when $mod \notin P$} \]

建模

一个 01 序列区间的众数 \(\iff\) 将 0 换成 -1 后区间和与 0 的关系

ARC137E:覆盖一个区间,每个位置覆盖次数有上限,超过后无贡献:最小费用循环流模型

在一个 DAG 中删去一些点,使剩下任意 3 个点不在一条链上:将原图 G 复制一遍得到 G',对于每个点 u,从 G 中的 u 向 G' 中的 u 连边。答案即为这个新图的最长反链=最小路径点覆盖(=二分图匹配)。

一个合法的点分树,设它的根权值为树的深度,每个点的权值为其父节点的权值 -1,那么点分树方案合法 <=> 任意两个权值相同的点之间有一个权值比它们大的点

交换一个序列的相邻两个 01 \(\iff\) 将 0 视为向右下走,1 视为向右上走,产生的一个“谷” V 变成“峰” ^

从一个序列中删数就变成往一个序列里加数,往一个序列里加数就变成从一个序列中删数,一定要与出题人对着干!

重要构造:让一个 \(n\) 个数的集合任意两对数的和互不相同,可以找一个足够大的质数 \(p\),对于第 \(i\) 个数,令 \(a_i=(i^2\bmod p)\cdot p+i\) 即可。注意到对于一个 \(s\),我们 找出 \(\lfloor {s\over p}\rfloor\)\(s\bmod p\),由后者得到 \(i+j\),再由前者就可得到 \(i^2+j^2\),然后得到 \((i-j)^2\),然后开根得到 \(i-j\) 就做完了。
怎么开根?for(int i=0;i<p;i++) sqr[i*i%p]=i; /cy 二次剩余滚吧 /cy/cy/cy

思想

每当 pos 右移一位时,a 只有一个元素性质发生大的改变,其它元素平移后不变/变化相同

求“aaa中xxx的最大值”的最大值,可以枚举 aaa 中的所有 xxx,使它最大,记录下结果,再在所有结果中取最大值

边很稀疏的图 (\(m-n \le 9\) 之类的)可以考虑收缩 1,2 度点,甚至收缩 3 度点进行递归求解

Segment Tree Beats: 留坑。。。

当对一个序列的操作等与其元素之间的大小有关时,可以考虑将 \(\le k\) 的视为 \(0\)\(>k\) 的视为 \(1\),01 串的操作往往有一些很好的性质

对于一些作用在多个(复杂)位置的操作,可以考虑用数据结构(一般是线段树)维护操作轴即时间轴,然后按顺序枚举位置(而不是时间)

从一个字符串 \(S\) 加/删 字符变成另一个字符串 \(T\),可以考虑将操作倒过来,变成从 \(T\) 删/加 字符变成 \(S\),往往会取得奇效

区间放一个数查询区间 mex:

  1. 区间内连续出现最远的 → 区间取反,变为区间内“每个位置最小出现”的最大值 (貌似这是 mex 题的常见套路)

  2. 标记永久化:\(\max(\min(lc,v),\min(rc,v))=\min(v,\max(lc,rc))\)

AC 自动机能够处理:\(O(\log len)\) 求出一堆串中拎出一个文本串,其它串作为模式串出现的次数(路径 +1 fail 树求和)—— fail 树是一个可以与 SAM 媲美的东西

动态规划肯定要排序,但不一定要从左到右转移,也可以将所有转移排序,然后一个个转移进行,这样可以保证转移过程中的另一个有序性(如凸包上的斜率)。此时假的转移自然就假了,真的转移一定能转

对于停时问题,如果状态转移形成 DAG,则停时期望为所有非法状态出现的概率 * 离开这个状态的期望时间。(见 定理3

当我们要数“一个 \(f\) 生成的一个 \(g\)” 的 不同的 \(g\) 的方案数时,如果不同的 \(f\) 可以生成同一个 \(g\),则应该想办法钦定每个 \(g\) 由唯一一种方法被 \(f\) 生成,然后数这样的 \(f\) 的个数。

随机二分法: 对于一个很大的数域,想要求第 \(k\) 大,我们随机挑一个数计算有 \(c_0\) 个数小于它\(c_1\) 个数小于等于它,若 \(c_0+1\le k\le c_1\) 则其为答案,否则根据结果左右递归处理,次数期望即为 \(O(\log V)\)

A* 求 \(k\) 短路技巧: 维护一个堆,必须要设一个估价函数,为已走过的距离和到终点的最短距离之和(如果是简单路径就去掉已访问过的点), 每次取出堆顶的路径进行更新即可。复杂度是正确的, 因为每更新一次,都必然会更出一条合法路径,其它可能没用,但是对于每一条路径,最多只会在途径的 \(O(n)\) 个点上各叉出 \(O(n)\) 条岔路,设需要求出第 \(k\) 短路,则一共只会有 \(O(n^2k)\) 路径,堆内比较的复杂度可达 \(O(n)\)(字典序比较),于是时间复杂度不超过 \(O(n^3k\log ??)\),并且卡不满。转移时需要转移到多个点,应从 \(n\) 倒着跑最短路,一次性算出所有转移点到 \(n\) 的最短路。

时间复杂度分析小专题

\[\sum\limits_u \sum\limits_{v\in son_u} siz_v(\sum\limits_{w\ before v}siz_w) = O(n^2) \]

证明:等价于每两个点在其 LCA 处贡献 1,自然 \(O(n^2)\)

在一个序列上以一定的规则游走,提出 \([l,r]\) 的位置所走出的序列是整个序列所走出的序列的一个子串

一堆数异或和 \(=C\) 的题目,有两种基本方法:一是 \(FWT\),二是如果有一个数可取的值为 \([0,2^k)\), 则方案数可以 \(O(1)\) 计算(其它任选,这个数调整即可)

鞭尸技巧: 一些互相关联的操作,可以单独掰出一个操作来,考虑其它操作,如果对它有影响,那就有影响;没有影响的操作等于重开,就是干了一个空气,剩下操作的概率相同(猎人杀)

与环和链有关的题目,可以按每个点连出的一条或两条边的情况进行 dp

点分树时间复杂度计算: 计算以每个节点为根,整棵树被删空的时间,就是每个节点被删除的期望时间和,由上面的鞭尸操作,一个深度为 \(dep\) 的节点对期望贡献为 \(1\over dep\),乱作即可。

凡是树上与距离有关的问题,都可以考虑长链剖分直径(后者更加常用)

序列相邻元素相关构造技巧: 先构造一个短序列,然后每次将这个序列复制一遍并翻转接在原序论后面,然后调整一下中间接触的地方

凡是与字符串相关的题,都可以考虑用 \(SA/SAM\)\(lcp\) 解决。\(SA\) 会把 \(lcp\) 整到序列上 \(RMQ\)height 数组),\(SAM\) 可以转成后缀树,\(lcp\) 成为 \(LCA\)。几乎所有字符串题都这么整

二维刷墙问题: 每个点的最终颜色可以转化为两维中时间靠后者给它涂的颜色,从而变成时间之间的关系,用二维偏序解决

一个 \(k\) 进制数数位重排后,前后之差为 15 的倍数,退位次数为差的各位数之和 /15,并且满足 \(x-y=a\) 的最小的 \(y\) 最高位一定是 0

\(\gcd\)\(\mathrm{lcm}\) 的序列维护(或其它)问题,那么一定要记得把它变成 \(\min\)\(\max\)!许多特殊性质即水落石出!

和类似 \(f(x,y,z)=\min(x,\max(y,z))\) 之类的东西都是可以用线段树合并的~ \(\min(x,\max(y,z))=\max(\min(x,y),\min(x,z))\)

平面图与平面剖分的分治技巧: 对于平面图和剖分来说,可以找到两个有连边的点将其分成两边,由平面剖分性知道左右两边之间没有连边,于是可以从中间处理跨越两边的最短路之类的问题,然后递归处理两边。复杂度正确性: 考虑平面图转对偶图,每次选一条边进行分治就是割掉一条边,对于三角剖分来说,它是一棵三度化的树,边分治复杂度即正确。本质上找到两边的点数较大值最小的边进行分治即可。

关于序列上 \(\sum{|i-p_i|}\) 的贪心问题的技巧:

  • 如果要求序列上不同颜色才能匹配,则对于任意两个位置 \(i\)\(i+1\),跨越这两个位置分隔线的匹配,一定是多色对一色或一色对多色。(考虑排列 a b c d,若 ac 匹配,bd 匹配,显然不如 ab 匹配,cd 匹配。)
  • 在要求值最小的前提下让字典序最小,可以发现可以分成一段一段的“括号序列”,然后发现对于每一个位置,其后面可以匹配的位置单调包含,因此尽管是贪字典序,依然可以从后往前贪心取最大值。(感觉这个技巧可以扩展)

区间颜色数计数技巧:维护每个位置上一个颜色相同的位置 \(pre_i\),则区间 \([l,r]\) 中的颜色数即为 \(pre_i<l\) 的位置个数(这样可以保证每个颜色只被算过一次)。

求元素极差最小值技巧: 从大到小枚举最小值 \(min\),过程中维护最大值 \(max\) 的最小值。

自转移函数求期望可以考虑类似 Dijikstra 的办法,每次拉出函数值最小的更新其它的函数值。

博弈论简化技巧: 取数游戏由于所有数之和为定值,故可以改为求双方得分之差的最大值/最小值,然后根据贪心性质可以将形如 \(a_{i-1}<a_i\)\(a_i>a_{i+1}\) 的三个数合并为 \(a_{i-1}+a_{i+1}-a_i\) 之类的方式。

至少改变一半,层数至多为 \(\log\) 的技巧永世不衰

贪心缩小 dp 范围技巧: 设数组 \(a\) 的值域为 \([0,V]\),则对于任意 \(S\),可以找到一个 \(a\) 的子集使其和属于 \([S-V,S]\),方法为从前往后不断选数直至即将超出 \(S\) 即可。对于和 \(S\) 有关的背包问题可以有效减小值域。

背包缩小元素个数技巧: 可以利用抽屉原理证明调整次数不多于某一个阈值。

扩展 01 bfs 的技巧: 若一张图只有两种边权 \(A\)\(B\),那么可以创建两个队列 \(a\)\(b\),每次取出两个队列队头的较小值,连出的 \(A\) 边插入队列 \(a\),连出的 \(B\) 边插入队列 \(b\),过程与 Dijikstra 相似,但时间复杂度少了一个 \(\log\)

wlx:多颜色子树最大值技巧: 对于每种颜色,将叶子节点权值赋为其权值,非叶子节点权值赋为其儿子中所有非最大值节点权值之和的相反数, 则查询时只需查子树和即可。

lh:背包计数 dp 删除物品技巧: 对于一些背包问题,有时需要删除某个物品进行转移,这时可以将原 dp 方程视为网格图上的行走路线,从而选择某个方向倒推回原先的 dp。注意可能会存在转移系数没有逆元的情况,此时可以分类讨论选取某个有逆元的方向进行倒推(作为一个转移式,必然至少有一个系数有逆元),或手推出必然有逆元的那个方向进行转移。

技巧

\(mod 2\) 意义下的多项式,乘法(又称二项卷积)可以变为子集卷积,求逆即为自身,可以各种乱搞

当一个区间的答案与其最小值/最大值有关时,可以考虑对整个序列建出笛卡尔树,然后对每个节点预处理出其前后缀的答案,对于每组询问 \([l,r]\),以其最大值/最小值 \(k\) 为中心划分成三部分:\(val(l,r),f(l,k-1),f(k+1,r)\) 计算,后两者即为一个节点的前缀/后缀

分治 FFT 只需要保证递归层数是 \(O(\log n)\) 级别的,例如 \(m\) 个多项式相乘,次数和为 \(n\),尽管这些多项式次数各不相同,但直接普通分治 FFT,每层的次数和均为 \(O(n)\),共 \(O(\log n)\) 层,则总复杂度为 \(O(n \log^2 n)\)

!! 有些(很多)换根树形 dp 可以对于每个“上子树”都算出它的 dp 值,但这样做是 \(O(n^2)\) 的(虽然界很弱),怎么办?拆点!将一个点的若干个儿子拆成一条链(和边分治一样),然后就是 \(O(n)\) 的了(边权的重赋值可能有点棘手)

求强连通分量中所有环长度的 \(\gcd\),可以跑出一棵 dfs 树,然后对所有非树边 \((i,j)\),求 \(|dep_i+1-dep_j|\)\(\gcd\)

---——对于一些传染性问题的技巧——

  1. 如果转移是直至无穷时候的并且是循环的,那么可以每次不同时转移,而是每次只转移一步

  2. 初始时每个点找出一条出边,找不到一般很平凡,否则就成了一棵基环树。

  3. 转移的性质有时满足:若 a -> b,那么 a 一定比 b 劣。这时,可以从每棵基环树开始搜,搜到其它基环树则并查集合并,否则只遇到自己,自己就是答案。

  4. 运用 Boruvka 算法的复杂度分析,我们每次对于一层中所有基环树同时开搜,这样每轮基环树个数至少减半,于是就是 \(O(n \log n)\) 的。


对于一棵树,求一棵子树内是否有某种颜色,可以将所有有此颜色的点按 dfs 序排序,每个点打标记 +1,每相邻两个点的 lca 打标记 -1,答案即为子树内标记和

(因为听说 pb 在 GDOI2019 因为不会这个技巧爆炸了所以全部加粗)

dp 神奇优化:CDQ 分治(?,\(solve(l,r)\) 递归到 \(solve(l,k-1)\)\(solve(k,r)\),在中间处理 \([l,k-1]\)\([k,r]\) 的转移。

然后 \(k\) 不一定要是区间中点,如果能够在 \(\min (k-l,r-k)\) 的时间内处理出这个转移,则时间复杂度等同于启发式合并,\(O(n \log n)\)

复杂度分析:有时一个算法的复杂度可能看上去是 \(O(nmk)\) 的,实际上是 \(O(nk\frac{m}{k})\) 的,然后你就过了(?

如果要求一个区间第 \(k\) 大的数的贡献,可以转为枚举每个位置,看它在那些区间里面是第 \(k\) 大,这个就开一个链表,每次查询最小的左右两边 \(k\) 个位置,再把它删掉。

解树上的 dp 方程的好套路:\(f_u=\sum\limits_{v \in son_u} c_vf_v+d_uf_{fa_u}\),则记 \(f_u=a_uf_{fa_u}+b_u\),当 \(u\) 为根时就有 \(f_u=b_u\),于是再从上到下递推回来即可

处理点分树的技巧:留坑

对于一个由若干条直线组成的下凸函数,可以用如下方法求出它的所有拐点:先找出最左端和最右段的直线,找出它们的交点,如果这个交点在凸壳上,则这个区间内只有这一个拐点,返回;否则,找到这个交点横坐标所在直线,左右递归处理。这个过程是 \(O(n)\) 的(不会证)

\(a_1,a_2,\dots,a_n\) 中有 \(k\) 个子集的和为 \(j\),则不妨设 \(a_1+a_2+\dots+a_x=j\),有 \(a_1,a_2,\dots,a_x,-a_{x+1},-a_{x+2},\dots,-a_n\) 中有 \(k\) 个子集的和为 \(0\)

\[x^k=\sum\limits_{j=1}^k\Big\{ \begin{matrix} k \\ j \end{matrix} \Big\} j!\binom{x}{j} \]

于是 \(k\) 次方可以表示为若干个组合数之和,这给组合意义赋予了非常好的武器。

对于计数的问题,可以考虑转化为期望,然后变成次数较小的多项式进行插值。

dp 的批量转移技巧:如果我们要进行若干次 dp,每次 dp 的初值相同而终态不同,则我们可以将整个 dp 反过来进行,如果原来的 dp 有 \(u*k \rightarrow v\),则在新的 dp 中进行 \(v*k\rightarrow u\),就可以求出 dp 的结果。仅限于一个点 dp 到另一个点的 dp。

巧妙推性质:如果我们可以从一个状态转移到其它若干个状态,但每个状态的某个函数值恰有一种转移使之严格变小,且函数值均非负,则我们可以证明所有状态都可以走到某若干个函数值最小的状态,从而形成树/森林/基环树。

dp 技巧:如果一个转移方程形如 \(f_{i,j,k}\cdot a(j) \cdot b(k)\rightarrow g_{i',j',k'}\) 之类的,其中中间的两个转移系数分别与某一维独立,则可以考虑设置一个中间状态 \(h_{i,j,k}\),例如让 \(f_{i,j,k}\) 转移到 \(h_{i',j',k'}\),再由另一种转移从 \(h_{i',j',k'}\) 转移到 \(g_{i'',j'',k''}\)

无穷归纳法: 求一个序列 \(a_1,a_2,\dots,a_n\) 的函数 \(f(a_1,a_2,\dots,a_n)\),可以对方差进行归纳,即

\[f(a_1,a_2,\dots,a_k,a_{k+1},\dots,a_n)\leftarrow f(a_1,a_2,\dots,{a_k+a_{k+1}\over2},{a_k+a_{k+1}\over2},\dots,a_n) \]

由于前者的方差严格小于后者的方差,我们就可以无限将序列 \(a\) 变为同一个值!
(事实上,方差这个函数可以改为任意一个会严格变小的函数)

树上多点最远距离: 维护一个树上的点集,支持加点,删点,询问一个(树上的)点到点集中任意一个点的最远距离
做法:把所有点按一定顺序丢到一个线段树里(只要有顺序就行,方式任意,这意味着可以按 时间戳/dfn 排序等方式也是可行的),每个节点上维护其节点内所有点形成的虚树的直径端点,合并时直接6条线段取最大值即可(用 #define 好用)
查询时直接对区间内直径的两个端点测一下即可(这意味着也可以只对一个 时间段/子树 查)

树上与点 \(u\) 距离在 \(k\) 以内的点一定在 \(u\)\(k\) 级祖先的子树内(注意判0)

拉格朗日乘子法🍊: 用于计算多点函数最值的方法,记住偏导以及算子 \(\lambda\)
具体公式见这里

区间改为前缀/后缀最大/小值技巧: 用两个 set 来记录 \(f\) 值的差分数组,一个记录正数,一个记录负数,例如当区间 \([l,r]\) 改前缀最小值时,就从 \(l\) 开始往右不断找最近的正数,并找到正数后面的第一个负数,如果存在就尝试与之对消,如果不存在就一直到 \(r\) 这一段都可以整体下降 it->se,直接在 \(r\) 这个点这里 add 即可。
实现时一个技巧是开 map 而非 set,用 mp[0/1] 来表示负数与正数。要注意的是 it 的终止位置与 it2 的限度不同。

zz:分解 \(10^{18}\) 因数的技巧: 枚举 \(O(W^{1/3})\) 以内的因数判掉,那么剩下的数要么是 \(1\),要么是一个大质数的平方,要么是两个大质数的乘积。前两种情况很好判断,最后一种就记录下来,然后求若干个数的 \(\mathrm{lcm}\) 时就可以拿来用。

wlx:随机化问题爆砸技巧: 随一个(与原问题相似而不相同的)问题,解这个问题,解的过程中会得到一堆子问题,这些问题都可能会与原问题在某程度上重叠,此时就可以得到答案。而每解决一个随机问题就可以解除很多子问题,这意味着相撞概率极大。

yjz:判定出现在至少一个集合的元素个数技巧与按秩合并撤销技巧: 建立一个 map,存的是每个元素出现的集合(根节点) pair(即分别在每一维的哪个集合),然后合并和撤销时会对一个元素所在集合的根产生影响,动态更新 map。而对于后者,让每个节点存其子树中有那些点,当断开边 \((x,fa_x)\) 时,只用 pop_back \(fa_x\)vector 中的后 \(siz_x\) 个元素即可

zz:二分防寄必备:假设现在二分到的区间为 \([l,r]\),则会有 \(\mathrm{len}([l,mid])\ge \mathrm{len}([mid+1,r])\),大于号可以取到。此时当递归到某一边时,可能会产生新的区间不满足原区间某些条件的情况(比如区间 \([l,r]\) 中包含至多 \(r-l-2\) 个标记之类的),必须注意二分时是用 \(\ge\) 还是 \(>\)!!!

问一个集合的交互题,永远不会问一个随机集合/变形

一张图用最少的路径覆盖所有的边,所需路径数为 \(\sum_u |in_u-out_u|\)(不要用 \(\sum_u in_u\) 来算,很难算)

序列 \(O(n)\) 并查集: 设并查集复杂度为 \(O(\log n)\),则把整个序列分成 \(n\over \log n\) 段,每段中用 lowbit 找出最低位的 \(1\),复杂度 \(O(\log n)\times O({n\over \log n})=O(n)\)

wlx:和字符串子串字典序有关的 dp 问题,可以考虑从后往前进行 dp,这样便于比较字典序。

拓扑序计数技巧:一个黑球和白球组成的序列,球与球之间可以区分,要求第 \(i\) 个黑球后面有给定的 \(a_i\) 个白球,求方案数以及黑球位置之和。
递推:四元组 \((n,b,c,s)\) 表示当前已经有 \(n\) 个球,其中 \(b\) 个是黑球,有 \(c\) 种方案,黑球位置之和为 \(s\)
加一个白球:\(n\) 个空有 \(n+1\) 种方案,对于在位置 \(k\) 的黑球,其位置增加的情况有 \(k\) 种,故总共增加的位置和为 \(s\),因此转移为 \((n,b,c,s)\rightarrow (n+1,b,(n+1)c,(n+2)s)\)
\(k\) 个白球:\((n,b,c,s)\rightarrow (n+k,b,\frac{(n+k)!}{n!}c,\frac{(n+k+1)!}{(n+1)!}s)\)
加一个黑球:对于每种方案,会有 \(b+1\) 个黑球位置 +1,总共增加 \((b+1)c\)\((n,b,c,s)\rightarrow (n+1,b+1,c,s+(b+1)c)\)

半在线与卷积技巧: 即在线计算 \(B_S=\sum_{T\in S}A_T\) 的值,记录 \(f_{S,i}\) 表示对于所有使得 \(T\) 的高 \(i\) 位与 \(S\) 相同而低位是 \(S\) 的子集的 \(A_T\) 之和,每当加入一个数 \(A_S\) 时,从低位到高位处理,计算的过程中顺便维护 \(f\)

三角剖分技巧: 平面三角剖分转对偶图后,每个点至多为三度点,因此边分治的复杂度是正确的。

数据结构优化转移: 当将一段数同时加若干相同的数时,可以线段树合并/分裂或使用 set 之类的东西。

区间位运算计数技巧: 任意一个区间 \([l,r]\) 都可以划分成至多 \(O(\log V)\) 个段,每段都形如 \([u2^k,(u+1)2^k)\),方便计数。

压位计算技巧: 往往类似 \(FWT\) 卷积的预处理可以优化掉一个 \(2^n\)

区间 dp 决策单调性优化计算 \(w(l,r)\) 技巧: 有时即使我们能通过决策单调性找到 \(mid\) 的最优决策点 \(k\),但我们还是不知道 \(w(k,mid)\) 是多少而难以转移,此时可以借鉴莫队的技巧,记录一个全局 \(L,R\),每次查询一个 \(w(k,mid)\) 的时候对 \(L,R\) 进行移动求出答案。由于决策单调性分治时只有 \(O(\log n)\) 层,每层 \(L,R\) 移动的距离之和最多为 \(O(n)\),因此这部分的时间复杂度为 \(O(n\log n)\)

区间异或区间取 mex 技巧: 在相应节点打 tag 代表其子树内的异或情况,pushdown 时若该深度对应位为 1 则交换左右子树。

lgx:SG 函数计算技巧: 有一个 01 串,每次选出一个 1 结尾的区间进行 01 反转,求谁赢。区间反转对应于直接删掉 \(i\) 并加入 \([j,i-1]\),因为一个位置有两个石子自然抵消。 打表得 SG 值为 \(lowbit(i)\)

zz:逐步调整技巧: 假设有一个变量,其最小值为 \(mn\),其最大值为 \(mx\)且存在一种变化方式,使得它每步变化至多为 \(1\) 那么对于任意 \(mn\le k\le mx\)均存在一个状态,使得该变量取值为 \(k\)

wcj:bitset 优化 01 FMT 技巧: 将数组 \(f\) 压入一个 \(ull\) 数组中,前 6 次蝴蝶变换记录一个 \(msk_i\) 通过 & 取出 \(msk_i\) 中的位进行处理, 之后的变换可以直接普通蝴蝶变换处理,时间复杂度 \(O(\frac{n2^n}{w}+2^n)=O(2^n)\)

lh:min + 矩乘 \(O(n^2)\) 技巧: 正常矩乘当然是 \(O(n^3)\) 的,但是,可以利用决策单调性之类的 dp 技巧优化这个转移变成 \(O(n^2)\)!在优化复杂度的同时,仍然可以视其为一个正常的矩阵,用线段树维护动态 dp !

线段树合并初值技巧: 先立下一个模板线段树,放好初值,每次线段树动态开点或线段树合并新建节点时,记录下当前所访问到的模板线段树位置, 并将新建节点的左右子节点以及 tag,mn 都复制过来。线段树合并时,判断如果是初始节点即返回(而不是空节点返回)。注意初始模板线段树的叶子节点的 mn 设为 a[l]tag 设为 0!注意合并到叶子节点时新的 mn 值不是两者的 mn 而是 mn[p]+tag[q]

lzy:因数枚举加速技巧: 当需要枚举一个序列 \(a\) 中所有 \(a_i\) 的倍数时,可以不断二分 \(a\) 中大于等于 \(ka_i\) 的第一个数,当 \(a\) 序列较短时加速效果明显。

公式2

\(B,C\) 中的元素值都是 \(v\) 时,可以双重递推计算

\[\det \begin{pmatrix} A & B \\ C & D \end{pmatrix} 与 \det_s \begin{pmatrix} A & B \\ C & D \end{pmatrix} \]

(递推到 $ \det A, \det_s A, \det D, \det_s D $ )。

其中 \(\det_s A\) 代表将 \(A\) 中任意一行全变成 \(1\) 之后求和。具体递推方式见 这里

重点在于计算将 \(A\) 中所有数都减去 \(t\) 之后的矩阵 \(A_t\)\(\det\)\(\det_s\) 值。

实现

当计算中可能出现 0 的逆元时,可以考虑定义整数类 Int,存储结果为 \(x \cdot p^y\)

将整个 bitset 翻转(不是01反转)过来,可以先用 to_string 转化成字符串,字符串翻过来,再转化回去(不过是 \(O(n)\) 的)

当数组需要负数下标时,可以先找出所有负数的最小值,然后将偏移量设为这个最小值的相反数(而不是事先定义,会浪费很多空间)

dp 过程中,如果要连做两件相同的事(如连加两个相同的数),一个好主意是把同一份代码复制两遍

子集卷积在 \(k\) 较小(\(\le 17\))时往往暴力 \(3^k\) 可以爆踩 \(2^kk^2\)!特别是 dp 数组中 \(0\) 很多完全跑不满时!!

CDQ 分治不要新开一个数组来排序,直接原地排序并扫一遍,甚至可以直接用 inplace_merge

LCT 求子树大小: 对每个节点 \(u\) 记录一个 \(xsz_u\) 表示 \(u\) 的虚子树大小和,改变 splay 形态时可以动态更新这个 \(xsz_u\)\(sz_u=sz_{lc[u]}+sz_{rc[u]}+1+xsz_u\)注意查询子树大小前要对 \(u\) 进行 splay 操作!

wcj:计算旋转角技巧: \((x,y)\) 转角 \(\theta\) 即为 \((x+yi)(cos\theta+isin\theta)\)

wlx:环上重合区间计数技巧: 首先将所有区间端点变为 \([0,2\pi)\) 内,然后若右端点小于左端点则加上 \(2\pi\)。接下来将所有区间的 \(r-2\pi\) 插入一个优先队列中,对每个区间按左端点排序,每次弹队列直至队头大于左端点,答案加上队列大小,然后再塞入右端点即可。注意如果有区间长度大于 \(\pi\) 时不适用!

因数枚举技巧: 有时当一道题需要求很大值域内的因数(如 \(3\times 10^6\))时,可以考虑不是预处理因数而是利用 vis 数组现场求出其所有质因子,进而得到所有因数。可能会有玄学优化效果。

卡常专题:

SegmentTree Beats 卡常技巧:当新赋的值比当前节点的 max 还大时直接 return
当返回值只是用来计算表达式时可以定义为 static 类型并 const X& 形式返回

时间戳树状数组:不要用 vector 来存改变过的值,而是记录一个时间戳 tim,清空时直接 tim++,一个位置的值有效当且仅当 t[i]=tim

wlx:bitset 卡常技巧: 手动特判当 \(n\) 较小时使用较小的 bitset,\(n\) 开满时才使用大的 bitset。这样可以保证被卡常只会挂成 70 分之类的(而非 0 分,因为 bitset 永远对所有位运算),同时有助于争最优解

wlx:取模卡常技巧: 当模数不固定时,可以考虑使用 __int128 进行优化,不要取模,宁可使用 __int128(若模数固定,可以两者都写一遍测一测速度 ——wlx)

posted @ 2022-07-17 09:30  CharlieVinnie  阅读(142)  评论(0编辑  收藏  举报