精心整理2万字c++知识点

制作不易,求一键三连~

文章目录

  • 1、基本数据结构
    • 数组
    • 链表
    • 队列、单调队列、双端队列
  • 2、中极数据结构
    • 并查集与带权并查集
    • hash表
      • 自然溢出
      • 双hash
  • 3、高级数据结构
    • 树状数组
    • 线段树及其合并
      • Zkw线段树
      • Fhq线树
      • 超哥线段树
    • 平衡树
      • Treap随机平衡二叉树
      • Splay伸展树
      • Scapegoat Tree替罪羊树
      • 后缀平衡树
    • 块状数组、块状链表
    • 树套树
      • 线段树套线段树
      • 线段树套平衡树
      • 平衡树套线段树
    • 可并堆
      • 左偏树
      • 配对堆
    • KDTree、四分树
    • 舞蹈链(DLX)、二进制分组
    • 划分树
  • 4、可持久化数据结构
    • 可持久化线段树(主席树)
    • 可持久化平衡树
    • 可持久化块状数组
  • 5、字符串相关算法及数据结构
    • KMP
    • AC自动机
    • 后缀数组
    • 后缀树
    • 后缀自动机
    • 字典树Trie
    • Manacher
  • 6、图论相关
    • 最小生成树
      • Prim
      • Kruskal
    • 最短路、次短路、K短路
      • Spfa
      • Dijkstra
      • Floyd
    • 图的联通
      • 连通分量
      • 割点、割边
    • 网络流
      • 最大流
      • 最小割
      • 费用流
      • 分数规划
    • 树相关
      • 树上倍增、公共祖先
      • 树链剖分
      • 树的分治算法(点分治、边分治、动态树分治)
    • 动态树(LCT、树分块)
    • 虚树
    • prufer编码
    • 拓扑排序
    • 欧拉图
    • 二分图
      • KM算法
      • 匈牙利算法
    • 仙人掌算法
  • 7、数学相关
    • (扩展)欧几里得算法、筛法、快速幂
      • 斐蜀定理
      • 更相减损术
    • 欧拉函数与降幂
    • 费马小定理
    • 排列组合
      • Lucas定理
      • 杨辉三角
    • 乘法逆元
    • 矩阵乘法
    • 数学期望与概率
    • 博弈论
      • Sg函数
      • 树上删边游戏
    • 拉格朗日乘子法
    • 中国剩余定理
    • 线性规划与网络流
    • 辛普森积分
    • 模拟线性方程组
    • 容斥原理与莫比乌斯反演
    • 快速傅立叶变换
    • 大步小步BSGS法(扩展)
    • 高斯消元
    • 线性筛
    • Min25筛与杜教筛
    • 母函数
    • Burnside引理与Polya计数
    • Miller-Robin素数检测
    • Pollard大数分解
  • 8、动态规划
    • 基础形式(记忆化搜索、斯坦纳树、背包九讲)
      • 背包dp
      • 线性dp
      • 区间dp
      • 状压dp
      • 环形dp
      • 树形dp
      • 数位dp
      • 倍增dp
      • 插头dp
    • 斜率优化与四边形不等式优化
    • 环+外向树上的dp
  • 9、计算几何
    • 计算几何基础
    • 三位计算几何初步
    • 梯形剖分与三角形剖分
    • 凸包
    • 旋转卡壳
    • 半平面交
    • pick定理
    • 扫描线
  • 10、搜索相关
    • dfs、bfs
    • A*算法
    • 迭代加深搜索(IDA*)、双向广搜
  • 11、特殊算法
    • 莫队算法、树上莫队
    • 模拟退火
    • 爬山算法
    • 随机增量算法
  • 12、其他重要工具与方法
    • 模拟与贪心
    • 二分法、三分法(求偏导)
    • 分治、CDQ分治
    • 高精度
    • 离线
    • ST表
  • 13、STL
    • map
    • priority_queue
    • set
    • bitset
    • rope
  • 14、非常见算法
    • 朱刘算法
    • 弦图与区间图

1、基本数据结构

数组

数组(Array)是有序的元素序列。 [1] 若将有限个类型相同的变量的集合命名,那么这个名称为数组名。组成数组的各个变量称为数组的分量,也称为数组的元素,有时也称为下标变量。用于区分数组的各个元素的数字编号称为下标。数组是在程序设计中,为了处理方便, 把具有相同类型的若干元素按有序的形式组织起来的一种形式。 [1] 这些有序排列的同类数据元素的集合称为数组。
数组是用于储存多个相同类型数据的集合。

链表

链表是一种物理存储单元上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。链表由一系列结点(链表中每一个元素称为结点)组成,结点可以在运行时动态生成。每个结点包括两个部分:一个是存储数据元素的数据域,另一个是存储下一个结点地址的指针域。 相比于线性表顺序结构,操作复杂。由于不必须按顺序存储,链表在插入的时候可以达到O(1)的复杂度,比另一种线性表顺序表快得多,但是查找一个节点或者访问特定编号的节点则需要O(n)的时间,而线性表和顺序表相应的时间复杂度分别是O(logn)和O(1)。
使用链表结构可以克服数组链表需要预先知道数据大小的缺点,链表结构可以充分利用计算机内存空间,实现灵活的内存动态管理。但是链表失去了数组随机读取的优点,同时链表由于增加了结点的指针域,空间开销比较大。链表最明显的好处就是,常规数组排列关联项目的方式可能不同于这些数据项目在记忆体或磁盘上顺序,数据的存取往往要在不同的排列顺序中转换。链表允许插入和移除表上任意位置上的节点,但是不允许随机存取。链表有很多种不同的类型:单向链表,双向链表以及循环链表。链表可以在多种编程语言中实现。像Lisp和Scheme这样的语言的内建数据类型中就包含了链表的存取和操作。程序语言或面向对象语言,如C,C++和Java依靠易变工具来生成链表。

队列、单调队列、双端队列

队列是一种特殊的线性表,特殊之处在于它只允许在表的前端(front)进行删除操作,而在表的后端(rear)进行插入操作,和栈一样,队列是一种操作受限制的线性表。进行插入操作的端称为队尾,进行删除操作的端称为队头。
单调队列,即单调递减或单调递增的队列。使用频率不高,但在有些程序中会有非同寻常的作用。
deque(double-ended queue,双端队列)是一种具有队列和栈的性质的数据结构。双端队列中的元素可以从两端弹出,相比list增加[]运算符重载。

栈(stack)又名堆栈,它是一种运算受限的线性表。限定仅在表尾进行插入和删除操作的线性表。这一端被称为栈顶,相对地,把另一端称为栈底。向一个栈插入新元素又称作进栈、入栈或压栈,它是把新元素放到栈顶元素的上面,使之成为新的栈顶元素;从一个栈删除元素又称作出栈或退栈,它是把栈顶元素删除掉,使其相邻的元素成为新的栈顶元素。

2、中极数据结构

堆(Heap)是计算机科学中一类特殊的数据结构的统称。堆通常是一个可以被看做一棵完全二叉树的数组对象。

并查集与带权并查集

