自定义博客皮肤VIP专享

*博客头图:

格式为PNG、JPG,宽度*高度大于1920*100像素,不超过2MB,主视觉建议放在右侧,请参照线上博客头图

请上传大于1920*100像素的图片!

博客底图:

图片格式为PNG、JPG,不超过1MB,可上下左右平铺至整个背景

栏目图:

图片格式为PNG、JPG,图片宽度*高度为300*38像素,不超过0.5MB

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

-+
  • 博客(54)
  • 收藏
  • 关注

原创 树上倍增求树中任意两点

跳步祖宗数组 fa : fa [ i ] [ 20 ] 表示从当前位置向上跳 2^ j 次方步后所在的点的代号。深度数组 depth[ i ] : 表示当前的点的深度。(用于比较两点位置。跳步祖宗数组需要预处理:(dfsfor(int i = 1; i <= n; i ++){ if(!st[i]) // 挨个, 防止有不连通的块没有遍历到; { depth[i] = 1; dfs(i); }}void dfs...

2022-01-30 11:53:07 333

原创 三分查找(我就想不明白为什么标题必须5个字?

二分查找, 使用与单调的函数, 用于查找true 与 false 的分割点, 该点为极限值。三分查找的概念 : 在二分查找的基础上, 在其中一个区间再进行一次二分。即三分。通常也用来确定最值。而三分查找 是寻找峰值,即函数的趋势并不是单调的通过比较mid 和 mmid 对峰值的接近程度(一般是比大小),来一次次的缩小L 和 R 的范围。如上图, judge( mid ) < judge( mmid ) 则可缩小边界为 R = mmid;个人更喜欢的三分.

2022-01-14 16:46:13 192

原创 快速幂 ex ///快速乘 mul

快速幂(化幂为乘):快速计算 a * b % mod 的结果。(时间复杂度log n, 且可以在过程中取模)快速乘(化乘为加) : log n求a的b次方,取模mod(1<=a,b,mod<=1e18)Input多组输入,每组数据一行,3个正整数,分别为a,b,modOutput每组数据输出一行,为答案Sample Input2 10 100000005 100 10 2 37Sample Output102400Hint无.

2022-01-07 20:33:36 592

原创 记忆化搜索(递归处理dp)(dfs + 记忆化搜索)

给定一个RR行CC列的矩阵,表示一个矩形网格滑雪场。矩阵中第ii行第jj列的点表示滑雪场的第ii行第jj列区域的高度。一个人从滑雪场中的某个区域内出发,每次可以向上下左右任意一个方向滑动一个单位距离。当然,一个人能够滑动到某相邻区域的前提是该区域的高度低于自己目前所在区域的高度。下面给出一个矩阵作为例子: 1 2 3 4 516 17 18 19 615 24 25 20 714 23 22 21 813 12 11 10 9在给定...

2022-01-04 22:34:49 274

原创 树形dp

Ural 大学有NN名职员,编号为1∼N1∼N。他们的关系就像一棵以校长为根的树,父节点就是子节点的直接上司。每个职员有一个快乐指数,用整数HiHi给出,其中1≤i≤N1≤i≤N。现在要召开一场周年庆宴会,不过,没有职员愿意和直接上司一起参会。在满足这个条件的前提下,主办方希望邀请一部分职员参会,使得所有参会职员的快乐指数总和最大,求这个最大值。输入格式第一行一个整数NN。接下来NN行,第ii行表示ii号职员的快乐指数HiHi。接下来N−1N−...

2022-01-04 22:06:44 4437 1

原创 状态压缩dp

蒙德里安的梦想:求把N×MN×M的棋盘分割成若干个1×21×2的的长方形,有多少种方案。例如当N=2,M=4N=2,M=4时,共有55种方案。当N=2,M=3N=2,M=3时,共有33种方案。如下图所示:输入格式输入包含多组测试用例。每组测试用例占一行,包含两个整数NN和MM。当输入用例N=0,M=0N=0,M=0时,表示输入终止,且该用例无需处理。输出格式每个测试用例输出一个结果,每个结果占一行。数据范围1≤N,M≤111...

2022-01-03 21:13:18 351

原创 数位统计dp

给定两个整数aa和bb,求aa和bb之间的所有数字中0∼90∼9的出现次数。例如,a=1024,b=1032a=1024,b=1032,则aa和bb之间共有99个数如下:1024 1025 1026 1027 1028 1029 1030 1031 1032其中0出现1010次,1出现1010次,2出现77次,3出现33次等等…输入格式输入包含多组测试数据。每组测试数据占一行,包含两个整数aa和bb。当读入一行为0...

2022-01-03 15:38:34 3941

原创 区间和并

例题,石子合并设有NN堆石子排成一排,其编号为1,2,3,…,N1,2,3,…,N。每堆石子有一定的质量,可以用一个整数来描述,现在要将这NN堆石子合并成为一堆。每次只能合并相邻的两堆,合并的代价为这两堆石子的质量之和,合并后与这两堆石子相邻的石子将和新堆相邻,合并时由于选择的顺序不同,合并的总代价也不相同。例如有44堆石子分别为1 3 5 2, 我们可以先合并1、21、2堆,代价为44,得到4 5 2, 又合并1,21,2堆,代价为99,得到9 2,再合...

2022-01-03 10:45:17 93

原创 线性dp

一 、 数字三角形。给定一个如下图所示的数字三角形,从顶部出发,在每一结点可以选择移动至其左下方的结点或移动至其右下方的结点,一直走到底层,要求找出一条路径,使路径上的数字的和最大。 7 3 8 8 1 0 2 7 4 44 5 2 6 5输入格式第一行包含整数nn,表示数字三角形的层数。接下来nn行,每行包含若干整数,其中第ii行表示数字三角形第ii层包含的整数。输出格式输...

2022-01-02 21:48:21 313

原创 分组背包 (一组里选一个

有NN组物品和一个容量是VV的背包。每组物品有若干个,同一组内的物品最多只能选一个。每件物品的体积是vijvij,价值是wijwij,其中ii是组号,jj是组内编号。求解将哪些物品装入背包,可使物品总体积不超过背包容量,且总价值最大。输出最大价值。输入格式第一行有两个整数N,VN,V,用空格隔开,分别表示物品组数和背包容量。接下来有NN组数据:每组数据第一行有一个整数SiSi,表示第ii个物品组的物品数量; 每组数据接下来有SiSi行,每行...

2022-01-02 15:37:41 292

原创 多重背包问题

暴力拆解。(不推荐多重背包可以看作0 1 背包,将多重背包拆开存放。#include<iostream>using namespace std;int a[10005], b[10005];int main(){ int t = 0, n, m, dp[10005] = { }, w, v, s; cin >> n >> m; while(n -- ) { cin >> v >&gt

2022-01-02 14:57:56 123

原创 完全背包

有NN种物品和一个容量是VV的背包,每种物品都有无限件可用。第ii种物品的体积是vivi,价值是wiwi。求解将哪些物品装入背包,可使这些物品的总体积不超过背包容量,且总价值最大。输出最大价值。输入格式第一行两个整数,N,VN,V,用空格隔开,分别表示物品种数和背包容积。接下来有NN行,每行两个整数vi,wivi,wi,用空格隔开,分别表示第ii种物品的体积和价值。输出格式输出一个整数,表示最大价值。数据范围0<N,V≤10000&lt...

2021-12-27 19:33:20 68

原创 0-1背包问题

有NN件物品和一个容量是VV的背包。每件物品只能使用一次。第ii件物品的体积是vivi,价值是wiwi。求解将哪些物品装入背包,可使这些物品的总体积不超过背包容量,且总价值最大。输出最大价值。输入格式第一行两个整数,N,VN,V,用空格隔开,分别表示物品数量和背包容积。接下来有NN行,每行两个整数vi,wivi,wi,用空格隔开,分别表示第ii件物品的体积和价值。输出格式输出一个整数,表示最大价值。数据范围0<N,V≤10000<...

2021-12-27 17:57:27 134

原创 二分图的最大匹配(yxc的人生小课堂)

最让人后悔的往往不是做错了, 而是没有去做。(啊啊啊我最喜欢听别人讲人生)匈牙利算法因为只需要用左边的二分图来搜, 所以只需要存一下从左到右的边, 不需要用无向图来存。模板核心 find函数:int match[ N ]; 用于记录女孩的现男友。预定数组:每次循环需要重置使得另一个男生在考虑环bool st [ N ];...

2021-12-27 13:29:13 102

原创 染色法判断二分图

将所有的点分成两个集合, 使所有的边只出现在集合之间,就是二分图。二分图一定不含有奇数环,也不一定是连通图。因为不一定是连通图, 故最后要遍历一遍 1~ n, 且要立flag作为标志。思路:利用深搜遍历进行染色(1, 2 交替染色)在染色(深搜)过程中维系一个bool遇到染色矛盾情况 bool false给定一个nn个点mm条边的无向图,图中可能存在重边和自环。请你判断这个图是否是二分图。输入格式第一行包含两个整数nn和mm。接...

2021-12-24 20:50:45 293

原创 kruskal求最小生成树(对边的排序,遍历)

给定一个nn个点mm条边的无向图,图中可能存在重边和自环,边权可能为负数。求最小生成树的树边权重之和,如果最小生成树不存在则输出impossible。给定一张边带权的无向图G=(V,E)G=(V,E),其中VV表示图中点的集合,EE表示图中边的集合,n=|V|n=|V|,m=|E|m=|E|。由VV中的全部nn个顶点和EE中n−1n−1条边构成的无向连通子图被称为GG的一棵生成树,其中边的权值之和最小的生成树被称为无向图GG的最小生成树。输入格式...

2021-12-24 10:13:51 275

原创 prim最小生成树

给定一个nn个点mm条边的无向图,图中可能存在重边和自环,边权可能为负数。求最小生成树的树边权重之和,如果最小生成树不存在则输出impossible。给定一张边带权的无向图G=(V,E)G=(V,E),其中VV表示图中点的集合,EE表示图中边的集合,n=|V|n=|V|,m=|E|m=|E|。由VV中的全部nn个顶点和EE中n−1n−1条边构成的无向连通子图被称为GG的一棵生成树,其中边的权值之和最小的生成树被称为无向图GG的最小生成树。输入...

2021-12-23 20:32:20 70

原创 dijkstra 求最短路(稀疏图)

给定一个nn个点mm条边的有向图,图中可能存在重边和自环,所有边权均为非负值。请你求出11号点到nn号点的最短距离,如果无法从11号点走到nn号点,则输出−1−1。输入格式第一行包含整数nn和mm。接下来mm行每行包含三个整数x,y,zx,y,z,表示存在一条从点xx到点yy的有向边,边长为zz。输出格式输出一个整数,表示11号点到nn号点的最短距离。如果路径不存在,则输出−1−1。数据范围1≤n,m≤1.5×1...

2021-12-20 09:49:58 178

原创 双链表的构建(idx的0 1 作为左右边界)

实现一个双链表,双链表初始为空,支持55种操作:在最左侧插入一个数; 在最右侧插入一个数; 将第kk个插入的数删除; 在第kk个插入的数左侧插入一个数; 在第kk个插入的数右侧插入一个数现在要对该链表进行MM次操作,进行完所有操作后,从左到右输出整个链表。注意:题目中第kk个插入的数并不是指当前链表的第kk个数。例如操作过程中一共插入了nn个数,则按照插入的时间顺序,这nn个数依次为:第11个插入的数,第22个插入的数,…第nn个插入的数。...

2021-12-14 18:08:01 176 2

原创 单调栈(一个例题)

题目的目的 : 找到一个数右边第一个比它大的数因此我们可以自右向左构建单调栈,这样就可以保证第一个比它大的数一定在栈中栈储存数的下标单调栈中,大于两个坐标之间所有的数,所以可以忽略这些数。#include<iostream>#include<stack>using namespace std;const int maxn = 1e6 + 5;int n;int a[maxn];int ans[maxn];int main(){ ci...

2021-12-12 11:14:16 464

原创 Floyd求最短路

就是一笨b算法给定一个nn个点mm条边的有向图,图中可能存在重边和自环,边权可能为负数。再给定kk个询问,每个询问包含两个整数xx和yy,表示查询从点xx到点yy的最短距离,如果路径不存在,则输出impossible。数据保证图中不存在负权回路。输入格式第一行包含三个整数n,m,kn,m,k。接下来mm行,每行包含三个整数x,y,zx,y,z,表示存在一条从点xx到点yy的有向边,边长为zz。接下来kk行,每行包含两个整数x...

2021-12-10 15:02:34 92

原创 SPFA算法

思路分析bellman _ ford算法会遍历所有的边, 但很多的边没有必要遍历,因此我们只需要遍历那些到源点距离变小的点所连接的边即可,只有当前一个点的前驱节点更新了,该节点才会得到更新,因此我们将创建一个队列,每次加入距离被更新的节点。注意 :1 . st 数组的作用 : 判断当前的点是否已经加入到队列当中了 , 已经加入的不用重复加入,如果需要更新数值,则仅更新。2 . SPFA算法和dijstra 算法长得像,但是其中意义还是相差很远:1] Dijkstra算法中的st数.

2021-12-10 14:28:21 518

原创 有边数限制的最短路 (bellman -ford 算法)

dijkstra 为什么不能解决解决负权边最短路问题加入每条边去松弛每个点到起点的距离dist[b] = min(dist[b], backup[a] + w);为什么需要back[a]数组避免一次更新了多条边把下一次迭代的事情提前做了为了避免如下的串联情况, 在边数限制为一条的情况下,节点3的距离应该是3,但是由于串联情况,利用本轮更新的节点2更新了节点3的距离,所以现在节点3的距离是2。正确做法是用上轮节点2更新的距离--无穷大,来更新节点...

2021-12-09 17:15:02 469

原创 Dijkstra求最短路

整体思路 :进行 n 次迭代 去确定每个点到起点的最小值 , 最后输出的终点即为我们要找的最短路的距离。dist [ n ] 用于储存每个点到起点的最短距离st [ n ] 用于在更新最短距离时 判断当前点的最短距离是否已经确定,是否需要更新每次迭代的过程中我们都先找到当前未确定的最短距离中 路径最短的点而于此同时该店的最短路径也已经确定, 然后将该点标记。st [ t ] = true;然后用这个点去更新其余未确定的点的最短距离。...

2021-12-09 15:34:38 109

原创 图的拓扑排序

算法流程:用队列来实现,初始化所有入度为 0 的点入队。主要由一下两部循环执行,直到不存在入度为 0 的顶点为止 1. 选择一个入度为 0 的点,并将它输出, 2. 删除图中从顶点连出的所有边。循环结束输出的定点数小于图中的顶点数,则表示该图中存在回路,即无法拓扑排序,否则,输出的就是拓扑排序(不唯一)#include<iostream>#include<cstring>#include<queue>#inc...

2021-12-09 11:12:24 609

原创 双指针算法

模板for(i=0,j=0;i<n;i++) { while (j < i && check(i, j)) j++; 每道题的具体逻辑; }可以先想出暴力做法,然后想出check函数check函数依据题意而定核心思想其实是for (int i = 0; i < n; i++) for (int j = 0; j < n; j++) O(n ^ 2) 将这个朴素的算法优化到O(...

2021-12-07 17:35:00 390

原创 数的重心 (化树为图)

给定一颗树,树中包含nn个结点(编号1∼n1∼n)和n−1n−1条无向边。请你找到树的重心,并输出将重心删除后,剩余各个连通块中点数的最大值。重心定义:重心是指树中的一个结点,如果将这个点删除后,剩余各个连通块中点数的最大值最小,那么这个节点被称为树的重心。输入格式第一行包含整数nn,表示树的结点数。接下来n−1n−1行,每行包含两个整数aa和bb,表示点aa和点bb之间存在一条边。输出格式输出一个整数mm,表示将重心删除后,剩余各个连通块中点数...

2021-12-07 17:15:25 75

原创 容斥原理。

容斥原理概况:用二进制表示状态的小技巧非常常用,后面的状态压缩DP也用到了这个技巧,因此一定要掌握。能被整除的数给定一个整数nn和mm个不同的质数p1,p2,…,pmp1,p2,…,pm。请你求出1∼n1∼n中能被p1,p2,…,pmp1,p2,…,pm中的至少一个数整除的整数有多少个。输入格式第一行包含整数nn和mm。第二行包含mm个质数。输出格式输出一个整数,表示满足条件的整数的个数。数据范围1≤m≤16...

2021-12-07 16:46:41 104

原创 区间合并 。

给定 nn 个区间 [lili,riri],要求合并所有有交集的区间。注意如果在端点处相交,也算有交集。输出合并完成后的区间个数。例如:[11,33] 和 [22,66] 可以合并为一个区间 [11,66] 。输入格式第一行包含整数nn。接下来nn行,每行包含两个整数ll和rr。输出格式共一行,包含一个整数,表示合并区间完成后的区间个数。数据范围1≤n≤1000001≤n≤1000001≤n≤1000001≤n≤100000,−109≤li≤ri≤109−109≤li≤.

2021-12-07 16:08:26 597

原创 离散化整 (区间和)

假定有一个无限长的数轴,数轴上每个坐标上的数都是 0。////现在,我们首先进行 n 次操作,每次操作将某一位置 x 上的数加 c。////接下来,进行 m 次询问,每个询问包含两个整数 l 和 r,你需要求出在区间[l, r] 之间的所有数的和。////输入格式//第一行包含两个整数 n 和 m。////接下来 n 行,每行包含两个整数 x 和 c。////再接下来 m 行,每行包含两个整数 l 和 r。////输出格式//共 m 行,每行输出一个询问中所求的区间内数字和。.

2021-12-07 15:52:10 87

原创 hash表

高精度数hash开放寻址法 :::只需开一个数组,相对简单,就像蹲坑找位置,hhh#include<iostream>using namespace std;开放寻址法,一般开数组大小 为数据范围的 2~3 倍,这样大概率就没有冲突了const int N = 2e5 + 3; 经验 : 大于数据范围的第一个质数const int null = 0x3f3f3f3f; 规定空指针为0x3f3f3f3f 避免与输入数据冲突i...

2021-12-07 14:59:29 376

原创 排序 (快排,归并排序)

快排模板 (以 j 为分界)快排属于分治算法, 分治算法都有三步 :1. 分成子问题2. 递归处理子问题3. 子问题合并代码段 : (注意,j 是分界线)void quick_sort(int q[], int l, int r){ 递归终止情况 if(l >= r) return; 第一步 : 分成子问题 int i = l - 1, j = r + 1, x = q[l + r >> 1]; while(i &lt

2021-12-07 14:00:38 354

原创 二分的模板

二分查找元素要求数组的有序性,或者拥有类似与有序的性质。本题要找到不小于该元素的最小位置和不大于该元素的最大位置, 两个界限,所以写两个二分查找不小于 x 的第一个位置, 代码如下:int l = 0, r = n - 1;while(l < r){ int mid = l + r >> 1; if(a[mid] < x) l = mid + 1; else r = mid;}查找第二个位置:int l = 0, .

2021-12-06 20:27:56 44

原创 模拟堆 的解释

如何理解模拟堆中的 heap_swap, hp[N],ph[N]?hp 是 heap pointer 的缩写 表示堆中下标到第 k 个插入的映射(存的是第几个插入)ph 是 pointer heap 的缩写 表示第 k 个插入到堆数组中的下标的映射(存的是数组下标)互为反函数简单理解,hp 就是 堆下标(heap数组下标) 指向 第几个插入(pointer) ph就是 第几个插入(pointer) 指向 堆下标(heap数组下标)注意: 堆的数据结构下标是不变的,...

2021-12-06 20:09:13 129

原创 auto 和 auto&

感谢空梦大佬让我学到新知识????for (auto& i : a) cin >> i; cin >> b; int result = 0; for (auto i : a) { if (b - i >= 0) { b -= i; result += i; } else break; }第一个auto 加了取址符,则可以通过 变量 i 来改变数组

2021-12-06 13:40:46 1858 1

原创 高精度加减乘除

总结 : 所有高精度加减乘除,都是按照其运算规律,利用工具人 t 模拟正常运算过程1. 高精度加法关键 : 工具人 t ,答案容器 c, 个位放前面, 大数加小数#include<iostream>#include<vector>using namespace std;const int N = 1e6 + 10;vector<int> add(vector<int>& a, vector<int>&amp..

2021-12-05 22:34:46 3845

原创 差分 , 前缀和

差分数组:首先给定一个原数组a:a[1], a[2], a[3],,,,,, a[n];然后我们构造一个数组b : b[1] ,b[2] , b[3],,,,,, b[i];使得 a[i] = b[1] + b[2 ]+ b[3] +,,,,,, + b[i]也就是说,a数组是b数组的前缀和数组,反过来我们把b数组叫做a数组的差分数组。换句话说,每一个a[i]都是b数组中从头开始的一段区间和。构建差分数组 :b[i] = a[i] - a[i - 1];一维差分总结 : 给.

2021-12-05 21:28:36 227

原创 并查集 ++ (连接块中点的数量)

原题链接:837. 连通块中点的数量 - AcWing题库1 . 初始化void init(){ for(int i = 1; i <= n; i++) { p[i] = i; p数组是祖宗数组, 初始时每个点的祖宗节点都是自己 size[i] = 1; }}2 . 找祖宗int find(int x){ if(p[x] == x) return x; else return p[x] = find.

2021-12-05 21:11:21 152

原创 并查集 (集合合并)

开始时,每个集合都是一个独立的集合,并且每个集合的祖宗节点都是等于自己本身的下标如 : p[5] = 5, p[3] = 3.如果是合并操作,只需要将两个集合其中一个祖宗节点作为共同的祖宗节点如 : p[3] = p[5] = 5;此时以 5 为祖宗节点的集合为{5,3}#include<iostream>using namespace std;const int N = 100010;int p[N]; // 定义多个集合int find(int x)

2021-12-05 16:51:54 438

原创 trie字符串统计

原题链接:835. Trie字符串统计 - AcWing题库不管是链表、trie树还是堆,他们的基本单元都是一个个节点连接构成的都可以成为一个由本身的值e 和指向下一个节点的指针 ne 构成的链式结构。 idx ++ 保障了不同的节点总是对应不同的idx值,因此可以用,idx将这两个属性联系起来。链表:链表会使用以下四件套:h, e[N] , ne[N], idx;h 表示头节点指针,一开始初始化指向 - 1, 每次插入的操作是 idx ++ 。单链表void.

2021-12-05 16:21:22 222

空空如也

空空如也

TA创建的收藏夹 TA关注的收藏夹

TA关注的人

提示
确定要删除当前文章?
取消 删除