【杂文】随心一记
一:【可能会用到的小知识】
-
数据较小 ((n leqslant 20)) 的题通常有三种做法:搜索,状压,高维大状态 (dp) 。
-
在对一个矩阵进行重复的覆盖操作时可用冰茶姬优化枚举【例 (1)】 【例 (2)】。(后来在一次考试中,(T3) 因时间不足只能打 (25pt) 的 (kn^3) 暴力,当时突发奇想,用类似的思路优化了树上向根节点的跳跃,变为 (kn^2) 拿了 (35pt))
-
求最大值最小可用二分,第 (K) 大最小亦可。
-
判断树上两条路径 ((a,b),(c,d)) 是否相交:必定有其中一条路径的两个端点的 (LCA) 在另一条路径上。设
lca1=LCA(a,b),lca2=LCA(c,d)
且deep[lca1]>=deep[lca2]
,当满足(LCA(lca1,c)=lca1||LCA(lca1,d)=lca1)
时成立。 【例 (1)】 【例 (2)】 -
一颗无根树上任意一条路径必定可以在以某个叶节点为根时,变成一条从上到下的路径(利于广义 (SAM) 的使用)。【例 (1)】
-
莫队离线处理序列上的区间询问时,如果所有区间互不包含或互不重叠,指针转移的复杂度可降为 (O(n)) 。【例 (1)】
-
已知一条直线 (Ax+By+C=0),对于直线上方的点 ((x_0,y_0)),(Ax_0+B_0y+C) 的正负性均与 (A * B) 相同 【例 (1)】 。
-
概率顺推,期望逆推。
-
(or) 运算的 ( ext{FWT}) 求点值相当于是在做子集求和,即计算 (f(S)=sum_{Tsubseteq S}g(T))。也可以用 ( ext{FMT}) 简单实现。两者复杂度均为 (O(nlog n)),而暴力枚举子集复杂度为 (O(3^n))。【例 (1)】
-
看见方格矩阵先黑白染色冷静一下。
-
(T(n)=T(frac{n}{2})+O(nlog n)Longrightarrow T(n)=O(nlog n)) 。
二:【算法细节、坑点】
-
写珂朵莉时注意:枚举
itl=split(l)
到itr=split(r+1)
如果用了 (while()),在一大堆操作后面要加一句++itl;
(( ext{inf}) 次)。 -
写 ( ext{kosaraju}) 时注意:储存询问给出的边时,空间要开成 (M) 而不是 (N)((3) 次)。
-
写 ( ext{tarjan}) 时注意:若用 (ip[x]) 表示 (x) 所在强联通分量编号,计算缩点后图中点的度数时应取 ((ip[x],ip[y])) 而不是 ((x,y))((4) 次)。
-
写线段树时注意:乘法标记要初始化为 (1)。标记可为 (0) 时初始化为 (-1)((1) 次) 。
-
写差分约束时注意:超源要把边连出去,一颗内向菊花图是跑不出结果的((1) 次)。
-
写 ( ext{Dinic}) 时注意:(bfs) 分层前 (dis[st]) 要初始化为 (1) 而不是 (0),如果没有使用 (vis) 数组的话就会出问题((1) 次)。
-
写主席树时注意:(change) 函数里面新开节点应写
p=++o;tr[p]=tr[q];
而不是if(!p)p=++o;tr[p]=tr[q];
否则信息会被覆盖掉 【例】 ((1) 次)。 -
写无返回值的函数时注意:用 (void) 啊!一定不要定义成 (int,long long) 或者 (double),例如用取地址符的快读,手写 (swap) 等等,其危害巨大且不易察觉((3) 次)。
-
写莫队时注意:块的大小应该为 (sqrt{n}) 而不是 (sqrt{T})((3) 次)。
-
写莫队时注意:答案数组要开到 (T) 而不是 (N)((4) 次)。
-
写 ( ext{Trie}) 树 时注意:如果第一个节点为 (1),那么 (cnt) 应初始化为 (1)((2) 次)。
-
写 带修莫队 时注意:仅当修改下标在 ([nowL,nowR]) 以内时才执行 (add(),del()),但 (swap) 无论如何都必须要执行((1) 次)。
-
写 ( ext{Manacher}) 时注意:以 (i) 为中点半径为 (r) 的回文串实际长度为
r-!(i+r&1)
(如果 (i) 与 (r) 奇偶性相同则长度为 (r-1) 否则为 (r))。如果 (r) 为 (i) 的最大半径,那么 (i) 与 (r) 奇偶性一定相同,所以通常是直接算作 (r-1),但有时候【例】也会用非最大半径进行计算,此时则不能直接用 (r-1)((1) 次)。 -
写树上线段树合并时注意:通常我们是合并了一颗子树里的所有信息后直接查询节点,并且此后不会再次查询这个点,所以 (merge(p,q)) 时可以将合并后的信息放到 (p) 里面返回。但如果要在合并结束后多次查询各个点的信息【例】,就必须新建节点返回,否则节点信息会丢失 ((1) 次)。
-
写 ( ext{FFT/NTT}) 时注意:如果确定思路没问题但是连样例都过不了,(99\%) 是初始化数组出了问题(( ext{inf}) 次)。
-
写 ( ext{Trie}) 树时注意:节点个数不用乘以字符集大小啊!!!(( ext{inf}) 次)。
-
写主席树时注意:空间复杂度在 (O(2nlog n)) 以上,树状数组套主席树是 (O(nlog^2 n))(( ext{inf}) 次)。
-
写 ( ext{SAM}) 时注意:在写 ( ext{SAM}) 转后缀树转后缀数组时(或者某些题目),需要求 (pos) 数组((pos[p]) 表示节点 (p) 在原串上的终止位置),则复制节点 (x) 到 (y) 时 (pos) 也应一同复制((2) 次)。
-
写结构体时注意:两个大结构体之间的赋值尽量不要直接用 (=) 符号,自己手写个 (operator) 暴力 (for) 枚举赋值会快无数倍。【例】((1) 次)。
-
写 ( ext{LCT}) 时注意:如果维护了虚+实子树信息和,在 (link(x,fa)) 时要对 (fa) 进行 (access) 和 (splay),避免 (fa) 的祖先节点信息缺失((1) 次)。
-
写动态开点线段树时注意:一次单点修改的空间为 (lceil log_2 n ceil+1),尤其是写线段树合并时极易被卡(( ext{inf}) 次)。
-
写可持久化 ( ext{Trie}) 树时注意:一次插入的空间为 (lceil log_2 n ceil+2)((2) 次)。
-
写 ( ext{Splay}) 时注意:(insert) 时要给新建的节点设置好 (fa) 啊啊啊!(( ext{inf}) 次)。
-
写 ( ext{SAM}) 时注意:(while) 语句里面要在末尾写
p=link[p];
啊...(( ext{inf})次)。 -
写 水平序求凸包 时注意:下凸包为 (P_{1sim St}),上凸包为 (P_{Stsim cnt+1}) ((1) 次)。
-
写 三进制插头 ( ext{DP}) 时注意:在求出 (Mi) 数组之后再获取 (V),不要直接写
V=1<<m+1
((2) 次)。 -
写最大子段和时注意:线段树中 (max,lmax,rmax) 都初始化为该点权值,但 ( ext{Splay}) 中的 (lmax,rmax) 要初始化为 (0),且不能用他们单独更新 (max)((2) 次)。
-
写 ( ext{Splay}) 时注意:(rotate) 函数在 (connect) 后要对 (fa,p) 进行 (pushup)(( ext{inf}) 次)。
-
写莫队时注意:把两种 (add) 放在 (del) 的前面(且 (addR) 要在最前 ),否则会计算到 (L>R) 的区间 【例】((1) 次)。
三:【巨佬们的经典语录集】
【LSY】
-
我真的觉得我的写法非常简单,瞬间就想出来了,而且代码也很好写,不就是个启发式合并加树上懒标记维护动态倍增 ( ext{lca}) 嘛。
-
大部分题都可以用 ( ext{Trie}) 树搞。
【HZH】
-
我要是 ( ext{A}) 了这道题就去持矢。
-
这次的题好难啊,我只会暴力枚举(
吊打std的暴力)和输出 ( ext{rand()})(暴切神仙题的随机)。
【ZTH】
-
我要是 ( ext{rank1}) 就女装。
-
我最喜欢调这种玄学 ( ext{bu})。
【HYJ】
-
这个妹纸这么可爱,一定是男的!(你在渴望些什么?)
【其他】
我感觉我整个人都自动机了…… ——(bztMinamoto)(回文自动机学习笔记)
组合意义天地灭,代数推导保平安。 —— (tiger0133)
这不就是个裸的可持久化动态凸包加可持久化动态树构造广义后缀自动机转广义后缀树得到后缀数组然后上可持久化动态仙人掌在虚树上做可持久化动态点分治维护最小费用无源汇有上下界可行流再套上任意模数分治快速数论变换对生成函数多项式求逆跑牛顿迭代的联赛难度水题吗?