并查集,在一些有N个元素的集合应用问题中,我们通常是在开始时让每个元素构成一个单元素的集合,然后按一定顺序将属于同一组的元素所在的集合合并,其间要反复查找一个元素在哪个集合中。这一类问题近几年来反复出现在信息学的国际国内赛题中。其特点是看似并不复杂,但数据量极大,若用正常的数据结构来描述的话,往往在空间上过大,计算机无法承受;即使在空间上勉强通过,运行的时间复杂度也极高,根本就不可能在比赛规定的运行时间(1~3秒)内计算出试题需要的结果,只能用并查集来描述。
并查集是一种树型的数据结构,用于处理一些不相交集合(disjoint sets)的合并及查询问题。常常在使用中以森林来表示。
带权并查集是普通并查集的进阶版本,功能更加强大。

普通并查集只能判断两个元素是否在一个集合中,带权并查集可以维护集合元素之间的关系,这个关系由每个元素的权值维护。

对权值的维护,我们需要在find(),unite()操作中分别进行修改。

hash表

散列表(Hash table,也叫哈希表),是根据关键码值(Key value)而直接进行访问的数据结构。也就是说,它通过把关键码值映射到表中一个位置来访问记录,以加快查找的速度。这个映射函数叫做散列函数,存放记录的数组叫做散列表。
给定表M,存在函数f(key),对任意给定的关键字值key,代入函数后若能得到包含该关键字的记录在表中的地址,则称表M为哈希(Hash)表,函数f(key)为哈希(Hash) 函数。

自然溢出

溢出哈希表是在hash 表填入过程中,将冲突的元素顺序填入到溢出表中,而当查找过程中发现冲突时,就在溢出表中进行顺序查找。

双hash

双重哈希属于开放地址哈希中的一种解决冲突方案,也就是说如果一次哈希不能解决问题的时候,要再次哈希

3、高级数据结构

树状数组

树状数组或二叉索引树(英语:Binary Indexed Tree),又以其发明者命名为Fenwick树,最早由Peter M. Fenwick于1994年以A New Data Structure for Cumulative Frequency Tables为题发表在SOFTWARE PRACTICE AND EXPERIENCE。其初衷是解决数据压缩里的累积频率(Cumulative Frequency)的计算问题,现多用于高效计算数列的前缀和, 区间和。

线段树及其合并

线段树合并说全来就是动态开点权值线段树合并,所以你需要掌握权值线段树的基本知识以及知道什么是动态开点

对于两个普通权值线段树如果暴力合并的话复杂度将会是n log ⁡n,更别说是合并n棵权值线段树了(炸空间、炸内存),但是在动态开点权值线段树中,这一操作是可以优化为log n的。

Zkw线段树

递归式线段树的常数很大,经常被卡,而zkw线段树的常数很小

Fhq线树

FHQ Treap,又名无旋Treap,是一种不需要旋转的平衡树,是范浩强基于Treap发明的。FHQ Treap具有代码短,易理解,速度快的优点。(当然跟红黑树等更高级的平衡树比一下就是……)至少它在OI中算是很优秀的数据结构了。

超哥线段树

超哥线段树,实际上是线段树的标记永久化。

平衡树

平衡树(Balance Tree,BT) 指的是,任意节点的子树的高度差都小于等于1。常见的符合平衡树的有,B树(多路平衡搜索树)、AVL树(二叉平衡搜索树)等。平衡树可以完成集合的一系列操作, 时间复杂度和空间复杂度相对于“2-3树”要低,在完成集合的一系列操作中始终保持平衡,为大型数据库的组织、索引提供了一条新的途径。 [1]
设“2-3 树”的每个结点存放一组与应用问题有关的数据, 且有一个关键字 (>0的整数) 作为标识。关键字的存放规则如下:对于结点X, 设左、中、右子树均不空, 则左子树任一结点的关键字小于中子树中任一结点的关键字;中子树中任一结点的关键字小于结点X的关键字;而X的关键字又小于右子树中任一结点的关键字, 称这样的“2-3树”为平衡树。[1]

Treap随机平衡二叉树

树堆(Treap)是二叉排序树(Binary Sort Tree)与堆(Heap)结合产生的一种拥有堆性质的二叉排序树。

Splay伸展树

Splay(伸展树)是一种二叉排序树,它能在O(log2 n)的时间内完成插入、查找和删除操作。

Splay(伸展树)能实现线段树不能实现的操作,比如区间翻转。

Splay的核心函数是旋转操作,将点x旋转至点k下面。特别的rotate (x, 0)表示把x旋转至根。旋转操作不会改变每个节点在该树的中序遍历中的位置。

旋转的目的:在每次查询、修改操作完,将操作的节点旋转到根,就像是输入法,常用的词汇会在第一页就出现,如果是第一次用,则需要翻好几页。可以保证均摊的时间复杂度为 [公式] 。

Scapegoat Tree替罪羊树

替罪羊树是计算机科学中,一种基于部分重建的自平衡二叉搜索树。在替罪羊树上,插入或删除节点的平摊最坏时间复杂度是O(log n),搜索节点的最坏时间复杂度是O(log n)

后缀平衡树

如果需要动态维护后缀数组,支持在字符串前端插入一个字符,询问后缀的大小关系,如何做呢?

这是一个不断插入的问题,可以从增量的角度考虑。我们在前端插入一个字符,其实就是插入了一个新的后缀。我们的问题其实就是这个后缀排名多少。我们可以用平衡树维护一下后缀数组,从根节点开始二分比较这个后缀的大小,看看它应该被插到哪里。现在问题就变成了快速比较一个新的后缀和一个已有的后缀。

如果这个新的后缀和当前比较的后缀的首字符不同,那么比较结果是显然的;如果新的后缀和当前比较的后缀的首字符相同,那么问题就转化成了比较原来已有的两个后缀的大小关系。我们在平衡树的每个节点上维护一个值x∈[0,1],代表它的大小,左儿子为的关键值为[l,mid],右儿子的关键值为[mid,r],那么只要直接比较这个值就可以啦。

然而如果平衡树的深度过大,那么这个值会爆实数的精度。所以我们采用深度为O(logn)的平衡树。但如果平衡树需要旋转,那么它的子树需要全部重新计算关键值。所以我们需要使用重量平衡树,其子树大小均摊O(logn),所以每次插入旋转后整个子树重算一下。

块状数组、块状链表

块状数组,即把一个数组分为几个块,块内信息整体保存,若查询时遇到两边不完整的块直接暴力查询。一般情况下,块的长度为O(√n) 。

树套树

线段树套线段树

树套树写法还是比较好理解的,不过要是让自己硬套的话可能很不容易套出来的

这里的二维线段树,外层线段树是对方阵的正投影,而内层线段树是对方阵的侧投影

线段树套平衡树

线段树的作用是区间修改和查询,平衡树的作用是查询第k大,k的排名,前驱,后继。这两个结合起来,就变成了可以区间修改和查询第k大,k的排名,前驱,后继的数据结构:树套树-线段树套平衡树。

平衡树套线段树

线段树维护的是区间,然后对于线段树维护的区间的所有数字都维护一个平衡树,然后所有的操作都对每个平衡树单独处理。

可并堆

可并堆,顾名思义,就是可以合并的堆。堆满足一个性质,就是当前节点,都大于或者等于他的所有子树上的节点,自然在这里我所讲的是结点的权值。显而易见,既然可并堆是堆的一种,容易推出,可并堆也满足这个性质。

左偏树

