
算法
chiyankuan
这个作者很懒,什么都没留下…
展开
专栏收录文章
- 默认排序
- 最新发布
- 最早发布
- 最多阅读
- 最少阅读
-
虚树
在处理一些要从一颗树上多次选出一些关键点的问题时,我们就要用到虚树。首先我们要对每一次的关键点建出虚树。所谓虚树就是只保留关键点和它们之间有用的lca的树,实际上就是把树缩小了。在对一次的关键点建树时,我们首先把关键点按dfs序从小到大排序,然后一个一个地加入关键点。这里我们要维护一个栈,根到当前关键点的一条路径。假设当前要加入的关键点为p,栈顶元素为d[t],那么我们求出p和d...原创 2020-01-18 22:22:04 · 131 阅读 · 0 评论 -
莫比乌斯反演
莫比乌斯反演其实套路挺多的.莫比乌斯函数首先我们要引入莫比乌斯函数.(i)=1、1(i=1)2、-1(i的每一个质因子的指数都为1)3、0(其他情况)我们有一种线性求的方法:mu[1]=1;for(i=2;i<=n;i++){ if(bz[i]==0){ss[0]++;ss[ss[0]]=i;mu[i]=-1;} for(j=1;j<=...原创 2019-12-17 18:41:16 · 147 阅读 · 0 评论 -
点分治
讲一讲点分治的基本运用,其实它也是一个优秀的暴力。点分治最常见的套路就是“求树中满足条件的点对的数目”,当然它也可以应用在一些玄学题目中。我们来看一道经典例题:jzoj1166. 树中点对距离这题的思想就是不断求出当前分治块的重心,然后算出经过重心的合法路径数,接着把重心断开,然后不断分治下去。这样就可以算出答案了。关键是怎样求经过当前重心的合法路径的数目。我们可以先暴力算出...原创 2019-12-10 19:53:53 · 148 阅读 · 0 评论 -
线性基
线性基是一种针对异或运算的工具。线性基的定义:对于一个序列,我们构造一个集合,使得序列中的每一个数都可以有集合中的一些数异或起来得到。构造方式for(i=1;i<=n;i++){ x=a[i]; for(j=len;j>=1;j--) if((x>>(j-1))%2==1) if(d[j]==0){d[j]=x;break;} el...原创 2019-12-09 20:43:21 · 125 阅读 · 0 评论 -
克鲁斯卡尔重构树
补一补之前没有写的博客。克鲁斯卡尔重构树的构建方法如下:每次合并x和y时,新建一个节点z,把x和y都连向z,并将x-y的边权l等信息赋值在z的点权上。这样做的好处是我们每次找一个范围内的点是,实质上就是在找某棵子树。注意点的一些值是随祖孙关系有单调性的。...原创 2019-11-10 22:20:41 · 246 阅读 · 0 评论 -
O(n)求逆元
求1~n在模M的意义下的逆元有一种O(n)的方法:inv[i]=(M-M/i)*inv[M%i]%M证明如下:设t=M/i, k=M%i(注意t是下取整)则两边同时除以k*i得在把t=M/i、k=M%i带入就得到了inv[i]=(M-M/i)*inv[M%i]%M。初始值为inv[1]=1。注意这里的M只能是质数,因为要同时除以k*i。若M不是质数,那么必...原创 2019-11-09 20:31:31 · 454 阅读 · 0 评论 -
tarjan总结
今天学了一下tarjan的几种常见应用,发现我还是有很多知识盲点的。有向图的强连通分量这是最简单的应用,关键就是:1、若dfn[y]=0,则dfs(y),low[x]=min(low[x],low[y])2、否则,若y在栈中,则low[x]=min(low[x],dfn[y])。这是为了防止搜到别的分量中去。代码如下:int dfs(int z){ int i;...原创 2019-11-06 22:31:56 · 345 阅读 · 0 评论 -
线段树合并(模板)
线段树合并的原理比较简单,这里贴一下模板。基本结构就是:int hb(int x1,int x2){ 1、若x1、x2是叶子节点,那么将x2合并到x1 2、若x1的左儿子为空,x2的左儿子不为空,那么将x1的左指针指向x2的左儿子;若x1、x2的左儿子都不为空那么继续合并它们的左儿子 3、右儿子同上 4、f[x1]=f[x1的左儿子]……f[x1的右儿子...原创 2019-10-26 21:23:02 · 340 阅读 · 0 评论 -
树链剖分
树链剖分某种意义上来说就是优秀的暴力。首先明确几个概念:1、重儿子:一个x的所有儿子中size最大的就是它的重儿子。2、轻儿子:非重儿子的儿子就是轻儿子。3、重边:连向重儿子的边就是重边。4、轻边:连向轻儿子的边就是轻边。5、重链:由重边构成的链。树链剖分的基本流程如下:1、dfs求出重儿子2、dfs求出dfs序和top。并且保证重链上的点的dfs序连续,...原创 2019-09-23 21:57:05 · 153 阅读 · 0 评论 -
manacher算法总结
manacher算法是一个在O(n)时间内求出一个字符串以每一个点为中心的回文串的长度的算法。下面是它的流程:首先我们在原串两个字符之间插入一个没有的字符(比如#),然后我们对这个新串进行操作,这样做的目的是为了保证求出来的回文串长度一定为奇数。设r[i]表示已i为中心的回文串的半径。然后我们从前往后扫一遍这个串,一次求出r[i]。在求r[i]时,我们要分类讨论。设R表示之前最...原创 2019-08-14 21:14:10 · 179 阅读 · 0 评论 -
较优的网络流算法
下面介绍两种时间复杂度较为优秀的网络流算法:dinic和SAP。dinicdinic主要是以下两大优化: 分层 当前弧优化 分层每一次dfs之前我们都从源点bfs一次,bfs只走还剩流量可流的边,通过bfs我们把残量网络分层。设i的深度为deep[i],那么在dfs是我们要保证deep[y]=deep[x]+1才走x-y这条边。当然我们也可以多次dfs再一次bf...原创 2019-08-14 19:37:44 · 253 阅读 · 0 评论 -
后缀自动机
后缀自动机是一个很复杂的算法,下面讲一讲建图和应用。建图首先要明确后缀自动机上点和含义:一个点代表的是一类有相同后缀的字符串,而每一个点的fail一定是它本身的后缀。那么我们定义如下结构体:struct point{ int len; int fa; int ch[30];};point a[MAXN];其中fa就是fail,ch表示点的出边(a...原创 2019-08-09 15:33:26 · 167 阅读 · 0 评论 -
树状数组总结
因为树状数组用得比较少,所以今天总结一下常见用法。(顺便贴一些板)首先上树状数组的定义:设原数组为a,树状数组为c,那么c[i]=a[i-2^k+1]+a[i-2^k+2]……+a[i]。其中k为i的二进制状态下最后面连续的0的个数。然后我们就可以得出树状数组的修改和查询操作了。查询:因为c[i]表示的是连续的一段a的和,那么查询的时候我们每次把当前的c[i]加上时候就把i减去一段数,...原创 2019-07-10 21:47:59 · 327 阅读 · 0 评论 -
半平面交
求多条直线的半平面交要有向量的基础。下面直接将算法。首先要明确每一条向量的左边还是右边是我们要取的部分,然后把所有的向量按极角排序。极角排序的流程是首先求出每一个向量的极角值,这个用atan2函数求。atan2的定义是atan2(y,x)表示(x,y)这个点的极角值,代码如下:for(j=1;j<=m;j++)a[j].angle=atan2(a[j].vy,a[j]....原创 2019-07-04 20:57:08 · 164 阅读 · 0 评论 -
set与multiset的用法
头文件:#includeusing namespace std;定义:set/multiset 名字set与multiset的区别:set中没有相同元素,而multiset可以有相同元素set与multiset的相同操作:s.insert(x) 把x元素插入s中s.empty()=0 s中有元素,s.empty()=1 s中没有原创 2017-03-04 16:15:15 · 651 阅读 · 0 评论 -
多重背包的单调队列优化
在直接用多重背包而超时时,我们可以考虑用单调队列来优化。我们来看一下转移方程:f[i][j]=max(f[i][j],f[i-1][j-w[i]*k]+v[i]*k)这时我们可以维护f[i-1][j-w[i]*k]+v[i]*k。当一个f[i-1][l]可以更新f[i][j]时,则有w[i]|(j-l),则有j%w[i]=l%w[i],就说明j与l除以w[i]的余数是一样的。那么我们可原创 2017-06-16 19:40:23 · 1627 阅读 · 0 评论 -
【gdoi2018 day1】密码锁
这一题的正解是差分。设dif[i]=a[i+1]-a[i],(0<=i<=n),默认a[0]=a[n+1]=0。当然,dif[i]是在模m的意义下的。我们的原目标是把a数组清成0,而若a全为0,则dif也全为0。反之,若dif全为0,则a全为0,因为a[1]=a[0]+dif[0]=0,a[2]=a[1]+dif[1]=0……,以此类推。那么我们现在的任务就是要把dif清成0.那么我们...原创 2018-05-09 20:02:11 · 348 阅读 · 0 评论 -
KMP总结
网上有很多讲得好的博客,这里简单说一下原理和实现过程就行了。原理就是当出现一个字符不匹配时,将当前最长相同前缀移上来,例.......Aa...... Bc...Bb.. Bc...Bb..假设A串与B串相同,可是a与b不匹配,那么如果这是我们一个一个移的话就会很慢,所以我们可以考虑预处理出一个最长的前缀与后缀相同,这时我们只需把Bc移上来,比较a与c是否相同就行了。那么我们需要预处...原创 2018-06-01 20:25:41 · 203 阅读 · 0 评论 -
4644. 【NOI2016模拟7.16】人生的经验——欧拉回路
这一题的第一个答案就是n*c+l-1(也就是说任意两个相邻的字符串都可以共用l-1个字符),证明如下:我们首先列出c^(l-1)个点,代表c^(l-1)种字符串的前缀,然后我们又把每一个点连出c条边,代表连向字符串的后缀。举个例子:abcd分别连向bcdabcdbbcdcbcdd(上面的后l-2个要与下面的前l-2个相同,两个字符串分别表示一个长度为l的字符串的前l-1个与后l-1个,连边的权值为...原创 2018-06-30 21:28:20 · 254 阅读 · 0 评论 -
SA后缀数组总结
SA后缀数组用于字符串。首先把每一个位置对应的后缀字符串按字典序从小到大排序,然后设sa[i]表示排名为i的后缀串在原串中对应的位置,rank[i]表示原串中位置i对应的后缀的排名为i。接下来讲讲怎样求sa。这里主要运用了倍增的思想。设S[i,k]表示从i开始长度为k的字符串在所有长度为k的字符串中的排名,一开始我们先求出S[i,1]。接下来我们考虑利用S[i,1]来求S[i.2]。这要用到一条性...原创 2018-07-14 21:58:06 · 826 阅读 · 0 评论 -
人工栈
当递归出现栈溢出时,那么久只能使用人工栈来解决问题。人工栈其实就是一个栈,栈的每一个点要保存递归函数里的所有参数以及在递归函数里定义的所有变量。每次就按照递归函数的操作顺序打一遍。流程如下。递归流程:int dg(int ……){ int …… A操作 while(E) { ...原创 2019-01-06 20:59:18 · 626 阅读 · 0 评论 -
期望总结
T1:1.26A组第三题,JZOJ4225。此题即树上游走。设f[i]表示由第i个点走向它的父亲的期望长度,则f[i]=1/d[i]+sum(1+f[y]+f[i])/d[i]。d[i]表示i的度数,y是i的儿子。这个方程的意思是从i往它的相邻的点走,每一个点都有1/d[i]的概率。若直接走到i的父亲则期望长度为1/d[i];若走到i的一个儿子再走上去则期望长度为(1+f[y]+f[i])/d...原创 2019-01-26 22:48:15 · 222 阅读 · 0 评论 -
splay总结
splay的功能十分强大,但是操作复杂,下面总结一下splay的几种常见操作。首先明确平衡树的概念:每一个节点的左子树都比它小,右子树都比它大。变量定义:ch[x][0/1]:x的左/右儿子size[x]:x所在子树的大小fa[x]:x的父亲清理一个节点:int clear(int x){ ch[x][0]=ch[x][1]=size[x]=0;}重新计...原创 2019-06-27 15:54:25 · 412 阅读 · 0 评论 -
莫队
莫队与分块一样,都是一种优化时间复杂度的思想方法,它的应用十分广。莫队分三种:普通莫队、树上莫队和带修莫队。 普通莫队 莫队的实质就是通过分块和排序来提高效率。分块就不讲了。还是和平常一样块大小为,块的个数也是。关键的是排序。排序方式如下:同一块的按r从小到大排,不同块的按l从小到大排。(其实就是先按块的顺序排,同一块的再按r排)。贴一下代码,方便理解:int cm...原创 2019-07-12 21:51:36 · 2120 阅读 · 0 评论 -
上下界网络流
有上下界的网络流与普通网络流比起来较为复杂,这里总结一下它的大概解法。首先我们要建新图(即转化为普通网络流图),步骤如下:1、对于原图中一条(x,y,down,up),我们在新图中建立(x,y,down-up)。2、设d[i]表示所有入i边的down的和-出i的边的down的和。建立新的超级源ss和超级汇tt。如果d[i]>0,那么连(ss,i,d[i]),否则连(i,tt,...原创 2019-07-09 20:35:05 · 158 阅读 · 0 评论 -
树的直径和重心
树的直径树的直径即为树上的最长链,这个树型dp一下求就好了。一棵树可能有多条直径,但他们的中点是唯一的。树的重心定义:最大子树大小最小的点是重心求法:还是树形dp性质:1、一棵树最多有两个重心,并且它们是相邻的。2、树中所有点到某个点的距离和中,到重心的距离和是最小的。...原创 2019-07-10 08:01:07 · 604 阅读 · 0 评论 -
向量
向量在计算几何中有很大用途,下面总结一下向量常见的几种用法。定义一个向量:struct DOT{ int x; int y;};向量的加减法:int jia(DOT a,DOT b){ return DOT(a.x+b.x,a.y+b.y)}int jian(DOT a,DOT b){ return DOT(a.x+b.x,a.y+b.y)}...原创 2019-07-04 20:31:00 · 814 阅读 · 0 评论 -
线段树基础总结
线段树程序分为三个部分:构造树、修改和查询。其中,构造树的程序十分简单,结构如下:dg(左端点,右端点、当前节点)if(当前区间只有一个点)直接把当前节点的赋为这个点else{ dg(左端点,中端点,左节点);//左子树 dg(中端点,右端点,右节点);//右子树 当前节点=左节点和右节点中最优的}而修改和查询则要根据题目不同来确定,下面是练习的两道题原创 2017-01-14 20:32:45 · 215 阅读 · 0 评论