自定义博客皮肤VIP专享

*博客头图:

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

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

博客底图:

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

栏目图:

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

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

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

原创 多维度线性DP及其记忆化搜索的转化 例题 GNYR04H - Mr Youngs Picture Permutations及动态规划状态转移的两种形式

这道题的重点在于多维度状态的转移。我们用a1a2a3a4a5表示每一行已经安排的学生人数,就是当前的状态。我们只关心此状态下的方案数,此状态可以推导出每一行在不超过限定人数和前一排的情况下的增加一人的方案数。这里值得注意的是:在动态规划的状态转移中有两种形式,一:如何计算出一种状态,即这种状态怎样有前一种推导 二:一个已知的状态应该更新哪些后续阶段的未知状态。前者更常见,但有时比如这道题后者更为适用。

2024-08-04 17:51:30 185

原创 2024 ICPC National Invitational Collegiate Programming Contest, Wuhan Site基础题K I B F E

当n%4==2时,序列为0001 0010 0011 ....... xx00 xx01 xx10,先手如果去xx10,则回到情况二,先手败,去0001,后手去xx10,此时0010 0011 xx00 xx10恰好异或和为0。这道题用二分写,具体不说了(主要不会)通过列举一些二进制数可以发现一个规律:0~3,4~7,8~11.....,以4为周期的二进制数的异或和为0,此时n可以分解成三个部分,0001 0010 0011 ....... xx00 xx01 xx10 xx11。

2024-07-21 10:27:43 1743

原创 字典树的两道经典例题:最大异或对 最长异或路径

根据异或的基本性质不难发现,x到y的异或和就是x到根节点的异或和异或y到根节点的异或和,求出所有节点的异或和,从高位插入字典树中,再从高位查询,和上道题一样,遇到不一样的就走。模板题,从最高位开始建立01字典树,查询时也从高位开始查,贪心思想遇到不一样的就走,没有就走一样的,就能保证走完的路径是这个数能组成的最大异或和。

2024-07-13 11:29:36 258

原创 字典树详解及对memset的思考

这里着重说一下空间的问题,首先trie数组第一维是点的数量,第二维则是字符的种类,由于这里的字符包括大小写字母和数字,而这些字符的ascll码是分散的,直接-‘0’使用会浪费很多空间使得超内存,这里需要做一下处理。还有每一组测试数据的初始化我都用了memset,memset的时间复杂度取决于你定义里面数组的空间大小,由于本题的空间先对较大,memset会超时。而精准的判断上一步用过哪些数组则省时的多。字典树是一种实现字符串快速检索的多叉树结构,trie的每个节点有若干个字符指针,这里可以理解成边。

2024-07-11 19:23:04 231

原创 离散化和map的相通之处及应用

电影语言字幕和人懂的语言的种类最多3*N,因此,我们可以将它们映射到1~3*N的实数范围内,先将N和2*M个数放入一个数组中,再将这个数组排序和去重。此后,它们将以排序去重后的次序代替原来的数据。我们在查找原来的数据是由1~2*N的哪一个数代替,只需二分即可。如果电影的语言对应的实数的范围不大,则可以开一个桶,依次扫描每个人会的语言,以语言的编号为数组的下标累加。用map更简便,只需开一个从int映射到int的map,key代表原人的语言,value代表这种语言懂的人数,查找时直接map数组查找即可。

2024-07-06 17:36:03 495

原创 离散化详解

离散化是排序算法的一个基本应用。离散化就是把无穷大集合中的若干元素映射到有限集合中以便统计的方法。有些时候问题的范围虽然是Z但是只涉及到m个有限值,并且数值的绝对大小无关,此时可以把整数集合中的m个数与1~m建立映射关系。原本时间空间复杂度与Z大小有关的算法就可以降为与m有关。此后,我们查找i(1<=i<=m)代替的数值只需返回b[i],查询a[j]被1~m哪个数替代只需再b数组中二分查找即可。

2024-07-05 18:45:36 173

原创 快速排序的讲解和排序算法时间复杂度的一个bug

我们现在一个序列(标号是l~r)中随机找一个基准元素,比如可以找序列中的第一个数a[l]记为x,然后扫描这个序列,遇到比x小的放入数组b中,和x一样大的放入数组c中,比x大的放入数组d中。因为我们每次基准元素找的都是第一个,那么b序列没有数,c序列只有一个数,d序列有n-1个,那么需要循环n-1次,每次平均扫描n>>1个数,时间复杂度退化到n*n。前者为O(n*n),后者O(nlongn)。第三类则是使用按按位划分,位映射的思想来排序,此时时间复杂度不仅和n的大小有关,还与元素的值的大小有关,局限性较大。