左偏树(英语:leftist tree或leftist heap),也可称为左偏堆、左倾堆,是计算机科学中的一种树,是一种优先队列实现方式,属于可并堆,在信息学中十分常见,在统计问题、最值问题、模拟问题和贪心问题等等类型的题目中,左偏树都有着广泛的应用。斜堆是比左偏树更为一般的数据结构。

配对堆

配对堆是一种实现简单、均摊复杂度优越的堆数据结构,由Michael Fredman、罗伯特·塞奇威克、Daniel Sleator、罗伯特·塔扬于1986年发明。配对堆是一种多叉树,并且可以被认为是一种简化的斐波那契堆。对于实现例如普林姆最小生成树算法等算法,配对堆是一个更优的选择,

KDTree、四分树

kd-tree(k-dimensional树的简称),是一种对k维空间中的实例点进行存储以便对其进行快速检索的树形数据结构。 [1] 主要应用于多维空间关键数据的搜索(如:范围搜索和最近邻搜索)。K-D树是二进制空间分割树的特殊的情况。
在计算机科学里,k-d树( k-维树的缩写)是在k维欧几里德空间组织点的数据结构。k-d树可以使用在多种应用场合,如多维键值搜索(例:范围搜寻及最邻近搜索)。k-d树是空间二分树(Binary space partitioning )的一种特殊情况。 [2]

四分树就是用一个类似于线段树的东西来维护一个矩阵,就是每个点有四个儿子
然后每个儿子代表切分之后的一块区域

舞蹈链(DLX)、二进制分组

舞蹈链(Dancing Links)算法在求解精确覆盖问题时效率惊人。

二进制分组就是把操作的数量二进制拆分,每个二进制位数用数据结构维护
合并的时候,暴力重构
每次查询,从logn个块依次用维护的数据结构查询

划分树

划分树定义为,它的每一个节点保存区间[lft,rht]所有元素,元素顺序与原数组(输入)相同,但是,两个子树的元素为该节点所有元素排序后(rht-lft+1)/2个进入左子树,其余的到右子树,同时维护一个num域,num[i]表示lft->i这个点有多少个进入了左子树。

4、可持久化数据结构

可持久化线段树(主席树)

主席树,也叫做可持久化线段树,准确来说,应该叫做可持久化权值线段树,因为其中的每一颗树都是一颗权值线段树。

所谓权值线段树,就是指线段树的叶子节点保存的是当前值的个数。这样说起来比较抽象,下面用具体例子来简单阐述。

可持久化平衡树

treap = tree + heap,即同时满足二叉搜索树和堆的性质。

为了使树尽可能的保证两边的大小平衡,所以有一个key值,使他满足堆得性质,来维护树的平衡,key值是随机的。
treap有一般平衡树的功能,前驱、后继、第k大、查询排名、插入、删除。也比较好写

可持久化块状数组

题目中要求可以查询历史状态,最暴力的想法是开a[m][n]的二维数组,每次修改暴力复制并修改,每次查询暴力扫描,时间复杂度是O(mn)的,但这显然是不行的.

这个时候其实很容易想到线段树,但线段树维护的是当前状态而无法维护历史状态,一种暴力的想法是开m棵线段树,但这样MLE的风险可谓巨大。

但我们发现,因为题目修改的是一个点的值,在线段树上,会被修改的点只有logn个,因此可以每次只新建这logn个结点

5、字符串相关算法及数据结构

KMP

KMP算法是一种改进的字符串匹配算法,由D.E.Knuth,J.H.Morris和V.R.Pratt提出的,因此人们称它为克努特—莫里斯—普拉特操作(简称KMP算法)。KMP算法的核心是利用匹配失败后的信息,尽量减少模式串与主串的匹配次数以达到快速匹配的目的。具体实现就是通过一个next()函数实现,函数本身包含了模式串的局部匹配信息。KMP算法的时间复杂度O(m+n) [1] 。

AC自动机

Aho-Corasick automaton,该算法在1975年产生于贝尔实验室,是著名的多模匹配算法。
要学会AC自动机,我们必须知道什么是Trie,也就是字典树。Trie树,又称单词查找树或键树,是一种树形结构,是一种哈希树的变种。典型应用是用于统计和排序大量的字符串(但不仅限于字符串),所以经常被搜索引擎系统用于文本词频统计。

后缀数组

在计算机科学里, 后缀数组(英语:suffix array)是一个通过对字符串的所有后缀经过排序后得到的数组。此数据结构被运用于全文索引、数据压缩算法、以及生物信息学。
后缀数组被乌迪·曼伯尔与尤金·迈尔斯于1990年提出,作为对后缀树的一种替代,更简单以及节省空间。它们也被Gaston Gonnet 于1987年独立发现,并命名为“PAT数组”。

后缀树

后缀树(Suffix tree)是一种数据结构,能快速解决很多关于字符串的问题。后缀树的概念最早由Weiner于1973年提出,既而由McCreight在1976年和Ukkonen在1992年和1995年加以改进完善。
一个string S的后缀树是一个边(edge)被标记为字符串的树。因此每一个S的后缀都唯一对应一条从根节点到叶节点的路径。这样就形成了一个S的后缀的基数树(radix tree)。后缀树是前缀树(trie)里的一个特殊类型。

后缀自动机

首先,后缀自动机是一种有限状态自动机,他可以识别且仅识别一个字符串的后缀。但是这不并不是后缀自动机强大的地方,我可以说如果把AC自动机反向插入我同样可以做到这一点。

后缀自动机真正的用处在于:它可以识别一个串的所有子串。

非常优秀的是后缀自动机只会有O(n)个节点,也就是说在字符集看做常数的情况下,对于后缀自动机的构建可以做到O(n)。

后缀自动机不同于AC自动机的地方在于:它并不是一棵树,不看prarent链的话,后缀自动机是一张DAG,这就让后缀自动机每一个节点的意义玄妙了起来。

字典树Trie

又称单词查找树,Trie树,是一种树形结构,是一种哈希树的变种。典型应用是用于统计,排序和保存大量的字符串(但不仅限于字符串),所以经常被搜索引擎系统用于文本词频统计。它的优点是:利用字符串的公共前缀来减少查询时间,最大限度地减少无谓的字符串比较,查询效率比哈希树高。

Manacher

马拉车算法 Manacher‘s Algorithm 是用来查找一个字符串的最长回文子串的线性方法,由一个叫Manacher的人在1975年发明的,这个方法的最大贡献是在于将时间复杂度提升到了线性。

6、图论相关

最小生成树

一个有 n 个结点的连通图的生成树是原图的极小连通子图,且包含原图中的所有 n 个结点,并且有保持图连通的最少的边。 [1] 最小生成树可以用kruskal(克鲁斯卡尔)算法或prim(普里姆)算法求出。

Prim

普里姆算法(Prim算法),图论中的一种算法,可在加权连通图里搜索最小生成树。意即由此算法搜索到的边子集所构成的树中,不但包括了连通图里的所有顶点(英语:Vertex (graph theory)),且其所有边的权值之和亦为最小。该算法于1930年由捷克数学家沃伊捷赫·亚尔尼克(英语:Vojtěch Jarník)发现;并在1957年由美国计算机科学家罗伯特·普里姆(英语:Robert C. Prim)独立发现;1959年,艾兹格·迪科斯彻再次发现了该算法。因此,在某些场合,普里姆算法又被称为DJP算法、亚尔尼克算法或普里姆-亚尔尼克算法。

