算法
yzyyylx
这个作者很懒,什么都没留下…
展开
-
How far away ? HDU - 2586
题面题意 给出一棵树,并询问任意两点间的距离.方法 首先找到最小公共祖先,然后两端距离之和即为答案 第一步求出欧拉序(dfs搜索顺序),然后两点的公共祖先就是两点在欧拉序中之间深度最小的点,也就是区间最小值. 因此,首先求出欧拉序,然后求出各个点的深度以及它们到根节点的距离,并在欧拉序中用st表维护区间最小深度,两点间距离即为它们到根节点距离之和减去2*公共祖先到根节点的距离.原创 2017-10-28 08:12:56 · 199 阅读 · 0 评论 -
Histogram LightOJ - 1083(RMQ)
题面题意 有一串由矩形组成的图,先要求出这幅图中所能容纳的最大矩形的面积总体思路 求出以各个小矩形高度为宽所能达到的最大面积,此时我们称这个最大矩形被这个小矩形统治,我们只需求出每一个小矩形统治的最大矩形的左端点和右端点.法1(单调栈)方法解释 让矩形依次入栈,当入栈矩形小于栈顶时,说明此时的栈顶不能统治该矩形,其右端点即为入栈矩形的位置-1.最后将让元素全部出栈,它们的右端点均为这原创 2017-10-21 13:20:46 · 286 阅读 · 0 评论 -
LCT
作用一种动态树,用于维护森林,支持加边,删边,换根等操作,每次操作的复杂度均为log.做法将每棵树分成多条实链,实链之间用虚边连接,要求每一条实链不存在深度相同的点,之后每一条实链再用splay维护,并且维护时保证每个splay维护的子树的中序遍历深度递增,这样就可以动态地修改虚边和实边了.核心操作:access将某个点到根的路径变为实边,可以发现到根的路径将会经过多个splay,每次要将两个spl原创 2018-04-10 16:15:43 · 504 阅读 · 1 评论 -
线性基
作用用于处理多个数中选取一些数的Xor最大值,最小值,并且能否得到某个值.可以在log的时间解决实现方法是一个大小为log的,对于每一位记录一个最高位为它的某个数的数组,要求这个数组可以表示所有这些数的子集的Xor值,初始全部为零插入及查询插入数u时,从高位到低位遍历,如果u的这一位有值,则进行判断,若数组的这一位还没有数,则改为u并且break,否则u^数组中的这个数(详见代码),这样操作之后u只原创 2018-04-21 15:36:26 · 610 阅读 · 0 评论 -
匈牙利算法
匈牙利算法 用于二分图匹配,不可用于一般图,一般图要用带花树.来做. 一个一个点来操作,为它先找一个点(任意可以匹配的一点),若其他点已经使用过了,则递归判断是否可以让使用该点的点再找一个点,并用同样的方法判断能否找到 举例说明:A可以匹配a点,但此时B已经与a匹配,则判断B是否可以换一个点. 若B可以匹配b点,而C已经与b匹配,则判断C是否可以换一个点. 如此递归下去,原创 2018-01-17 07:45:55 · 278 阅读 · 0 评论 -
km算法求带权二分图的最大匹配
做法 可以与匈牙利算法类比. 首先每一个匹配点都有一个期望匹配值为与它相连的所有边的最大搭配值,所有被匹配点的期望匹配值均为0. 然后如果匹配点与被匹配点的期望值之和恰好为该匹配值,则可以匹配,用匈牙利算法来求,如果没有找到则让参与此次失败匹配的点中的匹配点加上k,被匹配点减去k,k为产生一个合法匹配还需要的最小值(在代码中用need表示),全部匹配完后输出答案即可代码#inclu原创 2018-03-05 21:01:56 · 275 阅读 · 0 评论 -
uoj #117. 欧拉回路 套圈法
题面题意给出一幅有向或无向图,判断是否存在一个环走遍所有边,若有则输出求其中的环.做法首先判断很容易,对于无向图只要联通且度数都是偶数即可,对于有向图,则要联通且入度等于出度,问题在于如何找到这个环. 我们可以发现,如果随便走的话,必然会回到出发点,但是不一定走过所有的边,而剩下的图恰是一条与我们之前走的路有交点的欧拉回路,没有走完的原因就是我们之前有些地方走错了,因此要退回到两条路的焦点,也就是原创 2018-04-19 19:27:42 · 8319 阅读 · 0 评论 -
AC自动机
作用用于处理多个字符串匹配,例如给出一些关键单词,再给出一篇文章(或多篇),问文章内的出现了几个单词或一共出现了几次.实现方法可以说是KMP与字典树的结合,就好像利用字典树存储多个字符串的next数组. 首先将所有关键单词建一棵字典树,每个节点除了存储26(字符种类数)个儿子外,还要储存sum和fail. sum用于记录此节点是否是某个关键词的尾字符,并且也可以顺便储存此字符串的个数 fail原创 2018-03-13 19:37:10 · 194 阅读 · 0 评论 -
后缀自动机
作用常用于处理字符串问题,可以高效解决许多字符串问题。实现方法有点像将一个字符串的所有后缀都建在一个AC自动机上,但不同的是后缀自动机的节点数最多为2*n,因为它只记录需要记录的点,一些没有记录东西的点可以视为与下面有价值的节点并在一起,这样大大降低了时间复杂度和空间复杂度。 对于每一个节点记录它的后面加上每个字符后后缀最长可以到达的节点,以及它的长度len,它去掉一个最短前缀后存在的节点pre。原创 2018-03-14 23:47:47 · 332 阅读 · 0 评论 -
无旋treap
作用一种平衡树,可以只利用合并与拆分两种操作实现插入删除等所有二叉查找树可以做的事情.实现方法treap=tree+heap,利用tree来保持二叉查找树的功能,再利用heap来保证它是平衡树. 每个节点保存两个值,一个是题目给出的,要储存的值,还有一个是rand的且长期不变,建树时储存的值根据二叉查找树的性质来保存,同时保证rand()的值符合堆的性质,每个根为该子树的极值,这样就可以保证树的平原创 2018-03-14 14:40:14 · 308 阅读 · 0 评论 -
虚树
作用针对有q次询问,每次询问树上的m个点的信息的题目,如世界树,可以每次将询问的这些点和这些点两两之间的lca(O(m)个点)单独拿出来建一棵虚树,然后在虚树上贪心或是dp来解决,其复杂度为询问总点数*log询问总点数+在虚树上操作的复杂度.建法首先将所有询问点按dfs序排序,用栈维护刚刚扫过的一条链,然后求出此时要加入的点与栈顶节点的lca,然后不断pop(并且在pop的同时加边)直到栈顶元素为l原创 2018-03-26 20:17:15 · 228 阅读 · 0 评论 -
Palindromic Tree 回文自动机-回文树
作用回文自动机,顾名思义,用于解决回文串的问题,可以用于处理回文串的数量,种类数等问题.构造方法与其他自动机差不多,一般记录son[字符个数] (在左右两边加入某字符后匹配的节点),len(长度),fail(失配后所到达的节点,也就是这个回文串的最长回文后缀). 一开始有两个节点,长度分别为0(偶数长度的回文字符串的起始点)和-1(奇数长度的回文字符串的起始点,定为-1可方便后面的计算) 新加入原创 2018-03-29 19:42:04 · 301 阅读 · 0 评论 -
可持久化并查集
介绍可以查询并查集的历史版本,即几次操作之前的连通状态,有在线与离线两种不同算法.离线算法相比于在线算法,时间复杂度与空间复杂度均要优越得多,若要查询第k次操作之后的状态,则可以视为k节点与此节点相连,否则视为上一节点与此节点相连,则这样将会形成一棵树,记录时用启发式合并,将较小树向较大树合并,而且不进行路径压缩,这样复杂度为O(n*logn),dfs一遍即可.代码(以洛谷 P3402 【模板】可持原创 2018-03-22 18:48:15 · 266 阅读 · 0 评论 -
主席树
作用 用于查询区间第k小值等,本质是线段树,因为是某个主席发明而得名,算法内容与主席无关.实现方法 线段树维护序列的值的个数,并对每一个前缀建一棵线段树(主席树不是这样的,否则空间…),那么要查区间[l,r]就只需要将r这棵树减去(l-1)这棵线段树,在相减后的线段树查找即可(实际不需要再建一棵树). 空间优化:根据上述方法,可以发现相邻两棵线段树的区别只有log,因而后面的线段树可原创 2018-01-24 18:06:01 · 203 阅读 · 0 评论 -
可修改主席树(树状数组套主席树)
作用 普通主席树可以查询区间k小值,但若直接修改,则复杂度极大,而可修改主席树通过树状数组的辅助来修改,大大缩小了时间复杂度,缺点是空间复杂度过大. 修改的时间复杂度为O((logn)^2),空间复杂度为O(n*logn^2).实现方法 为了减小修改复杂度,可以修改每个区间管理的范围. 传统主席树每个点对应的主席树管理一个前缀,而可修改主席树因为树状数组在处理动态区间和上有优势原创 2018-01-26 19:57:39 · 597 阅读 · 0 评论 -
乘法逆元
解释在两个数1/a,b modE的情况下,若两数同余.则b为a的逆元性质若a,b互为逆元,则k/a与k*b同余 并且当mod的数p为质数时,a与a^(p-2)互为逆元(费马定理),下为示例: 要求:(3/2)%5 2^(5-2)=8,8%5=3,故2和3互为逆元 (3/2)%5=(3*3)%5=4. 验证:4%5=4 -> (8/2)%5=4 ->(3/2)%5=...原创 2017-10-21 15:36:26 · 448 阅读 · 0 评论 -
单调栈
解释 单调栈就是一个栈中的所有元素都依次递增(或递减),若入栈元素不符合,则不断出栈(根据题目记录下需要信息),直到它符合条件,并根据题意记录需要信息,最后让元素全部出栈并记录信息. 可以先向栈加入一个为0或为无限大的元素(据增减性而定),使当栈为其他元素时,任意元素都可以进栈,而省去了对栈顶是否为空的判断. 最后让所有元素出栈时,也可采用相同方法,加入一个极端元素来实现.原创 2017-10-21 13:07:28 · 237 阅读 · 0 评论 -
插头dp
题面题意 给出m*n的矩形,问用1 *2的小矩形填满共有几种方法。方法 此题首先可以逐行递推,枚举两行可以转移的状态,详见状压dp解法,还可以用插头dp的方法,逐个格子递推,具体见图: 蓝色表示当前考虑的格子,红色表示此时记录的状态,本质上就是一个格子一个格子覆盖过去,若已经覆盖则直接转移到下一个状态,反之则覆盖上能盖的并更新状态。代码#include<iostream>原创 2017-11-08 22:21:26 · 286 阅读 · 2 评论 -
圆方树
解释对每一个点双新建一个方点,由这个方点向点双中的每一个点连一条新边,新边构成的新图即为圆方树,可以发现这张图必然是一棵树(如果原图不连通就是森林)。 可以发现,圆方树中任意两个圆点和任意两个方点之间都没有边。 圆方树可以用于处理图的问题,方点可以用于存储所有与它相连的圆点的信息(有时候存储部分,据题目而定)。代码void dfs(int now){ int p,q,t;...原创 2018-09-03 20:27:47 · 329 阅读 · 0 评论 -
稳定婚姻系统
解释可以通俗的理解为有n个男生,n个女生,每个人都每个异性都有一个好感度,要求两两配对结为夫妻,使不存在夫妻uv和ab,满足u对a的好感度大于u对v的好感度,a对u的好感度大于a对b的好感度。求这种稳定婚姻的方案。做法首先每个男生将他喜欢的所有女生按照他对她们的好感度由高到低排序,依次求婚,若此时的求婚对象还单身,则匹配,否则由女生根据她对他俩的好感度选择匹配一位男生,将那位落选男...原创 2018-08-05 21:44:38 · 891 阅读 · 0 评论 -
克鲁斯卡尔重构树 (以BZOJ 3732 Network,[NOI2018]归程为例)
建树方法在克鲁斯卡尔求最短路的基础上对原来的图进行一定的修改,与克鲁斯卡尔求最短路的区别在于每当找到一条树边时,将其变成一个点,这个点连接这条边连接的两个联通块(的根节点),然后就可以得到一棵树,这棵树的叶子结点,其余节点都是树边,权值就是树边的长度。性质可以发现,这棵树上的某棵子树的根节点是这棵子树的多有点的权值的最大值,如果要求某两个点的路径上的最大边权的最小值,求它们在这棵树...原创 2018-07-19 16:39:59 · 851 阅读 · 0 评论 -
边分
说明树分治的一种,与点分相似,每次找到两边节点数量相对接近的一条边(与重心相似),然后考虑经过这条边的路径,之后在对边的两边分别考虑。 对于菊花图,如果直接边分,那么复杂度显然会由O(logn)退化成O(n),因此在边分之前,先要rebuild: 统计出每个节点的儿子节点个数,若它大于S(一般为2,可以根据实际情况调整),则在其儿子节点改为S个虚点,与它们连虚边,原来的儿子节点平均分配到S...原创 2018-07-13 11:41:52 · 13404 阅读 · 0 评论 -
支配树(以HDU4694 Important Sisters为例)
定义在一个流程图(单源有向图)中,如果从源点到某个点p必须要经过某个点q,则q是p的支配点,我们记除了该点自己外,所有支配点中到它最近的点为该点的最近支配点(记为idom),将所有点与它的最近支配点连边构成的树就是支配树。求法对于DAG,非常简单,建出来的支配树也就是灭绝树。 首先建出dfs树,求出每个点的dfs序,之后点的大小比较都根据dfs序。 对于一般流程图则相对复杂,首先定...原创 2018-07-12 19:31:57 · 500 阅读 · 0 评论 -
笛卡尔树
性质二叉树,其中的每一个点是整棵树的极值,且每一棵树的中序遍历是原数组的一段。 详见下图: 建树方法每次加入到树的最右节点,若不符合其规范,沿着右边那一条链向上找,将它插入到恰好符合的那一个点的左节点,并且将那一段不符合的点加入到新加入点的右子树,并且更新右边那一条链。 例题代码scanf("%d",&amp;n); for(i=1;i&lt;=n;i...原创 2017-10-23 20:35:38 · 525 阅读 · 0 评论 -
边双(以CodeForces - 652E Pursuit For Artifacts为例)
定义若一张连通图中去掉任意一条边后仍然连通,则它是一个边双。求法可以发现,边双中不包含桥,因此将图中的桥去掉之后,剩下的图中的所有连通块都是边双。例题(CodeForces - 652E Pursuit For Artifacts)题意给出一张无向图,一些边上有一个神器,每条边只能经过一次,问,从s走到t,能否顺便拿到至少一个神器。做法可以发现,如...原创 2018-07-11 17:49:54 · 353 阅读 · 0 评论 -
点双(以HDU - 3686 Traffic Real Time Query System为例)
定义一张连通图中,若任意两个点之间都有至少两条没有重复点的路径,则这是一个点双。求法和tarjan系列的算法相似,在建dfs树的同时,可以发现每个割点都会将这个图分为几个点双,且每个割点都属于多个点双,因此,我们可以在dfs的同时,将所经过的边全部存起来,每当扫到一个割点就统计这个割点所分出的点双。代码void dfs(int now){// if(xh>D...原创 2018-07-11 17:23:15 · 376 阅读 · 0 评论 -
BZOJ 1001: [BeiJing2006]狼抓兔子 求平面图的最小割
题面题意给出一幅无向平面图,求s到t的最小割. 对偶图:将原图中的每一块区域当作一个点,原图上的每一条边转化为这条边两边区域之间的一条边,任何只在顶点处有交点的图(平面图)都有对偶图.做法这道题如果直接跑最大流,复杂度显然不对,但因为它存在对偶图,我们可以将题目转化为求左下角这块到右上角这块的最短路,对于样例可以这么建图 首先建对偶图 之后去掉原图就可以得到 可以发现从0点到13点(原创 2018-04-23 10:59:51 · 191 阅读 · 0 评论 -
并查集
作用 可以轻松记录并判断两个点是否在同一个连通图中 例如给出一些边,问两点是否连通的问题 也就是判断两个元素是否属于同一类实现方法 用树的形式来记录 点a的父节点就是指a的祖先结点中深度最小的那点,也就是父节点就是自己的那个点 一开始每一个点的父节点都是它自己 *父节点查找方法: 若a的父节点就是自己,则不变,反之,它的父节点为其父节点的父节点,详见代码原创 2017-11-05 15:53:22 · 210 阅读 · 0 评论 -
K-D Tree
作用一种用于储存多维数据的数据结构,同时可以查询多维空间中距离它最近的一个点.做法build首先它是一棵二叉树,而每一层用不同维进行分组,标准写法是每次求出每一维的方差,选取方差最大的那一维作为比较依据(后面与二叉查找树相同),找到这一维的中位数,分成两组,然后递归建树,复杂度为O(n*(logn)^2). 但实际上可以rand()一维再rand()一个分界点,之后比它大的放左子树,比它小的放右子原创 2018-04-13 20:25:27 · 289 阅读 · 1 评论 -
莫比乌斯反演
作用 用于简化一些运算,针对满足的函数的问题.引入 可以发现,若满足以上结论,则: F(1)=f(1) F(2)=f(1)+f(2) F(3)=f(1)+ f(3) F(4)=f(1)+f(2)+f(4) F(5)=f(1)+f(5) F(6)=f(1)+f(2)+f(3)+f(6) F(7)=f(1)+f(7) F(8)=f(1)+f(2)原创 2018-01-21 20:49:06 · 285 阅读 · 1 评论 -
HDU - 1754 I Hate It (树状数组维护区间最值)
题面题意 给出一列数,有两种操作: 1.修改一个数 2.询问区间最大值方法 用树状数组来维护区间最值,复杂度为O(n*(logn)^2). 做法与维护区间和不同,因为修改最值时无法求出新的最值,但是维护的区间相同. 树状数组维护的区间是[u-lowbit(u)+1,u],可以据此来进行这些操作.修改 若sz[i]之前的值都正确,则可以发现C[i]可以用这段代码原创 2018-01-16 11:58:21 · 428 阅读 · 0 评论 -
后缀数组
解释及作用 对于一个字符串,将其所有后缀排序,用后缀中的第一个字符代表这个后缀,那么排序后的数组就是后缀数组,例如,对于字符串ababs,它的后缀数组是1 3 2 4 5,因为 1.ababs -开始位置为1,排名第1 2.babs –开始位置为2,排名第3 3.abs—-开始位置为3,排名第2 4.bs——开始位置为4,排名第4 5.s——–开始位置为5,排名第5原创 2018-03-08 23:32:09 · 239 阅读 · 6 评论 -
Kosaraju求强连通分量,缩点
作用 只要两边dfs,相比于用tarjan求强连通分量,kosaraju算法还可以顺便求出强连通分量的拓扑序,有利于之后的运算.实现方法 首先以任意一点开始dfs,并记录下搜索的后序遍历,之后将所有边反向,每次从没有搜过的点中选择后序遍历最大的搜索,此次搜到的点均与该点属于同一个强连通分量,直到所有点都被搜到过停止,可以发现越先求出的强连通分量,拓扑序越小.例题(poj 2186)题意原创 2018-03-11 19:37:41 · 409 阅读 · 0 评论 -
2-SAT
解释 对于布尔方程(aVbVc…….)^(dVeVf……)^………,我们称(aVbVc…….),(dVeVf……)为子句,a,b,c,d,e,f…..为文字,若每个子句的文字均不超过两个,那么求解这样的方程被称为2-SAT. 此算法可以利用强连通分量高效求解这类方程.实现方法 若aVb=1,我们可以发现当!a时,b必须为1,当!b时,a必须为1,也就是说,若!a为真,则b为真,若!b原创 2018-03-11 20:54:26 · 331 阅读 · 0 评论 -
Tarjan求强连通分量,缩点
强连通分量 是指在一张图图中任意两点都可以两两互相到达.作用 在一些问题中因为两两可以互相到达的性质,可以将一个强连通分量当做一个大点来做.Tarjan 与tarjan算法求割点的做法相似,遍历时记录一个时间戳和一个low记录不经过祖先节点可以到达到的时间戳最小的点,遍历时再将扫到的点放入一个栈中,并用一个布尔数组记录这些点. 若时间戳与low相等,则不断pop直到当前点被po原创 2018-03-11 15:35:07 · 314 阅读 · 0 评论 -
差分约束系统 (Layout POJ - 3169为例)
作用 求解多个形如x+y<=c(c为常数)的不等式.具体做法 可以发现,在求最短路时,若a,b间有边的权值为c,则d[a]+c>=d[b],因而可以将不等式转化为这个形式,之后建边跑最短路即可.实际应用 一般讲题目转化为多个形如x+y<=c(c为常数)的不等式,之后建图跑最短路. 此题中一共就三种限制: 1.升序排列 2.有两点a,b间的距离不超过k,也就是b-a<原创 2018-02-23 18:04:40 · 223 阅读 · 0 评论 -
高度数组
解释及作用 是后缀数组中相邻两个字符串的lcp(最长公共前缀),可以在O(n)的时间内高效求出,帮助做一些字符串匹配问题。 h[i]=lcp(st[i],st[i+1])(st表示后缀数组中表示的字符串)实现方法 如果已经知道后缀数组中i与i+1的lcp为h,那么i代表的字符串与i+1代表的字符串去掉首字母后的lcp为h-1.根据这个我们可以发现,如果知道i与后缀数组中在它后一个的l原创 2018-03-11 11:42:52 · 541 阅读 · 0 评论 -
点分
作用 在树上实现,通过分治的方法,使原来需要复杂度为n^2的做法变为n*logn.实现方法 首先找到树的重心,然后以重心为根,考虑需要用到根的部分,之后去掉根节点,将原来子树分成多个小于原来大小的一半的多棵子树,再用上述方法反复处理,不难证明复杂度为n*logn. 因此点分的核心代码就是统计每个点的子树大小和找到根节点.void getsz(int now,int last){原创 2018-03-07 17:45:21 · 1715 阅读 · 0 评论 -
树状差分
作用 差分可以快速处理区间加的问题,而树状差分是分相似,可以快速处理树上一条链上的加法,将原来需要用树链剖分或是倍增的题目大大优化,且实现起来的复杂度低,也十分好些.实现方法 与差分基本相同,数列中的差分是每次修改头尾两节点,这里也是一样,处理链首和链尾即可,最后一遍dfs便可以求出每一个点或边的权值.代码以C. Fools and Roads CodeForces - 191C .#i原创 2018-02-10 19:14:22 · 398 阅读 · 0 评论 -
cdq分治
作用优点是可以代替高级数据结构相互嵌套,而且十分好写. 缺点是必须离线.实现方法可以和分治辨析: 普通分治将一个大问题分成两个相互独立的子问题,去分别解决,而cdq分治用于解决一个子问题会去影响另外一个子问题的题目,比如说归并排序求逆序对就是cdq分治. 实现时先解决影响另一子问题的子问题(一般为左边的那部分),然后再解决右边的. 具体建议通过题目来理解.例题题面题意已知一个数列,你需要进行原创 2018-04-15 20:29:18 · 7686 阅读 · 0 评论