tricks + 性质 + 血泪教训(
没有给样例解释的题一定要先手动模拟一遍样例!!!
做题
看题可以先归纳出一些基本的结论。往一些自己很熟练的模型上面靠,如果对不上的话一定不要强转,当作一个没见过的新题做。
观察题目时思考:
-
题目是否暗藏着一个图,如果是这个图有什么性质?树?DAG?还是连边有可以刻画的规律?
-
操作是否可以用矩阵描述?
-
式子是否带有组合意义?
-
转化成折线?转化成括号匹配?
如果什么思路都没有就尝试多推一点性质和结论,每次感觉得到了一个重要的结论就尝试重新思考能否转化成什么新问题。
比较容易忘记的思考方向:
-
背包。
-
欧拉回路。
-
根号分治。
-
操作分块。
-
哈希。
-
二分一个值。
-
倒着考虑某些东西。
-
考虑序列的前缀和/差分序列。
尝试从部分分里面获得启发:询问固定了一个端点是否意味着启发你用扫描线?
dp
dp 不要局限在填表,尝试刷表。转移不一定要完全正确,如果你错误的转移不会对答案产生影响那就是正确的。
图
是否存在特殊的边?能否构建出最短路树?特殊图(DAG、点双、边双)是否会更好做且能够拓展?能否优化建图?
注意力惊人
-
注意到树是一个二分图。
-
注意到网格图也是二分图。
-
注意到 \(a\oplus b\le a+b\)。
-
随机数据下字符串的 border 长度期望不会太长。
-
\(a_i-a_j(i>j)=\sum_{k=j+1}^i a_k-a_{k-1}\)。
-
交换排列的两项会改变排列的逆序对数的奇偶性。
-
\(\prod(a_i+b_i)=\sum_{T\in S}(\prod_{i\in T}a_i)(\prod_{i\notin T}b_i)\)。证明考虑乘法分配律。
-
\(a\operatorname{and}b=((a\oplus(2^V-1))\operatorname{or}(b\oplus(2^V-1)))\oplus(2^V-1)\)。
-
\((a\operatorname{and}b)+(a\operatorname{or}b)=a+b\),\((a\operatorname{and}b)+(a\oplus b)=a\operatorname{or}b\)。
tricks?
-
0/1,左/右括号,+1/-1 这些问题尝试往平面/折线上靠。【P9338 合唱】
-
二分最后的答案,把不好维护的东西变成 \(0\) 和 \(1\)。【P2824 排序】
-
操作分块。【P5443 桥梁】
-
dp 有后效性但影响范围很小,考虑把后续决策压缩起来当成一维。P2157 学校食堂
-
费用提前计算。【P2365 任务安排】
-
\(a_i\) 严格递增不好做可以考虑所有 \(a_i\gets a_i-i\),限制变为严格不降。【CF713C Sonya and Problem Wihtout a Legend】
-
从小到大填字典序出问题了可以考虑倒着从大到小填字典序。【CF825E Minimal Labels】
-
维护出现次数的平方考虑拆贡献,即多出现一次对答案的贡献。可以拓展到维护其他东西。【CF802I】Fake News (hard)
-
求树上两个路径的交时,先对两个路径的端点两两取 lca,然后取深度最大的两个点作为新路径的两个端点,如果新的端点深度小于原来两个路径的 lca,代表路径无交。【HDU-6110 路径交】
-
\(g=\gcd(a_l,a_{l+1},\cdots,a_r)\) 随着 \(r\) 的增大最多只有 \(\log n\) 个不同的取值。【P9032 Neboderi】
-
\(\sum dep_{lca(x,y)}\) 可以把所有 \(1\) 到 \(y\) 的路径加一,然后查询 \(1\) 到 \(x\) 的路径和。
-
对经过的边的起点有限制可以从终点反着来。【CF1407 Egor in the Republic of Dagestan】
-
lca 可以通过预处理做到 \(O(n\log n)-O(1)\)。具体地,st 表预处理一段 dfs 序区间中深度最小的点的编号,令查询节点为 \(x,y\),特判 \(x=y\) 的情况后,答案为 \(fa(st[dfn_x+1,dfn_y])\)。
-
lcs 或 lcp 问题具有单调性可以二分长度。【P4094 字符串】
-
dp 计数去重的时候可以限制转移顺序保证你的结果在你的限制下有且仅有一种方式可达。【CF53E Dead Ends】
-
带有结合律重复进行的操作可以用快速幂优化。【P6190 魔法】
-
构造的时候可以得到一个显然的上下界,然后思考是否在所有情况都可以取到这个上下界。【CF1054G New Road Network】
-
可以通过加强或简化问题得到解然后回到原问题求解。如果限制很松很轻易就能找到一组差不多的解也可以尝试调整法。
-
养成手玩构造的习惯,对于小数据手玩或者搜索出几组解观察通性。得到小数据通解之后说不定可以可以递归之类地将大构造缩成小构造,最后缩到一个小范围直接打表即可。【P9727 Aqre】
-
曼哈顿距离(\(|x_i-x_j|+|y_i-y_j|\))转切比雪夫距离(\(\max\{|x_i-x_j|,|y_i-y_j|\}\)):将点的坐标 \((x,y)\) 转为 \((x+y,x-y)\)。
-
整体二分常见的 trick 是把数列中原来的数看作是插入操作。【P2617 Dynamic Rankings】
-
尽管取单位体积性价比最高的做法是在一般背包是错误的,其思想仍然在某些题目中有简化做法的作用。【P9140 背包】
-
如果形如 \(i\) 是 \(j\) 的子串,\(j\) 是 \(k\) 的子串的类链性结构可以把子串转化成后缀考虑。【CF700E Cool Slogans】
-
bitset 可以解决小字符集字符串匹配问题同时支持带修。考虑维护每个字符出现的集合,查询时顺序遍历待查串,维护哪些点仍然可以作为起点。【CF914F Substrings in a String】
-
不同模式串在同一个文本串中的出现次数之和是 \(O(n\sqrt{n})\) 的。证明考虑把所有模式串按照长度分类,长度相同时由于互不相同,所以在 \(O(n)\) 个出现位置上至多一个字符串被匹配,又因为不同长度之和为 \(n\),所以长度种类数只有 \(O(sqrt{n})\) 种,因此出现次数之和为 \(O(n\sqrt{n})\) 次。【CF963D Frequency of String】
-
区间 \(\gcd\) 等于差分数组上区间 \(\gcd\)。证明考虑辗转相除法。
-
\(n\times V\) 在可接受范围内可以记 \(v_{i,j}=[a_i\ge j]\) 往 2-sat 靠。【ABC277Ex Constrained Sums】
-
对于二者之间选一个并且不同点之间的选择会互相影响的题目,我们可以套路地将二者连边,转化成一个图上问题。【ABC302Ex Ball Collector】
-
二进制分组,如何想到的暂时未知。【CERC2023 Interactive Reconstruction】
-
合并 MST 时不会用到原来没用到的边。【P14362 道路修复】
-
合并长度为 \(a\) 和 \(b\) 的不相关操作序列的方案数为 \({a\choose b}\)。
-
偏移下标消掉一些项加速转移。【P12046 生成树!】
-
每次对没有被删除的点随机选一个操作等价于随机一个排列操作,如果已经被删了就跳过。【ARC165E Random Isolation】
教训 & 名人名言
-
石堆:做撤销的时候一定要从后往前撤销。
-
吃饭:你猜结论要知道自己猜的方向,哪些跟你统计的东西相关你往那边去猜。
-
无根树哈希时把子节点按哈希值排序再做。
-
递归函数如果有全局变量记得注意递归之后值可能有改变。
-
期望题式子带平方一定要拆平方。
-
使用 STL 堆时若重载运算符中调用了外界数组,若外界数组更改则堆的性质会被破坏,需要把外界数组的值作为一部分存在堆中,若需要实时对应值的变化则不能使用堆,考虑 set 把要更改的数拎出来删掉再加回去新的数。
树的重心
在一个无根树中,以重心为根,该树最大子树的节点最少。放一些链接。

浙公网安备 33010602011771号