Kruskal

克鲁斯卡尔算法是求连通网的最小生成树的另一种方法。与普里姆算法不同,它的时间复杂度为O(eloge)(e为网中的边数),所以,适合于求边稀疏的网的最小生成树 [1] 。

最短路、次短路、K短路

Spfa

SPFA 算法是 Bellman-Ford算法 的队列优化算法的别称,通常用于求含负权边的单源最短路径,以及判负权环。SPFA 最坏情况下复杂度和朴素 Bellman-Ford 相同,为 O(VE)。

Dijkstra

迪杰斯特拉算法(Dijkstra)是由荷兰计算机科学家狄克斯特拉于1959年提出的,因此又叫狄克斯特拉算法。是从一个顶点到其余各顶点的最短路径算法,解决的是有权图中最短路径问题。迪杰斯特拉算法主要特点是从起始点开始,采用贪心算法的策略,每次遍历到始点距离最近且未访问过的顶点的邻接节点,直到扩展到终点为止。 [1]

Floyd

Floyd算法又称为插点法,是一种利用动态规划的思想寻找给定的加权图中多源点之间最短路径的算法,与Dijkstra算法类似。该算法名称以创始人之一、1978年图灵奖获得者、斯坦福大学计算机科学系教授罗伯特·弗洛伊德命名。 [1]

图的联通

连通分量

无向图G的极大连通子图称为G的连通分量( Connected Component)。任何连通图的连通分量只有一个,即是其自身,非连通的无向图有多个连通分量。

割点、割边

在一个无向图中,如果有一个顶点集合,删除这个顶点集合以及这个集合中所有顶点相关联的边以后,图的连通分量增多,就称这个点集为割点集合。
如果某个割点集合只含有一个顶点X(也即{X}是一个割点集合),那么X称为一个割点。

假设有连通图G,e是其中一条边,如果G-e是不连通的,则边e是图G的一条割边。此情形下,G-e必包含两个连通分支。

网络流

网络流(network-flows)是一种类比水流的解决问题方法,与线性规划密切相关。网络流的理论和应用在不断发展,出现了具有增益的流、多终端流、多商品流以及网络流的分解与合成等新课题。网络流的应用已遍及通讯、运输、电力、工程规划、任务分派、设备更新以及计算机辅助设计等众多领域。

最大流

管道网络中每条边的最大通过能力(容量)是有限的,实际流量不超过容量。
最大流问题(maximum flow problem),一种组合最优化问题,就是要讨论如何充分利用装置的能力,使得运输的流量最大,以取得最好的效果。求最大流的标号算法最早由福特和福克逊于1956年提出,20世纪50年代福特(Ford)、福克逊(Fulkerson)建立的“网络流理论”,是网络应用的重要组成成分。

最小割

最小割,图中所有的割中,边权值和最小的割为最小割。

费用流

最小费用流问题是一种组合最优化问题,也是网络流理论研究的一个重要问题。

分数规划

树相关

树上倍增、公共祖先

LCA(least common ancestors)最近公共祖先
指的就是对于一棵有根树,若结点z既是x的祖先,也是y的祖先,那么z就是结点x和y的最近公共祖先。

对于有根树T的两个结点u、v,最近公共祖先LCA(T,u,v)表示一个结点x,满足x是u和v的祖先且x的深度尽可能大。在这里,一个节点也可以是它自己的祖先。

树链剖分

树链剖分,计算机术语,指一种对树进行划分的算法,它先通过轻重边剖分将树分为多条链,保证每个点属于且只属于一条链,然后再通过数据结构(树状数组、BST、SPLAY、线段树等)来维护每一条链。

树的分治算法(点分治、边分治、动态树分治)

点分治,顾名思义就是基于树上的节点进行分治。
如果我们在深入一点呢?对于点的拆开其实就是对于树的拆开。
所以我认为点分治的本质其实是将一棵树拆分成许多棵子树处理,并不断进行。
这应该也是点分治的精髓。
边分治的分治过程与点分治类似,同样每次分治时找到一条分治中心边使这条边两端的两个联通块中较大的一个尽量小。以分治中心边为界限,恰好将当前分治的联通块中的点分成了两部分,统计路径经过分治中心边的答案,然后将分治中心边断开,递归分治中心边两端的两个联通块。
动态树分治,顾名思义,解决待修改的树分治问题。原本的树分治基于边或者重心的分治可以解决大多数静态树链问题,但是待修改怎么办?其实很简单,因为树结构是不变的,就是树分治的基础结构不变,对于修改和询问,只需要在第一次树分治的基础上用一些数据结构维护一些信息即可。

动态树(LCT、树分块)

动态树问题 ,是一类要求维护一个有根树森林,支持对树的分割, 合并等操作的问题。由RobertE.Tarjan为首的科学家们提出解决算法Link-Cut Trees,简称LCT。

虚树

虚树,是对于一棵给定的节点数为 n 的树 T,构造一棵新的树 T’ 使得总结点数最小且包含指定的某几个节点和他们的LCA。

prufer编码

prufer是无根树的一种编码方式,一棵无根树和一个prufer编码唯一对应,也就是一棵树有唯一的prufer编码,而一个prufer编码对应一棵唯一的树。

拓扑排序

对一个有向无环图(Directed Acyclic Graph简称DAG)G进行拓扑排序,是将G中所有顶点排成一个线性序列,使得图中任意一对顶点u和v,若边∈E(G),则u在线性序列中出现在v之前。通常,这样的线性序列称为满足拓扑次序(Topological Order)的序列,简称拓扑序列。简单的说,由某个集合上的一个偏序得到该集合上的一个全序,这个操作称之为拓扑排序。 [1]

欧拉图

欧拉图是指通过图(无向图或有向图)中所有边且每边仅通过一次通路,相应的回路称为欧拉回路。具有欧拉回路的图称为欧拉图(Euler Graph),具有欧拉通路而无欧拉回路的图称为半欧拉图。对欧拉图的一个现代扩展是蜘蛛图,它向欧拉图增加了可以连接的存在点。这给予欧拉图析取特征。欧拉图已经有了合取特征(就是说区定义了有着与起来的那些性质的对象在区中的存在)。所以蜘蛛图允许使用欧拉图建模逻辑或的条件。

二分图

二分图又称作二部图,是图论中的一种特殊模型。 设G=(V,E)是一个无向图,如果顶点V可分割为两个互不相交的子集(A,B),并且图中的每条边(i,j)所关联的两个顶点i和j分别属于这两个不同的顶点集(i in A,j in B),则称图G为一个二分图。

KM算法

KM算法用来求二分图最大权完美匹配。

匈牙利算法

匈牙利算法是一种在多项式时间内求解任务分配问题的组合优化算法,并推动了后来的原始对偶方法。1955年,库恩(W.W.Kuhn)利用匈牙利数学家康尼格(D.Kőnig)的一个定理构造了这个解法,故称为匈牙利法。 [2]

仙人掌算法

仙人掌图:每条边至多在一个环上的图。
仙人掌图中每个环相当于一个点双连通分量,那么用Tarjan算法处理dfs树。

7、数学相关

(扩展)欧几里得算法、筛法、快速幂