2024-07-05 18:03:14 288

原创 树上的差分详解及模板题 P3128 [USACO15DEC] Max Flow P

以本题为例,节点x和y之间所有的节点都增加1可以转换为节点x和y加1,x和y的公共祖先减2。相当于把x到y当成一个区间来操作,统计时只需算子树和即可。此题比较麻烦的是公共祖先节点要单独分类,在单独开一个数组记每个点当了几次公共祖先,统计时再加上这个值就可以了。树上的差分,顾名思义就是将原本数列的差分操作改成了树上节点和边的差分操作,利用到“差分序列的前缀和就是原序列”的重要性质将树上的操作简化。即区间操作转化为路径操作,前缀和转换为子树和。

2024-06-28 19:20:51 223

原创 P3379 【模板】最近公共祖先(LCA)的两种写法

回溯完它所有的子节点的时候(此时x标记为1)枚举所有要和x找公共祖先的点,判断这个点是否标记为2,如果为2,找到这个点所在集合的代表点,这个点即为x和y的公共祖先。做完这一切准备回溯x节点时别忘了把x节点标记成2。利用递推思想,f[y][j]=f[f[y][j-1]][j-1],即y往上走2^j的节点就是y往上走2^(j-1)到达的节点往上走2^(j-1)的节点,因为j从0-log(n)/log(2)的顺序循环,y的2^(j-1)的祖先上一步已经找到,这里可以理解为初始化f[y][0]=x的递推。

2024-06-28 15:38:25 181

原创 P8805 [蓝桥杯 2022 国 B] 机房

每个点的权值为这个点直接连接的点数,m次求x y两点之间的路径上所有点的权值和。如果直接深搜x y点的路径则时间复杂度的O(nm),超时。可考虑将x到y的路径转换为x到k和y到k (k=LCA(x,y))。建立前缀和,以根为原点,x和k的前缀和之差即为x到k上所有点(除k)的权值和,再加上y到k的前缀和之差,再加k点的权值即为答案。

2024-06-26 23:57:10 133

原创 P8773 蓝桥杯 2022 省A 选数异或

通过观察数据可以发现a[i]的值最大是2^20,很细节。我们可以建立一个数组b,b[i]=x xor a[i],在之后的数中一旦查到这个数和之前的b数组的某个值相等,即两个数可以组成异或对。现在问题是如何找到和a[i]相等的b的位置,注意到a的范围,可以用桶存b的位置,loc[b[i]]=i。f[i]表示[1,i]之间所有异或对中左边的数的位置的最大值,得到状态转移方程f[i]=max{f[i-1],loc[a[i]]}。我们很容易维护在每一个位置上的数的异或对的最大位置,记为loc[i]。

2024-06-26 17:00:56 247

原创 ST算法分析及代码

递推过程如下:将区间[i,i+2^j-1]分成两个已知区间[i,i+2^(j-1)-1]和[i+2^(j-1),i+2^j-1]表示为f[i][j-1],f[i+(1<<(j-1))][j-1]。二:查询,给出l和r后确定一个k,使2的k次幂小于区间长度的前提下最大,那么从l开始的2^k个数和以k结尾的k个数,这两段一定覆盖了整个区间,这两段的最大值为f[l][k],f[r-(1<<k)+1][k]。相比于线段树和树状数组的优势在于只需经过O(nlogn)的预处理即可实现O(1)在线的查询l-r的最值。

2024-06-24 23:35:46 133

原创 P1099树网的核(六种解法,全网首发)

我们一一验证,首先找到距离直径两端不超过mid的两点作为核的端点,验证核的长度是否超过s和核中是否有点所到达的最长长度超过mid,都满足此时mid合法,再二分变小,直至找出最小值。已知树的核在最特殊的情况下可以缩成一个点,这个点必然是树的直径上最靠近中点的点。向左或者右拓展的目的是减少此时的最大的偏心距,记现在部分核的的端点为i j,直径的端点为1 k,p为i到j之间的点的d的最大值,判断dis(i,1),dis(j,k)大小,大的和p比较,如果小于等于p则没有继续拓展的必要,直接输出。

2024-06-24 16:32:50 704

原创 P1886滑动窗口

