- 博客(62)
- 收藏
- 关注
原创 博弈问题----下
求出所有状态的sg值,发现只有石子的数量是(m+1)的整数倍时sg的值才为0,这样也可以得到bash博弈的结论。打表发现每个(a,b)sg值是(a-1) | ((b-1) 中最低位0在哪一位。把每个糖豆看成一个独立的游戏(将数组倒置求解,更符合sg的定义)n堆石子相当于有n个子游戏,异或值就是总的sg值。
2026-05-16 20:41:44
60
原创 倍增算法和ST表
建立几个预处理机构:根据数组是有序的,把相同的数字分到一个桶里,统计每个桶里有多少个数字,每个桶的下标范围,每个下标对应的桶的编号。例如,求下表6~26出现次数最多的数字的个数,首先找到6的桶的编号2,2号桶的下标范围右边界到7,所以有2个2;17-37长度为21,最接近21的2的幂是4,先求出17—32(17+16-1)的最大值,然后求22(37-16+1)—37的最大值,两者取最大就是最大值;1.建立关于最大值或最小值的st表,表示从i位置起(包含i位置)向右2^p范围上的最大值是多少。
2026-05-12 19:30:09
221
原创 欧 拉 路 径
因为这是个欧拉回路,所以你最后一定是到达了start(全为0的情况)才收集的最后一个边权,所以最后n-1位一定是n-1个0,只需要去掉最后n-1个0,循环利用到start(n-1个0),就是答案。从最小的点,先遍历权值最小的边跑一边希尔霍尔策算法,收集每个点来的那条边的边权,倒叙收集的序列,把第一个边权-1改为start,得到就是最短长度(德布罗意序列)2.如果题目要求字典序最小,那就先将每个点的边集按照通往点的序号排序,先处理通往点的序号小的边,就会得到字典序最小的结果。,大幅减少 DFS 的冗余遍历。
2026-05-06 19:14:43
392
原创 树 套 树
1.定义两个维度的线段树,x维度(外层线段树)表示身高来范围,每个外层线段树的每个节点中有一个完整的以活泼度维护缘分值的线段树(y维度)2.对于加入操作:将外层数字范围包含jobv的节点的内部的线段树 [ l , r ]加1(内部线段树维护数字个数)2.对于修改操作,只要身高的在来到的节点的范围内,就修改其内部的y维度活泼度的线段树(就是单点修改线段树)3对于查询操作:只要来到的范围被全包,就查询其内部的y维度的活泼度的线段树在给定的活泼度的范围内的最大值。引入 题目1 (线段树套线段树)
2026-01-17 14:50:45
168
原创 线段树和扫描线结合
后面扫到的位置同样方法处理,用10-70的覆盖长度乘以此时的边界和上个边界的距离,然后左边界有加1,右边界就减1。遍历查询的数,相当于有一根扫描线扫过区间,只要大于开头,就放到小根堆里;离散化后,如果一个矩形边界为离散化的编号为x~y,那就在x~y-1这段线段上加1或减1。因为线段树上x~y的总长度就等于离散化后的编号(y+1)对应的原坐标减x对应的原坐标。2.先建立一个按照区间大小的排序的小根堆,并且带有其过期的位置。2.以上面的例题为例,按左边界增1,有边界减1,得到6个事件。1.开区间处理边界问题。
2025-12-04 22:58:42
282
原创 博弈问题---上
解析:比如n%(m+1)==0,我先手拿a个(a<m+1),那我后手就拿(m+1-a),那石堆的最后一部分一定是后手拿掉的;如果不等于0,先手就先拿一部分使石子的数量变为(m+1)的整数倍,这样先手和后手就变换顺序了,先手相当于后手,后手先当与先手,根据上面那种情况的分析,那就是先手(转换后的后手)先赢。所以如果n%6==0,那么先手拿完后剩下的数量一定不是6的整数倍,那么后手就把剩下的石子拿成6的整数倍,最后一定是后手最先拿完石子;解析:如果石子数量的异或和不为0,那么总有方法使石堆的数量异或和为0;
2025-10-29 18:27:52
435
原创 树 的 重 心
但现在带有点权,d就是重心,也就是说,对于点权数,每个子树的大小是根节点子树的大小加根节点的点权。第6条性质:将第一棵树的 f 和第二棵树的 a 连接起来,那么连接后的树的重心在 p-d-f-a-c-p 这条路径上。2.对于两个重心的树,两个重心一定是互为最大子树的。如果再删掉e,c就是重心,相当于p重心移动到c了。根据第二条性质求重心(也可以用第一条,上一题也可以用第二条性质求重心,只是为了将两种代码的实现都演示一遍)2.由重心拓展性质可知,只有求出带点权的树的重心,所有牛到重心的距离就是最小的。
2025-10-17 16:59:04
401
原创 换 根 dp
1.首先 dfs1 得到每个节点子树的节点个数,然后得到dp[1](以1节点为根的答案),dp[子]=dp[父] - size[子] + n - size[子] 得到其相邻子节点的答案。2.假设以u为根节点的收益是dp[u],如果以v为根节点,对于以u为根,r染色v时收益增加n-size[v];2.设置sum数组:固定某个节点为根节点(比如下图以1为根节点),各节点到其子树所有节点的距离和,得到sum[1],就是dp[1]用下题引入换根dp:简而言之换根dp就是通过父节点的答案得到相邻子节点的答案。
2025-10-08 09:39:46
403
原创 树上倍增和LCA算法---上
树上倍增: 建立deep和st数组,就可以求出从一个节点往上走s步来到的节点。比如求从16走3步来到的节点,16走3步来到第3层,首先枚举走4步(8步及更多的步数没必要枚举,因为16所在第6层都不足8步),查st表来到2节点,在第2层,所以不要;然后走2步,到第4层的10,所以走到10节点;查询过程:比如要查询a和b的最近公共祖先,先让深度大的节点走到深度小的节点的深度,就是让a走到第37层,然后同时走64步,发现都到达-1这个节点,所以不要;然后走32步,到达第5层的同一个节点,不要;
2025-09-29 10:32:11
219
原创 有序表专题2---跳表
的比如查询key=35,从第4层开始,右一个节点100大于35,所以向下走到第三层;比如加入key=30,分配到6空间编号,所以key[6]=30,count[6]=1,level[6]=4(level为随机到的指针数量),next[6]([1]~[4])表示指针指向的下一个节点,len表示每个指针跨过的节点数量。调整len数组:比如加入key=160,来到第3层时加入160,但len数组说没办法调整的,所以需要递归到下层返回"从当前节点到最底层加入key时最底层有几个小于key的节点",然后调整len。
2025-09-28 11:30:08
335
原创 artificial intelligence 1
无监督学习:不会给你正确的类别,自己先将相似的数据划为3类,然后加入新数据时归到最相似的类别中。监督式学习:提前给你正确的类别,如果再给你一些数据,自己归到某一类别数据中。半监督学习:相比较监督学习给的标签较少,但也能自动归类。
2025-04-23 15:22:40
270
原创 Gauss消元---加法方程组
解方程的流程:遍历对角线,选出所剩的列中绝对值最大数所在的那一行(溢出风险小),换到当前行所在的位置并变为1,然后将这一列其余所有值全部减为0。如果对角线上没有凑齐全部的1(主元),并且对角线0(自由元)对应的最后一列的值为0,那么这种情况就是多解的情况。自由元就是在一列中做选择时,没有非0的行,所以整个一列都为0,就不会影响其他的自由元。首先补的自由元对应的最后一列为0,其余的为主元且对应的最后一列的值不为0。无解:如果自由元对应的最后一列的值不为0,那么这就是无解的情况。主元:对角线上为1的元。
2024-11-17 19:54:43
1037
1
原创 开点线段树、区间最值和历史最值
由于修改操作为特殊性:将一段区域所有的值都改为1,这个操作是一次性的,如果下一次还修改这段区域的值,相当于没有操作;3.空间估计:一次操作最差的情况就是从顶点节点沿两条边界线一直扎到末尾,所以每一次增加操作开辟2*logn空间,一共m次操作,所以大致开辟2*m*logn。1.如果子区间的最大值和父区间的最大值相同,就把maxadd、otheradd、maxaddtop、otheraddtop一起向下传递。增加操作:如果一段区域增加某一值,他所产生的标签数量就是logn,所以增加的势能就是(logn)^2。
2024-09-01 09:31:31
586
原创 线段树解决区间合并类问题
1.为了执行翻转操作,不仅需要记录1的连续最长字串长度、前缀长度、后缀长度,还需要记录0的连续最长字串长度、前缀长度、后缀长度。此题查询操作较为特殊:查询时,要求返回字典序较小的编号,所以要从左区域到中间区域到右区域查询,只要有满足条件的就返回。如果只维持一段区间连续1的最长字串长度是无法被线段树维护的:所以可以增加信息来共同维护。1.维护三个信息:连续1的最长字串长度、连续1的最长前缀长度、连续1的最长后缀长度。1.此题由于查询操作的特殊性不需要记录区域的最长连续字串。
2024-08-31 09:26:18
719
原创 线段树维护更多类型的信息
所以此题维护的是一段区域内以某种地雷开头的位置数量和以某种地雷结尾的位置的数量两种信息。那么求一段区域 l - r 内地雷的总数,从1 - r地雷的开头数减去1 - l-1地雷的结尾数就是地雷的种类数。如果知道一组数的差分数组,在原数组的l - r范围上增加首项为k,公差为d的等差数组,只需要在l上增加k,l+1到r上增加d,r+1减去末项,从1到p求和即可得出原数组操作后p位置上的数。若求平均数和方差,只需要维护好累加和数组和平方和数组即可:累加和和平方和都可以成为线段树的维护信息。
2024-08-31 09:26:06
458
原创 线段树离散化、二分搜索、特别修改
而将一个节点开到1,需要遍历6*树高的规模,所以1-n的线段树总势能为n*6*logn,因为有剪枝,所以这就是遍历到的规模。2.方块a落在1--3点,b落在3--4点,如果直接按照落点修改,查询3时位置会认为两方块重叠,但其实没有累到一起,所以方块落点的区域设置为左闭右开就可以避免这个问题。2.当一段范围的最大值为1时,此时就不需要执行开平发操作了,所以就可以剪枝了(此处的剪枝不是简单的优化常数时间,他减少了遍历规模)1.如果直接按照原落点的值构造线段树,空间开辟会过大,所以收集所有出现过的点进行离散化。
2024-08-31 09:25:42
389
原创 线段树的原理
范围修改logn的前提:如果维护的是区域和,要把区域上的每个数字加上a,只需要知道区域中数字的个数乘以a加到原数字和上就可以得到新的和,时间复杂度为O(1),那么这样的修改复杂度就是logn;如果是将区域上的每个数数位上的数字都倒置得到新的数字,那么这样是无法直接得到新的累加和的,这样的修改操作就不是logn。2.如果父节点既有add信息又有update信息,我们知道,如果有update操作,就会把add信息取消,所以update信息一定早于add信息,所以先传递update信息,在传递add信息。
2024-08-23 20:19:54
608
原创 树 状 数 组(数组离散化技巧)
可差分信息:如果知道部分的信息,用整体的信息和部分的信息就可以求出剩余部分的信息,那么这个信息是可差分的。维护其差分数组作为树状数组:这样范围增加相等于差分数组的单点增加;单点查询就可以用前缀和的方式求出。A1到Ak的所有数值的累加和可以通过差分分解为下述的表达式。从(1,1)到(n,m)的和经过推到得到下述的关系式。
2024-08-17 16:09:25
317
原创 Manacher算法、扩展Kmp
从第一个字符开始枚举间隔k长度的字符是否和原字符串的前缀完全相同:如果相同,那么跳过几个间隔就花费几秒;如果到字符串最后还没匹配上,那么字符串的总长度除以向上取整就是花费的时间。解决:在每两个字符之间及字符串的左右两头都插上任意字符(扩展串),然后枚举每个点向左右两边扩展,得到的扩展半径-1就是回文串长度。z数组:一个字符串从每个位置开始的字串和原字符串开头匹配上的最长公共前缀长度。e数组:字符串a的每一个位置和字符串b的开头匹配上的最长公共前缀长度。求一段字符串中的最长回文字符串。
2024-08-14 15:26:51
309
原创 AC自动机
遍历文章时的词频传递:遍历文章时,如果有对应的路径对应的节点就加1;如果没有就根据直去表对应的节点跳转。遍历完后建立每个节点和其fail指针的反图9(建立好后就是一棵树),遍历整颗树汇集每个子树的词频加到其父节点上,每个敏感词结尾的节点在收集到的次数就是对应敏感词出现的次数。设置times数组记录各节点的频率,遍历文章,只要有下一级节点,下一级节点和其fail指针不停跳转直至0节点路途中所有的节点全部加1;如果有下级节点,从表中根据fail指针所指向节点的对应的路径的下级节点设置其fail指针;
2024-08-13 22:44:26
593
1
原创 Kmp 算法
在匹配的过程中,只要发现目标串,就应该去除,且去除后的剩余字符串拼接后和目标串对比,所以要使用一种合适结构处理——栈:只要发现匹配出目标串就弹出栈,且通过栈找到下一个位置。时间复杂度为:O(n+m),n和m分别为两个字符串的长度。求解s1中1个位置的对比过程均摊的时间复杂度为O(1)如果有evil这个条件,就在枚举的时候通过next数组对比调整,如果之前选的字母和evil字符串配对了,就返回0。将链表的数字拿出形成一个数组,然后遍历树和数组对应,如果对应不上就通过nex数组调整。时间复杂度为O(n*m);
2024-08-11 18:47:19
543
原创 质数判断、质因子分解、质数筛
如果只要质数的个数,而不需要哪些是质数,欧式筛可以优化:预估出质数的大体个数,然后去掉其中的合数。对于c++,因为此题有乘法取余的过程,所以long类型也可能超,所以定义 ll 为128 位。求出分解各数的质因子,有相同的质因子就用并查集合并,最后求出最大的并查集即可。判断较大的数是否为质数:Miller-Rabin测试。时间复杂度为O(n^1/2)
2024-08-11 18:46:52
478
原创 快速幂、矩阵快速幂
通过递推关系可知,每项至于前一项有关,且每一项的维度有多个,所以此时可以根据递推关系写出关系表达式,然后按照k阶1维的方法求出答案矩阵。1.固定关系的1维k阶表达式(即某一项只有一个维度,是由前好几项推出的,且递推关系式是固定的),时间复杂度为O(logn*k^3)。对于a^b,把b看作二进制形式,让a从1次方开始,只要b的二进制形式某位上有1,就把此时的a加入(a不断的自乘的幂就对应二进制的每一位)。注:对于方阵幂的次数,从0项开始,求第n项,且递推表达式维度为k维,则幂的次数为(n-(k-1))
2024-08-11 18:46:40
455
原创 动态规划根据数据量猜解法
所以此题要利用好给定数 组的特殊性,给一个数组表号下标,给另一个数组写出对应的下标序列a,求a的最长上升子序列就是两个数组的最长公共子序列。如果用动态规划做,设置dp[i][j][k]表示从i开始只能挑j个,还剩k大小的和,是否可以完成。dp[i][j]表示通过前i个怪兽且花费的钱不超过j所能获得的最大能力值。// 给定一个正数k,表示要从1~n中选择k个数字组成集合A,剩下数字组成集合B。a[i]表示怪兽的能力值,b[i]表示每个怪兽的花费。1.如果怪兽的能力范围很大,而花费的钱范围较小。
2024-08-11 18:46:24
494
原创 数 位 DP
求在a-b之间的windy数,可以先写函数f求出0-i之间的windy数,然后f(b)-f(a-1)就是答案。free表示此时是否可以随意选,pre表示前一个数,如果pre为10,则前面没有数;然后不停的分类讨论即可。可以先求出1-i的非萌数。萌数是具有回文性质的数,所以非萌数的所有位上的数一定跟前一个和前前一个数一定不同。pre表示前一个数,prepre表示前前一个数,free表示是否可以自由选择。如果有len二进制位可以任意填写,有多少个非连续二进制1的数:就等于len-1位和len-2位的和。
2024-08-03 18:08:25
492
原创 动态规划---观察优化枚举(股票系列问题)
从0 - i上的最大利润:在i天的时候卖,需要0-i上的最小值;不在i上卖,则需要0 - i-1天上的最大利润,比较即可。手续费无非是在卖出的时候多出一笔钱,所以和无限次购买股票是一样的。dp[i][j]表示从0-j天最多买卖i次所能获得的最大收益。只要两天之间的差值为正数,即有利润,就购买;按照结束时间从小到大排序,才不会错过最大的利益。
2024-08-02 20:33:36
475
原创 状 压 DP
/ 返回当前的先手能不能赢,能赢返回true,不能赢返回false。// 数字范围1~n,当前的先手,面对status给定的数字状态。// s : n个人,谁没满足状态就是0,谁满足了状态就是1。// m : 帽子颜色的最大值, 1 ~ m。// n : 人的数量,0 ~ n-1。// 在累加和还剩rest的情况下。// i : 来到了什么颜色的帽子。// dp : 记忆化搜索的表。// 返回 : 有多少种方法。
2024-07-31 17:31:07
349
原创 树 形 DP (dnf序)
求一个子树所有边的经过次数之和,需要其子树的所有经过边之和,还有每个子树的节点与其子树上的硬币数量,做差的绝对值就是从头节点的子树到头节点之间的那条边经过的次数。求target的路径,如果知道之前遍历过的所有的节点之和,和之前所有从根节点到遍历过的节点的的路径和的路径个数,求出sum-target的路径个数累加即可。求到达头节点a的最少油量,需要其子树的最少油量,还需要到达其子树的头节点的人的个数,人数对seats求上限加子树的油量就是到达a的最少油量。如果选a,需要子树的头节点向下延申的最大长度。
2024-07-30 10:00:14
575
原创 区 间 DP
先写递归区间l到r内变成回文的最小次数,然后将递归改为动态规划。写递归:从l到r先手玩家所能获得的最大数值,然后改写为动态规划。在区间内进行划分dp。
2024-07-27 17:12:56
271
原创 分组背包、完全背包
每一组的物品都可能性展开就可以,时间复杂度为O(物品的数量*背包的容量)完全背包:每种商品可以选取无限次。时间复杂度为(物品数量*背包容量)把每个栈中取出硬币的情况装到一个数组中,展开讨论即可。分组背包:多个物品分组,每组只能取1件。
2024-07-26 18:12:26
256
原创 0-1背包、有依赖的背包
总优惠金额>=超过预算的金额就是快乐的,那么对于优惠金额大于出售金额的单个物品是必须要选的,并且相差的金额加到原有的预算上就是"心理上"拥有的预算;而对于差值小于0的物品加入待定物品的数组。设置king数组记录物品是否为主物品,fans数组记录主物品的附属物品的数量,follows二维数组记录主物品下附属品的编号。2.优先级队列:在数组中元素全部为非负数的情况下,先将数组从小到大排序,可以先加入数值最小的数a,然后将其弹出,将其排序后数组右边的数b及a+b加入到小根堆里直至弹出的数量到k。
2024-07-26 13:27:20
396
原创 最长递增子序列问题
ends记录遍历过的各子序列长度的最小结尾元素,例如ends[i]表示i+1长度的子序列的最小结尾元素。首先将信封按长从小到大排序,长相等的信封按宽的大小从大到小排序,然后求宽排列后的数组的最长子序列。枚举每k间距的数组,求出其最长的不降序的子序列长度,数组长度-最长长度累加求和就是最少的操作次数。ends数组加入数对的最后一个元素,查询的时候用数对的第一个元素查询。ends数组的加入和查询的数据可以是分离的,下面两题就用到了此技巧。两侧循环进行状态转移。
2024-07-25 18:21:32
275
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人
RSS订阅