扩展欧几里得算法是欧几里得算法(又叫辗转相除法)的扩展。除了计算a、b两个整数的最大公约数,此算法还能找到整数x、y(其中一个很可能是负数)。通常谈到最大公因子时, 我们都会提到一个非常基本的事实: 给予二整数 a 与 b, 必存在有整数 x 与 y 使得ax + by = gcd(a,b)。有两个数a,b,对它们进行辗转相除法,可得它们的最大公约数——这是众所周知的。然后,收集辗转相除法中产生的式子,倒回去,可以得到ax+by=gcd(a,b)的整数解。
筛法(挨拉托色尼筛法)是一种用来求所有小于N的素数的方法。把从2(素数是指大于1的自然数)开始的某一范围内的正整数从小到大按顺序排列,逐步筛掉非素数留下素数。
顾名思义,快速幂就是快速算底数的n次幂。其时间复杂度为 O(log₂N), 与朴素的O(N)相比效率有了极大的提高。

斐蜀定理

在数论中,裴蜀定理是一个关于最大公约数(或最大公约式)的定理,裴蜀定理得名于法国数学家艾蒂安·裴蜀。
裴蜀定理说明了对任何整数 a、b和它们的最大公约数 d ,关于未知数 x以及 y 的线性的丢番图方程(称为裴蜀等式)。

更相减损术

更相减损术是出自《九章算术》的一种求最大公约数的算法,它原本是为约分而设计的,但它适用于任何需要求最大公约数的场合。

欧拉函数与降幂

在数论,对正整数n,欧拉函数是小于n的正整数中与n互质的数的数目。

把一个多项式的各项按照某个字母的指数从大到小的顺序排列,叫做这一字母的降幂。如ab+(-2ba)+a为a的降幂。

费马小定理

费马小定理 (Fermat’s little theorem) 是数论中的一个重要定理,在1636年提出。如果p是一个质数,而整数a不是p的倍数,则有a ^ (p - 1) ≡ 1 (mod p)。[1]

排列组合

Lucas定理

Lucas定理是用来求 c(n,m) mod p,p为素数的值。

杨辉三角

杨辉三角,是二项式系数在三角形中的一种几何排列,中国南宋数学家杨辉1261年所著的《详解九章算法》一书中出现。在欧洲,帕斯卡(1623----1662)在1654年发现这一规律,所以这个表又叫做帕斯卡三角形。帕斯卡的发现比杨辉要迟393年,比贾宪迟600年。 [1]

乘法逆元

乘法逆元,是指数学领域群G中任意一个元素a,都在G中有唯一的逆元a‘,具有性质a×a’=a’×a=e,其中e为该群的单位元。

矩阵乘法

矩阵相乘最重要的方法是一般矩阵乘积。它只有在第一个矩阵的列数(column)和第二个矩阵的行数(row)相同时才有意义 [1] 。一般单指矩阵乘积时,指的便是一般矩阵乘积。一个m×n的矩阵就是m×n个数排成m行n列的一个数阵。由于它把许多数据紧凑地集中到了一起,所以有时候可以简便地表示一些复杂的模型,如电力系统网络模型。 [2]

数学期望与概率

在概率论和统计学中,数学期望(mean)(或均值,亦简称期望)是试验中每次可能结果的概率乘以其结果的总和,是最基本的数学特征之一。它反映随机变量平均取值的大小。
需要注意的是,期望值并不一定等同于常识中的“期望”——“期望值”也许与每一个结果都不相等。期望值是该变量输出值的平均数。期望值并不一定包含于变量的输出值集合里。
大数定律表明,随着重复次数接近无穷大,数值的算术平均值几乎肯定地收敛于期望值。

博弈论

博弈论,又称为对策论(Game Theory)、赛局理论等,既是现代数学的一个新分支,也是运筹学的一个重要学科。
博弈论主要研究公式化了的激励结构间的相互作用,是研究具有斗争或竞争性质现象的数学理论和方法。博弈论考虑游戏中的个体的预测行为和实际行为,并研究它们的优化策略。生物学家使用博弈理论来理解和预测进化论的某些结果。
博弈论已经成为经济学的标准分析工具之一。在金融学、证券学、生物学、经济学、国际关系、计算机科学、政治学、军事战略和其他很多学科都有广泛的应用。

Sg函数

给定一个有向无环图和一个起始顶点上的一枚棋子,两名选手交替的将这枚棋子沿有向边进行移动,无法移 动者判负。事实上,这个游戏可以认为是所有公平组合游戏的抽象模型。

树上删边游戏

在某一棵树上删除一条边,同时删去所有在删除后不再与根相连的部分
双方轮流操作,无法再进行删除者判定为失败
一个游戏中有多棵树,我们把ta们的根都放在地板上,方便之后的处理

在此,我们讨论的将是公平游戏,即双方都可以删除任意的树边
我们称这个游戏为:Green Hachenbush(树上公平删边游戏)

之所以强调是公平博弈,是因为还有另一种删边游戏,是不公平的,参与者双方一方只能删除蓝边,一方只能删除红边,而绿边双方都可以删除

拉格朗日乘子法

在数学最优问题中,拉格朗日乘数法(以数学家约瑟夫·路易斯·拉格朗日命名)是一种寻找变量受一个或多个条件所限制的多元函数的极值的方法。这种方法将一个有n 个变量与k 个约束条件的最优化问题转换为一个有n + k个变量的方程组的极值问题,其变量不受任何约束。这种方法引入了一种新的标量未知数,即拉格朗日乘数:约束方程的梯度(gradient)的线性组合里每个向量的系数。 [1] 此方法的证明牵涉到偏微分,全微分或链法,从而找到能让设出的隐函数的微分为零的未知数的值。

中国剩余定理

孙子定理是中国古代求解一次同余式组(见同余)的方法。是数论中一个重要定理。又称中国余数定理。一元线性同余方程组问题最早可见于中国南北朝时期(公元5世纪)的数学著作《孙子算经》卷下第二十六题,叫做“物不知数”问题,原文如下:
有物不知其数,三三数之剩二,五五数之剩三,七七数之剩二。问物几何?即,一个整数除以三余二,除以五余三,除以七余二,求这个整数。《孙子算经》中首次提到了同余方程组问题,以及以上具体问题的解法,因此在中文数学文献中也会将中国剩余定理称为孙子定理。

线性规划与网络流

线性规划(Linear programming,简称LP),是运筹学中研究较早、发展较快、应用广泛、方法较成熟的一个重要分支,它是辅助人们进行科学管理的一种数学方法。研究线性约束条件下线性目标函数的极值问题的数学理论和方法。英文缩写LP。
线性规划是运筹学的一个重要分支,广泛应用于军事作战、经济分析、经营管理和工程技术等方面。为合理地利用有限的人力、物力、财力等资源作出的最优决策,提供科学的依据。

辛普森积分

辛普森积分法是一种用抛物线近似函数曲线来求定积分数值解的方法。把积分区间等分成若干段,对被积函数在每一段上使用辛普森公式,根据其在每一段的两端和中点处的值近似为抛物线,逐段积分后加起来,即得到原定积分的数值解。辛普森积分法比梯形法则更精确,二者都是牛顿-柯特斯公式(Newton-Cotes)的特例。

模拟线性方程组

