- 博客(16)
- 收藏
- 关注
原创 图的常见存储结构
图的存储结构邻接矩阵邻接矩阵的表示方式为一个拥有两个维度的数组。其表示方法为define N 1000+5int a[N][N]a[i][j]=1;//其从i到j有边,其权值为1。一般当图是没有权重的 //就视为其权重为1前向星前向星和邻接矩阵的不同是,它使用主要存储边的方式来存储整个图的信息。其是用一个数据结构来定义而成int head[maxn]//存储每一个边的起始...
2020-01-30 16:29:43 420
原创 AC自动机
int idx(char s){return s-'a';} void insert(char s[]){ int len=strlen(s); int now=root; for(int i=0;i<len;i++) { int id=idx(s[i]); if(!c[now][id]) c[now][id]=cnt++; now=c[now][id]; ...
2019-10-18 15:25:05 124
原创 kmp
kmpvoid build(char s[],int n){ int k=0;nxt[0]=0; for(int i=1;i<n;i++) { while(k&&s[i]!=s[k]) k=nxt[k-1]; if(s[i]==s[k]) k+...
2019-10-17 21:21:09 149
原创 manachar
manacharint INIT(char *st){ int i, len = strlen(st); tmp[0] = '@'; for (i = 1; i <= 2 * len; i += 2) { tmp[i] = '#'; tmp[i + 1] = st[i / 2]; } tmp[2 * len + 1] = '#'; tmp[2 * len + 2] ...
2019-10-17 21:15:45 148
原创 数位DP
数位DP数位dp其实就算是计数dp在某些区间下求满足状态的个数。做数位dp就是找到并弄清楚题目的约束条件,注意有些题要考虑前导零的情况和确定dp记忆化数组的维度的意义,尽量越多越好,但是不要超出空间,因为维度太少,枚举记忆化的时候,大的数字得到结果可能会把小的数字得到的结果进行覆盖,这样就产生冲突,维度多一点就不会产生这种冲突。上两步分析完之后,再确定空间复杂度,如果超了就找方法降低空间。i...
2019-10-16 17:45:36 421
原创 Dynamic programming
算法 DPDP(英文 :Dynamic programming)是ACM竞赛中常见的一类题型,又名动态规划动态规划性质最优子结构性质:如果问题的最优解所包含的子问题的解也是最优的,我们就称该问题具有最优子结构性质(即满足最优化原理)。对此我们可以假设:C到B的最优路径为10,次优为11。在取C到B次优的情况下得到整体优是C到B到A,必然有C到B的最优解使得路径更小。子问题重叠性质:子问题重...
2019-10-16 17:17:40 168
原创 贪心
贪心贪心说起特别的简单,你只需要考虑当前一步的最优性能。但是这样的话,有可能得到的只是当前的极大值而不是最大值。贪心的难度在于怎么贪心和证明。我们常见的方法有1,邻项交换,证明在任意的情况下对局部最优策略的微小改变都会让整体的结果变差。2,范围放缩,对任何局部最优解的拓展都不会让整体结果变差。3,反证法。4,数学归纳法。5,决策包容性,在做出局部最优解后在问题状态空间的可达集合包含...
2019-10-16 17:11:51 385
原创 线段树
线段树线段数是一种二叉树,它主要应对的是多个离线询问或者操作时的回答。线段树可以在 O(logn)的时间复杂度内实现单点修改、区间修改、区间查询(区间求和,求区间最大值,求区间最小值)等操作。。是一种常用的算法结构。也是数据结构中的一种。线段树的结构非常有规律,我们拿用线段树来存除区间和的样例说明:根节点存储的是整个区间的最值,然后每个节点的左子节点存的是这个节点区间前半部分的和,右节点存储的...
2019-10-16 16:57:04 133
原创 并查集
并查集考虑一个问题:假设,A与B认识,B与C认识,那么A一定与C认识。由B与A认识,B与C认识,你得到A与C认识。因为你帮他们放在了一个集合中。也可以理解为他们构成了一个联通分量。也就变成了只要他们在一个集合或者强连通分量里就可以满足条件。我们可以用一个数组存储每个节点的父亲节点,当两个节点的祖先节点一样,这两个节点就在一个集合里。我们因为只要考虑是否在一个集合,所以我们可以压缩路径,让搜索...
2019-10-15 23:06:56 133
原创 ST算法
ST算法在给定的一个区间中,想要求出他的最值需要在这个区间中进行O(n)的操作。如果是在线查询,时间复杂度就是你查询的数目乘上你所要查询的区间长度。显然这样有可能是超范围的。当但,你还可以这样考虑,我先用O(n2)的时间预处理,这样就可以用O(1)的来应付每一个查询。这样,时间复杂度就是O(n2+m)(m是你询问的次数)。但是大多数情况下,你的n都会是1E4级别以上的。这样的预处理会超时。我...
2019-10-15 22:45:28 523
原创 并归排序
并归排序逆序对对于一个序列a,如果i<j,并且a[i]>a[j],则称a[i]与a[j]是一对逆序对。并归排序要统计一个序列里面有多少逆序对最简单的方法暴力统计逆序对。但是这样的时间复杂度是O(n2)的,在竞赛中一定时行的。那么,我们考虑这个问题。我们可不可以帮一段序列分为两段,然后排序,统计后一段的每一个与前一段的每一个是否构成逆序对,又因为后一段与前一段都是排好的序列,所以...
2019-10-11 18:05:17 146
原创 对顶堆
对顶堆对于离线让你找你个数组里面的最大值,最小值,第K大值,第K小值,我们可以遍历一遍,找出答案。但是如果让你在线的寻找第K大值,第K小值或者中位数呢。我们好像就不能使用这种方法了。这时我们可以使用对顶堆来完成题目要求。假设以中位数为要求,对顶堆就是一个堆存大数,一个堆存小数。当两个堆相差大于1的时候我们就帮数多的堆的堆顶元素加入数少的堆的堆顶。priority_queue<int&g...
2019-10-11 17:34:46 375
原创 离散化
离散化在许多问题里,问题的范围是很大的数N,但只涉及M个数的操作同时操作与他们的数字没有什么关系,只和他们的相对大小有关系的时候,我们可以离散化处理。帮他们按照相对大小在进行一次标号处理。一般使用于线段树中。int a[maxn],b[maxn];void discrete(int n){ for(int i=0;i<n;i++) b[i]=a[i]; sort(b,...
2019-10-11 17:21:37 97
原创 二分查找和三分求单峰函数极值
二分查找对于一个单调递增的数列,我们可以从头到尾遍历一遍求出所求值的位置,这样的时间复杂度毫无疑问的o(n)的,我们可以对其二分求出所需要的值。二分的写法有很多,根据问题的不同会有不同的写法。所有我们在这里只讲思路。假设这个区间是单调递增的,对于区间[l,r]我们可以找出中间点mid=(r+l)>>1,对中间的值和所需要的值进行比较,如果mid的值大于所求值,r=mid-1。反之,l...
2019-10-11 16:24:11 862
原创 前缀和和差分
前缀和如果题目给你一个区间,让你求此区间内的总和。从区间的最开始加到区间的结尾就可以完成要求。但是要是题目给你q(q<=50000)个询问呢,且每个询问的区间长度是10000左右呢。如果在暴力的加和肯定解决不了问题。这时我们可以使用前缀和解决这件事情。对于每个a[i],我们都可以让其表达为前i个值的和。这样对于从l到r的询问我们就可以用a[r]-a[l-1]来O(1)的求出这个询问。差分...
2019-10-11 16:00:37 175
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人