常用算法讲解
文章平均质量分 74
I_AM_HelloWord
爱好编程信息学
展开
-
浅谈单调队列优化dp
什么是单调队列?举个浅显的例子:滑动窗口:给出n个数,要求从每个位置开始到其后的k位中的最大值。显然这题可以用RMQ问题的做法解,但用单调队列效率最高。我们维护一个队列,这个队列有两个参数,一个是位置编号,一个是其值,这个队列具有“编号单调增,值单调减”的特点,因为如果i>j,且a[i]>a[j],显然只要i和j在一个窗口中,j就不会是最大值,我们可以把j删掉(对于冗余状态原创 2016-10-25 19:25:40 · 1048 阅读 · 0 评论 -
多叉树的树形背包常见建模方法
一.多叉树变二叉树。这个技巧其实也有两种具体的方法:树的孩子兄弟表示法与dfs序法。1.树的孩子兄弟表示法。 大家在学习树形结构时一定接触了一个多叉树变二叉树的方法,就是把每个点与它的第一个儿子连边,然后将它的儿子依次连接起来。可以结合下面的图片理解这句话。总结成口诀就是:第一个儿子是左子树,其他儿子是左子树的右子树(似乎并不押韵,手动滑稽)2.dfs序法原创 2017-09-03 20:04:58 · 8961 阅读 · 6 评论 -
图论之强连通分量
问题描述:给出一个图,求其中的强连通分量。分析:常见的算法有tarjan算法和二度深搜法(即Kosaraju算法)这里详解tarjan算法。算法核心:对于一个图,我们给每一个dfs访问的点设立时间戳,即到达这里所需的最小时间,那么如果在树中,显然儿子结点的时间戳一定大于父亲的时间戳,而这里是有环的图,所以如果儿子的时间戳小于父亲的时间戳,则说明在访问父亲之前,就已经到达儿子原创 2016-11-15 17:20:21 · 760 阅读 · 0 评论 -
终极树状数组
树状数组及初步拓展。接着提出新的问题:A l r x把[l,r]加上xQ l r 求[l,r]的总和这该怎么办呢?显然先前所提出的方法已不再使用,我们深度分析:令加x之前sum[i]=segma(a[i]),加x之后sum'[i]=segma(a[i]).如果给[l,r]加上x,会对sum产生怎样的影响?1.i2.l3.r显然,对于1,3我们原创 2016-11-14 19:45:12 · 263 阅读 · 0 评论 -
二分题型的模型建立
二分题型最明显的有两种:求最大值的最小化,或最小值的最大化。一般地,对于一个求最值的问题,如果不方便直接求解的话同时这个最值的趋向是单调的,就可以二分枚举。此时二分一般加上dp或贪心的check()即可得知接下来的答案区间。下面分别讨论最常见的两种。最大值最小化:对于此类问题,我们设答案的区间为[l,r]那么当l=r时,显然区间只有一个值,这就是我们原创 2016-10-28 16:40:33 · 595 阅读 · 0 评论 -
详解KMP入门
在网上很容易找到分析KMP算法的博客,但我觉得他们都没有讲到点子上去,导致一些读者越看越困惑,我则是看了刘汝佳的书后,自我比较通俗易懂的总结一下。解决问题:给出字符串T和P,求P在T中第一次出现的位置,简称字符串匹配。算法准备:最单纯的模拟算法就是每次枚举起始点,再判断是否匹配,效率O(nm),极低。 但根据经验,任何一个高效算原创 2016-10-25 18:52:28 · 1370 阅读 · 0 评论 -
登峰造极之树——Size_Blanced_Tree萌新入门教程
先前的博文:旧版SBT教程洛谷P3369是道模板题,我在洛谷P3369中详细的写了一个题解,这里就直接copy来了。当时写的时候把zig,zag表示的旋转方向弄反了,大家将就这看吧。大家自己打的时候就把zig改成left_rotate,把zag改成right_rotate。184ms / 3.15MB代码:2.61KB C++11时空以及编程复杂度都还好吧= =,大原创 2017-08-28 09:42:05 · 526 阅读 · 0 评论 -
登峰造极之树——平衡树
在所有的平衡树中,为陈启峰提出的SBT最富盛名,并且最快最方便。下面就是我对此的学习过程。首先要了解二叉排序树,然后要明白了旋转在平衡过程中的重要地位。有左旋和右旋之分,下面以右旋为例,左旋对称即可:以上为原树,经过右旋后得到:于是我们可以很清楚的得到右旋代码:void RR(int &t){ int k=left[t]; left[t]=right[k];原创 2016-05-14 19:30:33 · 400 阅读 · 0 评论 -
登封造极之树——树链剖分
解决问题:给出一个树,有两个操作:1.修改某条树边的权值。 2.求某个节点到另一个的路径中的最大边权值。基本原理:如果不是一棵树,而是一条链,那么很清楚用线段树做。而现在就是一棵树,那么我们就可以将树分成一条一条的链。算法步骤:1.构造:我们称这些链为重路径,每两条重路径之间由一条轻边连接,对于一棵树,每一个父节点u有且仅有一条重路连向一个子节点v,这个子节点v必原创 2016-05-19 12:29:58 · 853 阅读 · 0 评论 -
AC自动机总结
如果你还不知道KMP是什么,或者不知道Trie是什么,先点下面的链接,学好这两样再来看这篇文章。KMP入门教程传送门。Trie入门教程传送门。好,那么我来讲讲AC自动机吧。以洛谷P3808模板题为例,如果我们有n个模式串,和一个文本串,我们需要统计有多少个模式串在文本串中出现了,怎么办?显然,如果我们直接枚举每个模式串,然后将其与文本串进行匹配,判断是否匹配成功,那么效率就原创 2017-08-30 21:26:56 · 1510 阅读 · 0 评论 -
LCA求法的三度升级
1.RMQ做法: 可见:学会用rmq解决lca问题2.倍增做法: 可见:LCA倍增3.轻重路径剖分法: 轻重路径剖分基础:树链剖分(无需看剖分过程,重点搞清楚什么是轻重路径) 那么,具体过程可以类比剖分的query过程:void dfs1(int u){ dep[u]=dep[fa[u]]+1; int Max=0;原创 2016-10-13 19:10:20 · 491 阅读 · 0 评论 -
字典树Trie总结
Trie就是把n个字符串建成一个树,树的每个节点都是一个字母,然后字符串的最后一个节点,我们会在Trie中对应的节点处打上标记,然后从根节点到每个标记点的路径上的字母依次排开就是n个字符串中的一个。是不是很浅显?稍稍举个例子:n=5hehishersabcxbc那么我们建的Trie应该是这样的 root / |原创 2017-08-29 20:39:33 · 995 阅读 · 0 评论 -
网络流征程——Dinic再详解
旧版链接//感觉以前写的好敷衍上次的文章绝大本分摘自别人的博客,这次我自己仔细的分析一下。首先,简单的FolkFoukerson算法不断的增广时,可能走了太多的反向弧,即做了大量的无用功,所以我们规定了增广的一个条件——每次只增广最短的那条,那么可以保证这条增广路长度不下降,上限是O(n),如果我们简单用bfs进行增广,这就是著名的EmondKarp(EK)算法,那么整原创 2017-08-25 22:09:36 · 432 阅读 · 0 评论 -
网络流征程——ISAP算法
叹:真心没时间写博了问:那你怎么有时间在洛谷上切了4道ISAP的模板题,然后还详细写了题解?叹:【手动滑稽】先给了Dinic的说明吧:Dinic详解ISAP就是在Dinic上再优化。我们考虑Dinic,它其实在DFS回溯时就确定以当起点前点为的最短路层次图已经不适用了,但是Dinic选择放弃这条路,尝试其他的路,然后再bfs一次性重构一个层次图,但其实是没有必要的,因为随着原创 2017-08-25 22:21:30 · 323 阅读 · 0 评论 -
登峰造极之树——Splay伸展树
这个splay也是个很有趣的数据结构,它是为了平衡权值二叉树而提出的,却最终不是以权值二叉平衡树的形式被广泛使用,而是去维护序列的区间修改(某些线段树实现不了的区间修改,如区间翻转等),很多萌新在初学splay时都看的是平衡权值二叉树形式的,所以突然接触区间翻转等问题会有困难。这里我就不讲splay的权值平衡树的形式了(网上资料很多),而是主要讲一讲怎么去理解splay去维护区间(几乎没有人解释的原创 2017-08-28 10:04:57 · 1336 阅读 · 0 评论 -
登封造极之字符串——后缀数组
定义:给出字符串T,将T的所有后缀(包括空串和本身)排序后,得到一个顺序,定义sa[i]数组表示第i小的后缀是从T的哪个位置开始的,如:T=aabcd则有sa={0,1,2,3,4,5}构建:直接模拟,得出所有的后缀快排,则O(n^2*log n) 效率不够,定义S[i,k]表示从第i个位置开始的长度为k的字符串,rank[i,k]表示在所有排好序的S[i,k]原创 2016-05-26 13:03:06 · 927 阅读 · 0 评论