这个问题的源自《孙子算经》,其中有这样一道算术题:“今有物不知其数,三三数之剩二,五五数之剩三,七七数之剩二,问物几何?”按照今天的话来说:一个数除以3余2,除以5余3,除以7余2,求这个数.这样的问题,也有人称为“韩信点兵”.它形成了一类问题,也就是初等数论中解同余式.这类问题的有解条件和解的方法被称为“中国剩余定理”,这是由中国人首先提出的。

容斥原理与莫比乌斯反演

在计数时,必须注意没有重复,没有遗漏。为了使重叠部分不被重复计算,人们研究出一种新的计数方法,这种方法的基本思想是:先不考虑重叠的情况,把包含于某内容中的所有对象的数目先计算出来,然后再把计数时重复计算的数目排斥出去,使得计算的结果既无遗漏又无重复,这种计数的方法称为容斥原理。 [1]

莫比乌斯反演是数论数学中很重要的内容,可以用于解决很多组合数学的问题。

快速傅立叶变换

快速傅里叶变换 (fast Fourier transform), 即利用计算机计算离散傅里叶变换(DFT)的高效、快速计算方法的统称,简称FFT。快速傅里叶变换是1965年由J.W.库利和T.W.图基提出的。采用这种算法能使计算机计算离散傅里叶变换所需要的乘法次数大为减少,特别是被变换的抽样点数N越多,FFT算法计算量的节省就越显著。

大步小步BSGS法(扩展)

计算(y^x ≡ z mod p) 中 (x) 的解。

高斯消元

数学上,高斯消元法(或译:高斯消去法),是线性代数规划中的一个算法,可用来为线性方程组求解。但其算法十分复杂,不常用于加减消元法,求出矩阵的秩,以及求出可逆方阵的逆矩阵。不过,如果有过百万条等式时,这个算法会十分省时。一些极大的方程组通常会用迭代法以及花式消元来解决。当用于一个矩阵时,高斯消元法会产生出一个“行梯阵式”。高斯消元法可以用在电脑中来解决数千条等式及未知数。亦有一些方法特地用来解决一些有特别排列的系数的方程组。 [1]

线性筛

在刚接触编程语言时,对于寻找素数,第一时间想到的便是二重循环暴力查找,其复杂度O(n),通过循环中只判断到根号n可以优化一些,不过复杂度也达不到预期。在数论的学习中,我学到了埃氏筛法,O(nloglogn)的算法,而在一些数据范围达到1e7这样的题目中,也很难让人满意,于是我便学习了欧拉筛法,也即 O(n)的线性筛法。

Min25筛与杜教筛

考虑一个积性函数F(x),用来快速计算前缀和
∑i=1nF(i)
当然,这个积性函数要满足F(x),x∈Prime可以用多项式表示
同时,F(xk),x∈Prime要能够快速计算答案
杜教筛是用来求一类积性函数的前缀和
它通过各种转化,最终利用数论分块的思想来降低复杂度
假设我们现在要求S(n)=∑ni=1f(i),f(i)为积性函数,n⩽1012
直接求肯定是不好求的,不过现在假设有另一个积性函数g
我们来求它们狄利克雷卷积的前缀和

∑i=1n(g∗f)=∑i=1n∑d∣ig(d)f(id)

=∑d=1ng(d)∑d|if(id)

=∑d=1ng(d)∑i=1ndf(i)

=∑d=1ng(d)S(nd)

然后就化不动了,不过我们发现我们化出了nd!
但是S(n)怎么求呢?

容斥一下

g(1)S(n)=∑d=1ng(d)S(nd)−∑d=2ng(d)S(nd)

前半部分是狄利克雷卷积的前缀和的形式
后半部分可以数论分块。这样看起来就好搞多了
现在我们的问题是,如何选择g才能使得上面这个式子好算
这个就要因情况而定了

母函数

生成函数即母函数,是组合数学中尤其是计数方面的一个重要理论和工具。生成函数有普通型生成函数和指数型生成函数两种,其中普通型用的比较多。形式上说,普通型生成函数用于解决多重集的组合问题,而指数型母函数用于解决多重集的排列问题。母函数还可以解决递归数列的通项问题(例如使用母函数解决斐波那契数列的通项公式)。

Burnside引理与Polya计数

伯恩赛德引理(Burnside’s lemma),也叫伯恩赛德计数定理(Burnside’s counting theorem),柯西-弗罗贝尼乌斯引理(Cauchy-Frobenius lemma)或轨道计数定理(orbit-counting theorem),是群论中一个结果,在考虑对称的计数中经常很有用。该结论被冠以多个人的名字,其中包括威廉·伯恩赛德(William Burnside)、波利亚、柯西和弗罗贝尼乌斯。这个命题不属于伯恩赛德自己,他只是在自己的书中《有限群论 On the Theory of Groups of Finite Order》引用了,而将其归于弗罗贝尼乌斯 (1887)。

Burnside定理之所以能够计数不等价着色数,与它能够计算C(f)有关,而C中的原色不变是f保持的,通过考虑置换的循环结构计算可变得容易简便。

Miller-Robin素数检测

快速概率测素数的算法------MillerRobin(),适用于测试单个素数,出错概率比计算机本身出错的概率还要低

为(1/4)^(s),一般s取50就可以认为是准确测试出了。

算法是基于费马小定理(format),二次探测定理 x*x % p == 1 ,若P为素数,则x的解只能是x = 1或者x = p - 1)加上迭代乘法判断的Miller算法

Pollard大数分解

Pollard_rho算法的大致流程是 先判断当前数是否是素数(Miller_rabin)了,如果是则直接返回。如果不是素数的话,试图找到当前数的一个因子(可以不是质因子)。然后递归对该因子和约去这个因子的另一个因子进行分解。

8、动态规划

基础形式(记忆化搜索、斯坦纳树、背包九讲)

背包dp

背包问题(Knapsack problem)是一种组合优化的NP完全问题。问题可以描述为:给定一组物品,每种物品都有自己的重量和价格,在限定的总重量内,我们如何选择,才能使得物品的总价格最高。问题的名称来源于如何选择最合适的物品放置于给定背包中。相似问题经常出现在商业、组合数学,计算复杂性理论、密码学和应用数学等领域中。也可以将背包问题描述为决定性问题,即在总重量不超过W的前提下,总价值是否能达到V?它是在1978年由Merkle和Hellman提出的。
背包问题已经研究了一个多世纪,早期的作品可追溯到1897年 [1] 数学家托比亚斯·丹齐格(Tobias Dantzig,1884-1956)的早期作品 [2] ,并指的是包装你最有价值或有用的物品而不会超载你的行李的常见问题。

线性dp

线性DP是动态规划问题中的一类问题,指状态之间有线性关系的动态规划问题。

区间dp

区间dp就是在一段区间上进行动态规划。对于每段区间,他们的最优值都是由几段更小区间的最优值得到,是分治思想的一种应用,将一个区间问题不断划分为更小的区间直至一个元素组成的区间,枚举他们的组合 ,求合并后的最优值。

状压dp

状态压缩动态规划,就是我们俗称的状压DP,是利用计算机二进制的性质来描述状态的一种DP方式。

环形dp

其实环形动态规划也是区间型,只不过区间首尾相接
此时使用记忆化搜索实现,其实是不容易的
典型例题是能量项链

树形dp

树型动态规划就是在“树”的数据结构上的动态规划

数位dp