让你寻找区间K内的极值(不妨设极小值),建立一个队列p为单调队列,存K区间内有可能作为答案的数,队列q存对应队列p的编号。当新加入一个数,判断和队首的编号是否超过k,若超过,则弹出队首元素。此时由于找极小值,若此元素比队尾的小,则队尾的元素不再具有价值,因为当前区间不可能选它,之后新加入数也不会选,因此把队尾所有大于等于新加入元素的元素弹出,这就叫做及时排除一定不是最优解的选择。单调队列顾名思义,要建立一个队列,并且使这个队列单调,建立单调队列的目是及时排除一定不是最优解的情况。

2024-06-19 22:10:00 208

原创 树的直径的几条定理/引理/结论

1.如果一棵树存在多条直径,则树上必存在一点 p,使得所有直径均经过该点(简单来说,所有直径必交于至少一点)。4.直径的重边的端点到非重叠部分的端点的边长(不经过重边)都相等。2.多条直径的中点(不一定为整点,可能在边上)为同一点。3.如果存在多条直径,则两两的重边都相同。

2024-06-13 22:31:44 114

原创 P3304直径

证明所有的直径必相交且两两重边都相同。逆向思维,假设已经存在一条直径,如果存在第二条测满足以下:设重边的两个端点为j,k 直径的两个端点为m,n 若存在直径外两点u,v 使得d(m,j)=d(u,j)并且d(n,k)=d(v,k) 此时u-v为第二条直径。我们找重边只需在第一条直径的每个点找不经过直径且以这个点为端点的最长链和这个点到直径左或右端点的距离。如果两者相等则这个点为总重边的左或右端点。(代码很长需要耐心)求一棵树中所有直径都经过的边的个数。

2024-06-13 21:44:36 203

原创 P3629巡逻

当加两条新路,会形成两个小环,情况一没有重叠边,找第二长的边。情况二有重叠边,原本一条边都不加此重叠边走两遍,加了一条新路重叠边走的次数减少一遍,只走一遍,加两条新路重叠边走的次数减少两遍,一遍不走。此时,重叠的边不得不走两遍。答案为2*(n-1)-L1+1-L2+1+2*L=2*n-L1-L2+L*2(L为重叠的边长)。重叠的边长因选择的第二条直径的变化而变化,很难求解,故我们选择一种巧妙地方法:将-L2+L*2写成-(L2-L*2)。将第一条直径经过的边长改为-1,此时求出的直径长即为L2-L*2。

2024-06-12 22:34:35 195

原创 P2195 HXY造公园

因为合并后的树的直径一定大于等于原树的直径,如果存在大于原树的直径的链,那么这条链一定过合并的那条边通向原本另一个树。这时只需让这条链在原树的部分的最大值最小,故链的起点一定在直径的中点。合并后只需使用路径压缩法,使树A的根的父亲指向树B的根节点,树B的根节点的直径数组改为max{两棵树直径的一半(向上取整)的和+1,原本两棵树的直径}即可,此时无论查找树A还是树B都可以返回合并后的树的直径。值得注意的是,本题需要多次查找树的直径,可使用某点所在树的根节点的直径表示,记为数组c[x]。

2024-06-10 20:24:00 283

原创 P4047部落划分

分析题意可知本题是用kruskal算法求解最小生成树的一部分,即求解k的树组成的最小生成森林,判断边数达到n-k-1即可。

2024-06-04 20:18:30 107

原创 P1265公路管理

还要注意如果坐标用int类型,则经过两点距离公式计算过后的答案即使用double类型依然会出错,为避免这种情况,建议坐标直接定义为double。prim以点为核心延展边,时间复杂度n*n,适用于稠密图,尤其是完全图。kruskal以边为核心,时间复杂度为mlogm,适用于稀疏图。证明不可能出现环状,故本题为最小生成树模板。关键在于本体的图为完全图,点数少,边数多。

2024-06-04 20:06:20 101

原创 P1340 兽径管理

若有公共祖先,则在之前添加的边找一次最小生成树(一定把之前的父子关系清零),此时边数一定和上一次相同,依旧边数=n-1输出答案。思路:若新提供的两点未有公共祖先,则可直接连,答案累加,边数加一。若边数为n-1则输出答案。之后直接相连的情况用到的森林结构一定是最近一次新生成最小生成树的森林结构。

2024-06-03 22:12:44 116

原创 关于二分答案

我们要二分的就是牛之间的最大距离。这里我才用的是l

2023-10-21 20:56:39 43 1

空空如也

空空如也

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

TA关注的人

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