03 2024 档案
杂项
摘要:快读 template<typename T>void in(T &a) { T ans=0; bool f=0; char c=getchar(); for(;c<'0'||c>'9';c=getchar())if(c=='-')f=1; for(;c>='0'&&c<='9';c=getchar
一些求函数最值的算法
摘要:三分法 流程 三分法可以求区间上一个单峰函数的最值。顾名思义,三分法与二分法相似,但是会把区间分三段。 板子 P3382 在区间 中任取两点 (设 ),分类讨论。 当 ,说明 \(
贪心 学习笔记
摘要:概述 贪心算法指每一步都选当前的最优解,不考虑这一步对后面的影响。使用时需要先证明贪心策略的正确性。一般使用反证法或数学归纳法证明。 例题 P1080 这一题要求的是一个最优的排列,考虑反证。假设当前的排列最优,尝试交换相邻两个大臣生成一个新的排列。 设前面所有人左手的乘积为 。交换前两个
搜索算法 学习笔记
摘要:概述 做搜索题时,直接朴素 DFS 或 BFS 可能会寄,这时需要对搜索方法进行改进。 下面以 P1379 八数码问题为例。 双向广搜 如果直接广搜,搜索树会比较庞大。这题中由于终点已知,可以从起点和终点同时广搜,可以将复杂度的指数减半。 具体来说,维护两个队列,从起点和终点交替扩展队列,搜索的两端
双指针 学习笔记
摘要:概述 双指针是一种简单的技巧,通过两个指针维护一些具有单调性、可快速增删的区间信息。 一般要求的是求满足某个条件的最长/最短区间。当一个指针增加时,单调性要求满足这个条件的分界点是单调递增的。枚举一个指针,让另一个指针不断增加直到满足条件即可。两个指针都只会遍历一遍,复杂度 。 例题
寒假集训 思维题
摘要:HDU 7220 一个 串,可以翻转长为奇数的区间,求可能得到的最小字典序。 翻转只会在奇偶性相同的位置造成变化,只用长度为 的翻转,可以任意调换奇偶性相同的位置,那么将奇数位与偶数位分别排序即可。 一道数论题: 求 \(\sum_{i=1}^n\sum_{j=1}^m\m
差分与前缀和 学习笔记
摘要:前缀和 一维前缀和 前缀和指数列前 项和,比如数组 的前缀和为 。可以通过递推计算前缀和: for(int i=1;i<=n;i++)sum[i]=sum[i-1]+a[i]; 前缀和可以做到 查询静态区间和
Dancing Links X 学习笔记
摘要:X 算法 用于解决精确覆盖问题,即给定一个零一矩阵,选出若干行让每一行恰有一个一。 \[\begin{bmatrix}0&0&1&0&1&1&0\1&0&0&1&0&0&1\0&1&1&0&0&1&0\1&0&0&1&0&0&0\0&1&0&0&0&0&1\0&0&0&1&1&0&1\en
最小生成树 学习笔记
摘要:最小生成树 定义 生成树:一个连通无向图的生成子图,同时要求是树。 最小生成树:边权和最小的生成树。 Kruskal 算法 Kruskal 算法是一种基于贪心的最小生成树算法,好写易懂且复杂度低。 流程很简单,首先对边排序,每次选最小的边,如果没有形成环就加入生成树。 可以这样理解,如果一条边加入生
字符串
摘要:KMP void getnxt(int m,char t[],int nxt[]){ nxt[1]=0; for(int i=2,j=0;i<=m;i++){ while(j&&t[j+1]!=t[i])j=nxt[j]; if(t[j+1]==t[i])j++; nxt[i]=j; } } int
子序列自动机 学习笔记
摘要:定义 子序列自动机是接受且只接受一个串的子序列的自动机。 子序列自动机有 个状态,也就是主串的下标加上 ,起始状态为 。令自动机的转移函数为 ,则 为 之后第一个字符 的位置(第一个是因为这
扩展KMP 学习笔记
摘要:定义 扩展 KMP(Z 函数)可以求主串的所有后缀与模式串的最长公共前缀。 约定字符串下标以 为起点。定义字符串 的 Z 数组 ,即串与每个后缀的 ;主串 与模式串
后缀数组 学习笔记
摘要:定义 定义字符串从第 个字符开始的后缀为 。 后缀数组一种是处理字符串的有力工具。将字符串的所有后缀按字典序排序,则 表示排名为 的后缀的起始位置, 为第 个后缀的排名。 倍增算法 直接排序,由于要进行字符串的比
Manacher算法 学习笔记
摘要:概述 Manacher 算法可以在 的复杂度中求出一个字符串的最长回文子串。 过程 回文串有奇数长度和偶数长度两种,这就比较麻烦。如果把每两个字符之间加一个特殊字符,就只有奇数长度的回文子串了。这里为了方便处理边界还在首尾各加了一个特殊字符。 cin>>temp+1,n=strle
AC自动机 学习笔记
摘要:自动机 OI 中所说的“自动机”一般都指“确定有限状态自动机”。 自动机可以看作一张图,有五个组成部分:字符集 、状态集合 、起始状态 、接受状态集合 、转移函数 。 字符集可以输入一个串,这个串的字符属于字符集。状态从起始状态转移。
最短路 学习笔记
摘要:BFS 过程 如果图的边权只有一种,那么在 BFS 的过程中松弛即可。 否则如果有两种边权,一种为 ,使用 0-1 BFS。使用双端队列,对于大的边权入队尾, 边权入队首即可。 与 Dijkstra 和 SPFA 的关系 这两种算法与 BFS 的过程很像。 将 BFS 的队列换成
拓扑排序 学习笔记
摘要:拓扑排序是一个 DAG 的所有顶点的线性序列,满足每个顶点出现且只出现一次和如果有一条 A 到 B 的路径,在序列中 A 出现在 B 的前面。 可以用一个类似 BFS 的方式(又叫 Kahn 算法)解决: 首先统计入度,如果一个点没有入边就加入队列,代表当前可以输出。 每次取出队首,删除这个点,把这
图论
摘要:链式前向星 struct edge{ int v,w,nxt; }e[m+5]; int head[n+5],cnt=1; void add(int u,int v,int w){ cnt++,e[cnt].v=v,e[cnt].w=w,e[cnt].nxt=head[u],head[u]=cnt;
图的特殊点集和边集 学习笔记
摘要:支配集 一张无向图,如果一个点集使所有点要么在点集中,要么与点集中的一个点相邻,则称这个点集是图的一个支配集。最小支配集大小记作 。求一般图的最小支配集是 NP-hard 的。 考虑如何求树的最小支配集,有贪心和 DP 两种方式。 贪心时,按 DFS 序倒序处理,能保证当前
欧拉图 学习笔记
摘要:定义 欧拉回路:通过图中每条边恰好一次的回路。 欧拉通路:通过图中每条边恰好一次的通路。 欧拉图:具有欧拉回路的图。 半欧拉图:具有欧拉通路但不具有欧拉回路的图。 欧拉图的判定 经过一个点,除了起点和终点必然有进有出。因此可以得到欧拉图的判定: 无向图是欧拉图或半欧拉图需要去掉孤立点后联通。欧拉图没
连通性问题 学习笔记
摘要:强连通分量 定义 若一张有向图的节点两两互相可达,则称这张图是强连通的。 一张有向图的强连通分量是极大的强连通子图。 Tarjan算法 前置知识:dfs树 DFS 树就是对图进行 DFS 形成的图的生成树。通过 DFS 树可以把边分为四类: 1.树边:DFS 树上的边。 2.返祖边:不在 DFS 树
二分图最大匹配 学习笔记
摘要:基本概念 二分图是一种特殊的无向图。图的节点可以被分成两个部分,满足没有边连接相同的部分,记两个部分为左部点和右部点。 一张图的匹配,就是选出一些边没有公共顶点,最大匹配就是选出的边数最多。 增广路算法 增广路: 交错路始于非匹配点且由匹配边与非匹配边交错而成。 增广路是始于非匹配点且终于非匹配点的
中国剩余定理 学习笔记
摘要:中国剩余定理 中国剩余定理(Chinese remainder theorem, CRT)可以求解如下形式的同余方程组: \[\left\{\begin{matrix}x\equiv b_1\pmod{a_1} \x\equiv b_2\pmod{a_2} \\vdots\x\equiv b_
线性基 学习笔记
摘要:定义 线性空间:由向量集合 、基域 ,组成,其中定义向量加法,标量加法,数乘(标量乘向量)。其中向量加法满足封闭性、结合律、单位元、逆元、交换律,标量加法满足封闭性,数乘满足封闭性、对向量加法与标量加法的分配律、结合律、单位元。比如普通的向量和实数就构成线性空间
线性代数相关
摘要:定义 矩阵(Matrix)是一个按照长方阵列排列的复数或实数集合。 同型矩阵:行数和列数相同的两个矩阵。 方阵:行数等于列数的矩阵。 主对角线:方阵中行数等于列数的元素构成的对角线。 对角矩阵:主对角线之外的元素均为 的方阵,记作 \(\operatorname{diag}\{\lamb
数学
摘要:线性基 template<typename T,int maxn>struct basis{ T a[maxn]; basis(){ memset(a,0,sizeof(a)); } bool insert(T k){ for(int i=maxn-1;i>=0;i--){ if(k>>i&1){
筛法 学习笔记
摘要:埃拉托斯特尼筛法 一个质数数的倍数一定为合数,因此可以在枚举到一个质数时对其倍数打标记。如果从小到大枚举到一个数未被标记,说明这个数为质数,因为没有更小的质因数了。 int prime_init(int n,int prime[],bool a[],int cnt=0){ for(int i=2;i
欧拉函数 学习笔记
摘要:定义 表示小于 的数中与 互质的个数,是一个重要的数论函数。 性质 若 为质数,则 。 显然小于 的都与 互质。 若 为质数,则 \(\varphi(n^k)=n
莫比乌斯反演 学习笔记
摘要:基本定义 数论函数:定义域为正整数的函数。 积性函数:满足 的函数 。 完全积性函数:满足 \(\forall n,m\in \mathbb{N}^+,f(x)f(y)=f
高中数学必修一摘要
摘要:1 集合与常用逻辑用语 集合的定义:把研究对象统称为元素,把一些元素组成的总体叫做集合。元素可以是任何东西,比如数字、字符、线段甚至集合本身等。集合就是一堆元素。 集合具有确定性、互异性、无序性。集合中的元素必须确定,元素互不相同,并且没有顺序之分。 若构成两个集合的元素一样,则这两个集合相等。 若
乘法逆元 学习笔记
摘要:定义 如果 ,则称 为 模 的乘法逆元。 乘法逆元可以处理模意义的除法,可以理解成模意义下的倒数。比如在乘法中 ,也就是说倒数抵消了乘法,因此有 \(\frac{x}{a}
博弈论 学习笔记
摘要:定义 博弈论主要研究的是:在一个游戏中,进行游戏的多位玩家的策略。 OI 中出现比较多的是公平组合游戏,满足几点性质: 游戏有两个人参与,二者轮流做出决策,双方均知道游戏的完整信息; 任意一个游戏者在某一确定状态可以作出的决策集合只与当前的状态有关,而与游戏者无关; 游戏中的同一个状态不可能多次抵达
Miller-Rabin 素性测试和 Pollard-Rho 算法 学习笔记
摘要:Miller-Rabin 素性测试 用于判断一个数是否是质数。 首先有费马小定理:若 且 是质数,有 。 假如费马小定理的逆命题成立,只需要随机 使得 ,判断是
线段树 学习笔记
摘要:概述 线段树(Segment Tree)是一种常用的维护区间信息的数据结构。线段树的结构是如下的分治结构: 线段树是完全二叉树,每一个节点表示一个区间,将每个长度不为 的区间均分成左右两个区间。对于节点 ,左右儿子的编号分别为 。 下面以 P3372 为例
字典树 学习笔记
摘要:普通字典树 概述 字典树(Trie)是一种数据结构,一般用于处理字符串问题与异或问题。 字典树的结构是这样的: 其中每一个字符就是字典树的边,比如 aba 就是 ,ac 是 。而其中的节点代表的是字符串的前缀。 字典树的主体可以用一个数组
数据结构
摘要:分块 template<typename T,int maxn>struct block_array{ int bn,bp[maxn],bl[maxn],br[maxn],len[maxn]; T v[maxn],tag[maxn]; void build(int n,T a[]){ bn=sqrt
莫队算法 学习笔记
摘要:概述 莫队算法是一种离线算法,普通莫队可以 解决一些区间查询问题。这个问题需要满足区间 的答案能快速求出区间 的答案。经过一些扩展可以完成修改、上树等操作。 普通莫队 例题
树状数组 学习笔记
摘要:定义 树状数组(Binary Indexed Tree,BIT)是一种数据结构,可以高效地维护一些单点修改的问题。搬一张 OI-wiki 的图: 设原数组为 ,树状数组为 ,有: \[\begin{aligned}&c_1=a_1\&c_2=a_1+a_2\&c_3=a_3\
扫描线算法 学习笔记
摘要:概述 一种算法,常用于计算几何。大致思路是在其中一维维护一根扫描线,用一个数据结构维护被这条线所截的另一维信息。 例题 P5490 面积并是扫描线的一个比较典的应用。 假设有一根横向的扫描线从下往上扫,遇到一个矩形的上下边会停止,这根线会把矩形的并分成若干矩形,高为相邻两条边的高度差,宽为矩形的并覆
平衡树 学习笔记
摘要:定义 二叉查找树是一种树形数据结构,支持动态插入删除,查询排名和第 k 小,查询前驱后继等。二叉查找树的点权满足左儿子小于当前节点小于右儿子。上面的这些操作都可以在树上二分解决。 但是当树的深度很大,接近一条链时,操作复杂度会退化至 ,于是有了各种方法使树的深度保持期望 \(O(\l
珂朵莉树 学习笔记
摘要:珂朵莉树可以做维护带有区间赋值的数据结构题。事实上,珂朵莉树不是树,甚至不是数据结构,本质是基于数据随机的颜色段均摊。 建树 珂朵莉树将数值相同的区间看做整体,用 set 维护。 节点的保存方式: template<typename T>struct node{ int l,r; mutable T
划分树 学习笔记
摘要:建树 划分树(Dividing Tree)是一种可以解决静态区间 kth 的数据结构,与主席树相比更好理解,常数也更小。缺点是适用范围小,基本专门用来求解这个问题。下面以第 k 小为例。 划分树的结构如下: 方便起见,将原数组的长度补成 的整数幂。划分树的每个节点都是一个数组,根节点为原
寒假集训 数据结构
摘要:权值线段树 一个神奇的科技:通过简单重新编号可以使线段树只开两倍空间。对于一个区间 ,将节点编号设为 。这样这个节点的标号范围为 ,实际 ,左右儿子的标号范围为 \([2l
寒假集训 根号算法
摘要:根号分类讨论 HDU7226 给出一个排列 ,一个完全图 的边权为 ,求最小生成树。 构造一条链,连接 ,这样连的边小于 。那么跑 Kruskal 求出来的最小生成树的边也小于 。那么 \(
分块 学习笔记
摘要:分块是一种思想,指的是把数据划分为若干块,然后将块作为整体处理。此指数据结构中的块状数组。下文以维护区间加,区间查询为例。 初始化 一般来说,如果给出的数组长度为 ,块数会取 使块长与块数均衡。然后预处理块端点,每一个下标属于的块,块长与要维护的信息。末尾剩下的合
二叉堆 学习笔记
摘要:概述 堆是一种数据结构。堆的形态是一棵树,满足每个节点的权值都大于等于或小于等于其父亲的权值,分别称为小根堆、大根堆。一般支持插入、删除最值、查询最值等操作。 下文以小根堆为例。 二叉堆 二叉堆是完全二叉树,同时满足堆的性质,不可并(复杂度过高)。 查询最值 返回堆顶即可。 T top(){ ret
堆 学习笔记
摘要:概述 堆是一种数据结构。一般支持插入、删除最值、查询最值等操作,有小根堆和大根堆,分别维护最小值、最大值。 下文以小根堆为例。 二叉堆 定义 二叉堆是完全二叉树,同时满足堆的性质,不可并(复杂度过高)。 查询最值 返回堆顶即可。 T top(){ return h[1]; } 上浮、下沉 对于单独的
单调栈与单调队列 学习笔记
摘要:单调栈 概述 单调栈是一种特殊的,满足单调性的栈。单调栈插入元素时,不断弹出不满足单调性的元素。比如当前栈为 ,插入 时要弹出 。 单调栈维护的是当前的后缀最大值,因此当新元素入栈时间更晚,值更大,就要出栈。 单调递减栈代码: for(int i=1;i<
并查集 学习笔记
摘要:概述 并查集是一种维护集合的数据结构,可以看作一个森林,其中每个森林都代表一个集合。 操作 初始化 初始时每个元素单独一个集合。对于树的根节点,其父亲可以设为结点本身或 号结点。 我倾向于设为 号结点,这样可以省下这一步。 查询 查询一个结点的祖先时只需要不断向上跳即可。 i
van Emde Boas 树 学习笔记
摘要:概述 一种数据结构科技,可在 的复杂度内支持插入、删除、查询前驱后继、查询元素是否存在、查询最值(相当于阉割了有关排名操作的平衡树),其中 是值域。 定义 首先把值域补到 的整数幂,设 。 维护一个桶表示元素是否存在。运用
ST表 学习笔记
摘要:ST 表(Sparse Table,稀疏表)是用于解决可重复贡献问题的数据结构。典型的应用是可以 解决 RMQ 问题(区间的最值查询,Range Maximum/Minimum Query)。 ST 表运用了倍增的思想。以静态区间最大值为例,设 \(f_{i,j
树论
摘要:树上 k 级祖先 int lg[n+5],dep[n+5],maxd[n+5],f[n+5][log2(n)+5],son[n+5],top[n+5]; vector<int>up[n+5],down[n+5]; void dfs1(int pos,vector<int>e[]){ maxd[pos
树链剖分 学习笔记
摘要:重链剖分 定义 在维护树上路径信息时,如果带修,树上倍增和树上差分无法维护。如果能把每条路径拆成若干条链,并且重新标号使链的编号连续,就可以用数据结构维护。 定义一个节点子树最大的子节点为重儿子,其余为轻儿子。节点连向重儿子的边为重边,否则为轻边。若干条重边相连为重链,单独一个节点也算重链。这样可以
树分治 学习笔记
摘要:定义 树分治通过分治降低遍历树上路径的复杂度。适用于一些需要遍历树上所有路径的问题。 点分治 过程 钦定某个点为根,对于经过这个点的路径需要有一个快速处理的方式。不经过这个点的路径一定在某一棵子树上,可以删去这个点,对子树递归处理子问题。 为了使子问题的规模尽量小,钦定的这个点应当选择重心,因为重心
笛卡尔树 学习笔记
摘要:概述 笛卡尔树是一种特殊的二叉树,每个节点有两个值 , 满足二叉查找树的性质, 满足堆的性质。即 , 根据堆的种类有 \(x_{lson(u)}<x_u\wedge x_{rson(u)}<x_
状压DP 学习笔记
摘要:概述 在某些题目中,状态里需要添加很多 bool 类型的状态,比如表示一些元素是否在集合中。当这种状态过多,可以将其压缩为一个二进制数。 比如 表示 为真, 为假。 例题 P2915 状压 DP 题一个主要特征是数据范围很小,如本题中 \(
悬线法 学习笔记
摘要:概述 一种简单的 DP 技巧,可以在某些单调栈题中使用,相对单调栈更好理解。 例题 P4147 最大子矩形问题。 首先算出 ,分别表示一个点向左、右、上可以走多少格,容易递推。 for(int i=1;i<=n;i++){ for(int j=1
数位DP 学习笔记
摘要:概述 数位DP解决的是有关数字每一位的问题。一般形式为统计一个区间内满足一些限制的数的数量。 例题 HDU3555 首先把数字拆位: for(maxn=0;temp1;)n[++maxn]=temp1%10,temp1/=10; 数位DP可以采用记搜的方式转移。反向统计不含 的个数,设
树形DP 学习笔记
摘要:树形DP 树形DP,就是在树上DP,一般会在DFS中进行。 例题:P1352 一般遇到考树的题目,先想链上的做法,然后推广到树。链上的问题是这样的: 个职员,选择若干个参加宴会,相邻的不能同时参加,问快乐指数之和的最大值。 设 ,其中 是布尔值,表示前
决策单调性优化DP 学习笔记
摘要:概述 决策单调性是 DP 的一种性质。 用 D / D 描述一个 DP 方程,其中 表示状态数为 , 表示一个状态的转移需要用到 个之前的状态。 决策单调性一般体现在 1D / 1D 或 2D / 1D 的 DP 中
背包问题 学习笔记
摘要:概述 背包问题是最基本的动态规划模型,大概为: 有 件物品,拿一件物品有 的价值和 的花费,有一定限制,最多花费 的代价,问价值最多为多少。 简单背包问题 有 件物品,拿一件物品有 的价值,问能否从中选取若干件总价值