数位dp是一种计数用的dp,一般就是要统计一个区间[le,ri]内满足一些条件数的个数。所谓数位dp,字面意思就是在数位上进行dp咯。数位还算是比较好听的名字,数位的含义:一个数有个位、十位、百位、千位…数的每一位就是数位啦!

倍增dp

对于只考虑首位状态的DP,考虑用倍增优化

插头dp

基于联通性的状态压缩动态规划是一类很典型的状态压缩动态规划问题,因为其压缩的本质并不像是普通的状态压缩动态规划那样用0或者1来表示未使用、使用两种状态,而是使用数字来表示类似插头的状态,因此,它又被称作插头DP。

插头DP本质上是一类状态压缩DP,因此,依然避免不了其指数级别的算法复杂度,即便如此,它依然要比普通的搜索算法快很多。

斜率优化与四边形不等式优化

我们知道,有些DP方程可以转化成DP[i]=f[j]+x[i]的形式,其中f[j]中保存了只与j相关的量。这样的DP方程我们可以用单调队列进行优化,从而使得O(n^2)的复杂度降到O(n)。

四边形不等式是一种比较常见的优化动态规划的方法

环+外向树上的dp

想一想也知道,只要有一个人讨厌另外一个人,这两个人最后是不会在一起的。
n个人n条边(图不保证联通),这就是一个环加外向树森林
不能同时取一条边上的两个人,用DP来实现

9、计算几何

计算几何基础

三位计算几何初步

数学上,立体几何(Solid geometry)是3维欧氏空间的几何的传统名称—- 因为实际上这大致上就是我们生活的空间。一般作为平面几何的后续课程。立体测绘(Stereometry)处理不同形体的体积的测量问题:圆柱,圆锥, 锥台, 球,棱柱, 楔, 瓶盖等等。 毕达哥拉斯学派就处理过球和正多面体,但是棱锥,棱柱,圆锥和圆柱在柏拉图学派着手处理之前人们所知甚少。尤得塞斯(Eudoxus)建立了它们的测量法,证明锥是等底等高的柱体积的三分之一,可能也是第一个证明球体积和其半径的立方成正比的。

梯形剖分与三角形剖分

传说把一个多边形按照顺时针(或者逆时针)旋转,相邻两个点分别作x轴的垂线(并且这两个点相连),就构成了梯形,然后定义从点在x轴方向上左到右为正(或者为负),得到n个梯形,把面积加起来就构成了多边形面积,这种剖分就是梯形剖分。

三角剖分是代数拓扑学里最基本的研究方法。 以曲面为例, 我们把曲面剖开成一块块碎片,要求满足下面条件: (1)每块碎片都是曲边三角形; (2)曲面上任何两个这样的曲边三角形,要么不相交,要么恰好相交于一条公共边(不能同时交两条或两条以上的边)。 [1]

凸包

凸包(Convex Hull)是一个计算几何(图形学)中的概念。
在一个实数向量空间V中,对于给定集合X,所有包含X的凸集的交集S被称为X的凸包。X的凸包可以用X内所有点(X1,…Xn)的凸组合来构造.
在二维欧几里得空间中,凸包可想象为一条刚好包著所有点的橡皮圈。
用不严谨的话来讲,给定二维平面上的点集,凸包就是将最外层的点连接起来构成的凸多边形,它能包含点集中所有的点。

旋转卡壳

”旋转卡壳“是很形象的说法,因为根据我们枚举的边,可以从每个维护的点画出一条或平行或垂直的直线,为了确保对于当前枚举的边的最优性,我们的任务就是使这些直线能将凸包正好卡住。

半平面交

半平面:平面上的直线及其一侧的部分。

pick定理

皮克定理是指一个计算点阵中顶点在格点上的多边形面积公式,该公式可以表示为S=a+b÷2-1,其中a表示多边形内部的点数,b表示多边形落在格点边界上的点数,S表示多边形的面积。

扫描线

扫描线一般运用在图形上面,它和它的字面意思十分相似,就是一条线在整个图上扫来扫去,它一般被用来解决图形面积,周长等问题。

10、搜索相关

dfs、bfs

深度优先搜索是一种在开发爬虫早期使用较多的方法。它的目的是要达到被搜索结构的叶结点(即那些不包含任何超链的HTML文件) 。在一个HTML文件中,当一个超链被选择后,被链接的HTML文件将执行深度优先搜索,即在搜索其余的超链结果之前必须先完整地搜索单独的一条链。深度优先搜索沿着HTML文件上的超链走到不能再深入为止,然后返回到某一个HTML文件,再继续选择该HTML文件中的其他超链。当不再有其他超链可选择时,说明搜索已经结束。 [1]

宽度优先搜索算法(又称广度优先搜索)是最简便的图的搜索算法之一,这一算法也是很多重要的图的算法的原型。Dijkstra单源最短路径算法和Prim最小生成树算法都采用了和宽度优先搜索类似的思想。其别名又叫BFS,属于一种盲目搜寻法,目的是系统地展开并检查图中的所有节点,以找寻结果。换句话说,它并不考虑结果的可能位置,彻底地搜索整张图,直到找到结果为止。

A*算法

A算法,A(A-Star)算法是一种静态路网中求解最短路径最有效的直接搜索方法,也是解决许多搜索问题的有效算法。算法中的距离估算值与实际值越接近,最终搜索速度越快。

迭代加深搜索(IDA*)、双向广搜

IDA算法不是基于迭代加深的A算法。
迭代加深只有在状态呈指数级增长时才有较好的效果,而A就是为了防止状态呈指数级增长的。
IDA
算法其实是同时运用迭代加深与全局最优性剪枝。
IDA算法发明出来后,可以应用在生活的各个方面,小到你看电脑的屏幕节能,大到LED灯都采用了此算法,加进了LED灯的研发,举个例子,计算机的节能,使用了IDA算法根据光亮调整亮度,可以减少蓝光辐射以保护长时间盯着电脑的人们,保护了诸如程序员,OIer等等。

所谓双向搜索指的是搜索沿两个方向同时进行:正向搜索:从初始结点向目标结点方向搜索;逆向搜索:从目标结点向初始结点方向搜索;当两个方向的搜索生成同一子结点时终止此搜索过程。

11、特殊算法

莫队算法、树上莫队

莫队算法的思路是,离线情况下对所有的询问进行一个美妙的SORT (),然后两个指针l,r(本题是两个,其他的题可能会更多)不断以看似暴力的方式在区间内跳来跳去,最终输出答案。 掌握一个思想基础:两个询问之间的状态跳转。

树上莫队,顾名思义就是把莫队搬到树上。

模拟退火

模拟退火算法来源于固体退火原理,是一种基于概率的算法,将固体加温至充分高,再让其徐徐冷却,加温时,固体内部粒子随温升变为无序状,内能增大,而徐徐冷却时粒子渐趋有序,在每个温度都达到平衡态,最后在常温时达到基态,内能减为最小。

爬山算法

爬山算法是一种局部择优的方法,采用启发式方法,是对深度优先搜索的一种改进,它利用反馈信息帮助生成解的决策。 属于人工智能算法的一种。

随机增量算法

随机增量算法是计算几何的一个重要算法,它对理论知识要求不高,算法时间复杂度低,应用范围广大。 增量法 (Incremental Algorithm) 的思想与第一数学归纳法类似,它的本质是将一个问题化为规模刚好小一层的子问题。 解决子问题后加入当前的对象。

