方法论:万物皆朴素的第一性原理

几乎任何领域的任何问题的解决方案,都可以看作是“某个结构上的朴素方法的优化“。

计算机只能处理规模有限的问题,在给定规模且不考虑效率的情况下,问题一定存在朴素解法。具体手段有直接模拟 / 利用bit枚举 / 各种搜索算法等。

具体方法:从问题到解决方案

一般的问题我们有一般的思考方式,而特殊的问题经过总结可以形成特定的解决方案,供今后调用。这需要长时间的积累。

举出一些算法竞赛中常用的问题——解决方案的思路:

  • 若问题具备 ”线性多维逆序“ 结构,则考虑 CDQ分治。

  • 若问题具备 ”元素唯一归属于某集合“ 结构,则考虑并查集。

  • 若问题具备 ”连通性“ 结构,则考虑搜索 / 并查集。

  • 若问题具备 ”记录数据未来使用“,则考虑哈希表。

  • 若问题具备 “FILO / 可规约” 结构,则考虑栈。

  • 若问题具备 ”线性结构上地最远/近最大/小元素“ 结构,则考虑单调栈。

  • 若问题具备 ”FIFO“ 结构,考虑队列。

  • 若问题具备 ”动态维护滑动窗口“ 结构,考虑单调队列。

  • 若问题具备 ”字符串” 结构,则考虑如下做法:

    • 若问题具备 ”字符串匹配“ 结构,则考虑如下做法:
      • 若为线性结构,考虑KMP
      • 若为Trie结构,考虑AC自动机
    • 若问题具备 ”求最长回文子串” 结构,则考虑Mancher算法。
  • 若问题具备 “某节点只有一个父节点” 结构,考虑树结构的如下做法:

    • 若问题具备 “树的重心/直径/中心/最近公共祖先” 结构,则按经典算法处理。
    • 若问题具备 “子树的相同问题” 结构,则考虑递归。
    • 若问题具备 “子树的相似问题” 结构,则考虑树形Dp。
    • 若问题具备 “对树的操作在区间上简单” 结构,则考虑 树链剖分 + 区间维护
  • 若问题具备 “序无关 / 要求某种序” 结构,则考虑排序。

  • 若问题具备 “求解难, 但是验证解是否可行容易” 结构,则考虑二分答案。

  • 若问题具备 “最大最小 or 最小最大 or 结果单调性/二分性” 结构,则考虑二分。

  • 若问题具备 “枚举单调性” 结构,则考虑双指针。

  • 若问题具备 “大数计算”,则考虑高精度。

  • 若问题具备 “数据范围大但涉及范围小”,则考虑离散化。

  • 若问题具备 “子问题” 结构,则考虑动态规划。

    • 若问题具备 ”从1到n符合某些数位限制的个数”,则考虑数位DP
    • 若动态规划问题具备 “棋盘上联通约束” 结构,则考虑状态压缩dp
    • 若动态规划问题具备 ”固定长度区间最值“ 结构,则考虑单调队列优化。
    • 若动态规划问题具备 ”“ 结构,则考虑斜率优化。
    • 若动态规划问题具备 ”“ 结构,则考虑四边形不等式优化。
  • 若问题具备 “解空间无限 / 有明显优秀策略“ 结构,考虑贪心。

  • 若问题具备 “分块” 结构,则考虑 分块 / 块状链表 / 莫队优化暴力

  • 若问题具备 ”区间性质“ 结构,则考虑以下经典做法:

    • 特殊地,若该性质是区间 ”选点/分组/覆盖/最大不相交“ 的区间数,则按经典问题处理。
    • 否则,若该性质具备 ”区间减法 / 区间消去“ 结构,则考虑前缀和 / 差分 / 树状数组 / 线段树 / 平衡树 / 分块。
    • 否则,若该性质具备 ”区间加法 / 区间合并“ 结构,则考虑线段树 / 平衡树
  • 若问题具备 “状态迁移最少次数” 结构,则考虑最短路算法。

  • 若问题具备 “” 结构,则考虑最小生成树算法。

  • 若问题具备 “把图分成两部分” 结构,则考虑二分图算法。

  • 若问题具备 “把图变成拓扑图” 结构,则考虑强连通分量算法。

  • 若问题具备 “对拓扑图求拓扑序” 结构,则考虑拓扑排序算法。

  • 若问题具备 “对图恰好走一遍” 结构,则考虑欧拉路径和回路算法。

  • 若问题具备 “差分约束” 结构,则考虑图的差分约束算法。

  • 若问题具备 “判环” 结构,则考虑SPFA判环。

  • 若问题具备 ”面积并”,则考虑计算几何面积并。

  • 若问题具备 “最大公约数和最小公倍数“,则考虑gcd。

  • 若问题具备 “进制相关“ 结构,则考虑进制转换。

  • 若问题具备 “质数相关“ 结构,则考虑判定质数/分解质因数/质数筛

  • 若问题具备 ”约数相关” 结构,则考虑所有约数/求约数个数/求约束之和

  • 若问题具备 “欧拉函数相关” 结构,考虑欧拉函数算法

  • 若问题具备 “幂相关” 结构,考虑快速幂

  • 若问题具备 “”溢出long long但是时间限制不严格“ 结构,考虑龟速乘

  • 若问题具备 “矩阵运算相关“ 结构,考虑矩阵计算/矩阵快速幂

  • 若问题具备 ”阶乘计算相关“ 结构,考虑阶乘快速计算

  • 若问题具备 ”线性同余方程“ 结构,考虑扩展欧几里得

  • 若问题具备 “线性方程组相关” 结构,考虑高斯消元

  • 若问题具备 “组合数”,考虑求组合数的四种算法

  • 若问题具备 “容斥” 结构,考虑容斥计算

  • 若问题具备 “博弈论” 结构,考虑博弈论

当然这只是冰山一角,真正的细节还有很多。熟练的Coding是刻意练习的结果。
()

03-19 22:36