12、其他重要工具与方法

模拟与贪心

模拟的缺点是运算量大,效率低下。往往需要剪枝才能AC。

贪心算法(又称贪婪算法)是指,在对问题求解时,总是做出在当前看来是最好的选择。也就是说,不从整体最优上加以考虑,算法得到的是在某种意义上的局部最优解 [1] 。
贪心算法不是对所有问题都能得到整体最优解,关键是贪心策略的选择 [1] 。

二分法、三分法(求偏导)

二分查找也称折半查找(Binary Search),它是一种效率较高的查找方法。但是,折半查找要求线性表必须采用顺序存储结构,而且表中元素按关键字有序排列。 [1]

三分法是二分法的变种,他最基本的用途是求单峰函数的极值点。

分治、CDQ分治

分治,字面上的解释是“分而治之”,就是把一个复杂的问题分成两个或更多的相同或相似的子问题,再把子问题分成更小的子问题……直到最后子问题可以简单的直接求解,原问题的解即子问题的解的合并。在计算机科学中,分治法就是运用分治思想的一种很重要的算法。分治法是很多高效算法的基础,如排序算法(快速排序,归并排序),傅立叶变换(快速傅立叶变换)等等。

CDQ分治主要思想还是分治的思想,即递归处理小范围信息,之后将处理的信息合并上传。 一般来说,都是先处理左区间,之后用左区间更新右区间,顺便更新答案,然后处理右区间,之后再将两个区间的信息合并。

高精度

高精度算法(High Accuracy Algorithm)是处理大数字的数学计算方法。在一般的科学计算中,会经常算到小数点后几百位或者更多,当然也可能是几千亿几百亿的大数字。一般这类数字我们统称为高精度数,高精度算法是用计算机对于超大数据的一种模拟加,减,乘,除,乘方,阶乘,开方等运算。对于非常庞大的数字无法在计算机中正常存储,于是,将这个数字拆开,拆成一位一位的,或者是四位四位的存储到一个数组中, 用一个数组去表示一个数字,这样这个数字就被称为是高精度数。高精度算法就是能处理高精度数各种运算的算法,但又因其特殊性,故从普通数的算法中分离,自成一家。

离线

离线算法( off line algorithms),是指基于在执行算法前输入数据已知的基本假设,也就是说,对于一个离线算法,在开始时就需要知道问题的所有输入数据,而且在解决一个问题后就要立即输出结果。

ST表

ST表 (Sparse Table, 稀疏表 )是一种简单的数据结构,主要用来解决 RMQ (Range Maximum/Minimum Query,区间最大/最小值查询 )问题。 它主要应用 倍增 的思想,可以实现 预处理、 查询。

13、STL

map

作为关联式容器的一种,map 容器存储的都是 pair 对象,也就是用 pair 类模板创建的键值对。其中,各个键值对的键和值可以是任意数据类型,包括 C++ 基本数据类型(int、double 等)、使用结构体或类自定义的类型。

priority_queue

不出所料,priority_queue 容器适配器定义了一个元素有序排列的队列。默认队列头部的元素优先级最高。因为它是一个队列,所以只能访问第一个元素,这也意味着优先级最高的元素总是第一个被处理。但是如何定义“优先级”完全取决于我们自己。如果一个优先级队列记录的是医院里等待接受急救的病人,那么病人病情的严重性就是优先级。如果队列元素是银行的借贷业务,那么借记可能会优先于信贷。

set

C++ STL 之所以得到广泛的赞誉,也被很多人使用,不只是提供了像vector, string, list等方便的容器,更重要的是STL封装了许多复杂的数据结构算法和大量常用数据结构操作。vector封装数组,list封装了链表,map和set封装了二叉树等,在封装这些数据结构的时候,STL按照程序员的使用习惯,以成员函数方式提供的常用操作,如:插入、排序、删除、查找等。让用户在STL使用过程中,并不会感到陌生。

关于set,必须说明的是set关联式容器。set作为一个容器也是用来存储同一数据类型的数据类型,并且能从一个数据集合中取出数据,在set中每个元素的值都唯一,而且系统能根据元素的值自动进行排序。应该注意的是set中数元素的值不能直接被改变。C++ STL中标准关联容器set, multiset, map, multimap内部采用的就是一种非常高效的平衡检索二叉树:红黑树,也成为RB树(Red-Black Tree)。RB树的统计性能要好于一般平衡二叉树,所以被STL选择作为了关联容器的内部结构。

bitset

bitset 模板类由若干个位(bit)组成,它提供一些成员函数,使程序员不必通过位运算就能很方便地访问、修改其中的任意一位。

rope

rope 不属于标准 STL,属于扩展 STL,来自 pb_ds 库 (Policy-Based Data Structures)。

14、非常见算法

朱刘算法

朱刘算法是一个 O (nm) 的算法。 当然,还有Tarjan巨神的 O (n log n) 的算法。

弦图与区间图

定义弦为一个环中连接不相邻两个点的边。
弦图为一个图,其中任意一个长度大于3的环都包含至少一条弦。
换句话说:弦图最大的没有弦的环大小小于3

区间图着色问题

本篇文章已经接近尾声了,最后来纪念一下C语言、UNIX之父——丹尼斯·麦卡利斯泰尔·里奇(Dennis MacAlistair Ritchie)
丹尼斯·里奇(1941年9月9日-2011年10月12日),C语言之父,UNIX之父。曾担任朗讯科技公司贝尔实验室下属的计算机科学研究中心系统软件研究部的主任一职。1978年与布莱恩·科尔尼干(Brian W. Kernighan)一起出版了名著《C程序设计语言(The C Programming Language)》。此书已翻译成多种语言,被誉为c语言的圣经。2011年10月12日(北京时间为10月13日),丹尼斯·里奇去世,享年70岁。

普通年轻人可能都要摇头。丹尼斯·里奇是谁?
丹尼斯·里奇不像某位来自硅谷,精致的和少年得志的亿万富翁,穿着简约黑色的高领毛衣在站满粉丝的屋子里,演示新酷产品和恶意攻击对手。
不,丹尼斯·里奇是一位胡子有些凌乱的计算机科学家,他穿着羊毛衫坐在一间凌乱的办公室里。
精心整理2万字c++知识点_第1张图片
和乔布斯在大学辍学不同,他毕业于哈佛大学,有物理学和应用数学的博士学位。他工作于新泽西的 AT&T 贝尔实验室,而不是闪闪发光的硅谷。

虽然存在宗教和意识形态的差异。但我们亏欠丹尼斯·里奇很多,超出我们的想象。没有他的贡献,现在我们没法用个人计算机,成熟的软件应用甚至是互联网。
没有 Android 智能手机,没有昂贵的 DVR 和流媒设备,没有乔布斯和苹果创造令人惊叹的 Mac 和 iPad。
没有微软的 Windows 10 和 Surface Book。
没有云计算、没有 AWS(亚马逊网络服务,Amazon Web Services),没有 Azure(微软云)。
没有“为 XX 而生的应用程序”,也没有互联网这个东西。
向丹尼斯·里奇致敬 —— 感谢他带给我们这些技术,让我们可以成为今天的专家。
精心整理2万字c++知识点_第2张图片

你可能感兴趣的:(c++,c++)