![](https://img-blog.csdnimg.cn/20201014180756780.png?x-oss-process=image/resize,m_fixed,h_64,w_64)
算法竞赛进阶指南题解
文章平均质量分 57
CUCKyrie
中国传媒大学智能媒体计算实验室IMC研究生
展开
-
线段树整理
文章目录线段树整理题解部分HDU-1394HDU-2795POJ-2828POJ-2886HDU-1698POJ-2528线段树整理最近搞线段树上瘾。总结一下这一次遇到的一些题型:纯板子题目(区间操作)线段树求逆序对数线段树带遍历优先级线段树 + 反素数 + 约瑟夫环线段树 + 离散化插队问题线段树的染色问题(Lazy标记的理解)这里把做题过程中遇到的一些经典题目和对应思路解法记录一下。题解部分HDU-1394题意:给定一个序列ai{a_i}ai为一排列,现在按照某种方式原创 2021-09-12 10:17:57 · 110 阅读 · 0 评论 -
LuoGu P1197 星球大战
并查集 + 逆向思维题解:直接看题的话其实没有什么很好的思路,直接正向删除节点维护的话,时间复杂度必然爆炸…所以这个题目可以逆向考虑:我们假设现在有kkk个点是坏的,我们去修这kkk个点,每修一个点就统计一次整张图的联通块数目。所以先假设每一个点都是独立的,也就是total=n−ktotal = n - ktotal=n−k。之后每加入一个点都统计一次连通块的数目,解决两个点之间的联通性问题我们可以用并查集维护。#include <bits/stdc++.h>#define ill原创 2021-08-08 21:53:01 · 69 阅读 · 0 评论 -
BZOJ4195 程序自动分析
离散化 + 并查集题解:首先因为不等式并不具有传递关系,或者说冲突的情况只能是不等式和等式的冲突。我们先把所有的等式归于一类,然后逐个判断不等关系是否可以存在即可。这里需要注意,数据范围达到了1e91e91e9,一般的数组是开不下的,同时如果用mapmapmap肯定会超时,那就需要考虑离散化,把1→1e91\to 1e91→1e9的数据映射到1→2e51\to 2e51→2e5上,结合并查集即可。#include <bits/stdc++.h>#define ill __int128原创 2021-08-08 14:05:02 · 91 阅读 · 0 评论 -
AcWing 165 小猫爬山
题解:复习一下DFSDFSDFS,考虑到后面的图论和数据结构好多都是需要搜索的,所以这里再巩固一下,毕竟自己的搜索实在是一言难尽QAQ。带有回溯(还原现场)类型的题目,其实关键就是确定搜索边界+搜索的方法,这个题目的边界肯定是全部的猫都被放到了车上,然后我们的搜索方法是:当前对于编号为nownownow的猫:尝试把他放在第iii个车上,1≤i≤cnt1 \leq i \leq cnt1≤i≤cnt,cntcntcnt为当前我们租的车数目。如果放的下,我们就递归dfs(now+1,cnt)dfs(no原创 2021-08-04 21:01:53 · 80 阅读 · 0 评论 -
AcWing 164可达性统计
拓扑排序+STL(bitset)STL(bitset)STL(bitset)题解:我们假设从节点iii出发,可以达到的点集为S=s1,......snS = {s_1,......s_n}S=s1,......sn,那么我们要求节点iii可达的点数,其实就是SSS中所有点可达的点数之和,表示为:f(i)=∑i=1nf(si)f(i) = \sum_{i = 1} ^ nf(s_i)f(i)=∑i=1nf(si)其中f(i)f(i)f(i)为从iii出发可以到达的总点数。既然设计到到达顺序的问题原创 2021-08-04 20:08:13 · 121 阅读 · 0 评论 -
AcWing 160T
题解:就离谱的很的KMPKMPKMP之前写的159使用了KMPKMPKMP一个小拓展,直接对字符串数组进行模式匹配。这个更考验理解能力QAQ为啥这么说呢,就是整个KMPKMPKMP模式匹配从求解NextNextNext数组到求解FFF数组进行匹配,整个过程要求你必须了如指掌而且清楚每一步的操作原理。所以我就没了TAT这里我们首先对BBB字符串进行自我匹配求出NextNextNext数组,然后让他和AAA字符串进行匹配,我们发现求解过程中的这一步:for (int i = 1, j = 0;i原创 2021-07-30 11:01:18 · 71 阅读 · 0 评论 -
AcWing159T
好久没看的KMPKMPKMP题解:这个题一开始的思路是想看每一行的最短不整除循环节然后求一个lcmlcmlcm,但是最后被自己的数据Hack了…后来看了一下题解发现还可以直接对字符串数组进行KMPKMPKMP,原理其实是一样的,不过可以更快得确定完全覆盖需要得最小行数和最小列数。很妙的思路#include <bits/stdc++.h>#define ill __int128#define ll long long#define PII pair <ll,ll>#原创 2021-07-29 20:29:41 · 82 阅读 · 0 评论 -
AcWing 157 & 158
两个题目分别是考察的树的最小表示(157)和字符串的最小表示(158)。字符串的最小表示对于一个字符串SSS,有众多的循环同构串,所谓最小表示就是这些循环同构串中字典序最小的那个串。我们可以采用一个O(n)O(n)O(n)的算法求解出长度为nnn的字符串的最小表示。int n = strlen(s);int k = 0,j = 1,i = 0;while (i < n && j < n && k < n) { if (s[(i + k) % n]原创 2021-07-28 15:54:06 · 89 阅读 · 0 评论 -
Ac.wing 149. 荷马史诗
追逐影子的人,自己就是影子。 ——荷马写在前面纯粹是因为自己喜欢哈哈哈哈题解:我们需要让这个替换后的字符串总长度最小,同时要求在保持最小字符串长度的前提下,我们尽可能让最长的字符串最短。所以我们贪心一下很容易想到:如果要总的字符串长度最短,我们就让数量最大的单词长度最短就可以了,我们就把这个数量理解为Huffman的权值,把长度理解为Huffman中节点距离根的深度,这样就转换成了一个Huffman问题,同时我们把节点据根的深度表现在根到节点的路径上,这样就是使用了Trie树的原理。如何让最长的字原创 2021-03-07 23:48:16 · 146 阅读 · 0 评论 -
Ac.Wing 142.前缀统计
题解:问加入的字符串中有多少是当前给出的字符串的前缀子串,那么我们就可以对每一个加入的字符串建立Trie树,然后只需要把最后的End数组改一下意义就可以,因为统计的是前缀数目,那我们就把每一个作为结尾的节点数目记录一下,然后当我们发现这个节点是作为结尾的时候,让ans进行一次累加即可AC代码:#include<iostream>#include<cstring>#include<cstdio>#include<cmath>#include<原创 2021-01-21 16:45:59 · 85 阅读 · 0 评论 -
Ac.wing 140 后缀数组
题解:理论上后缀数组的求解要使用倍增orDC3算法来求解,但是这显然超出了我的水平范围不符合题目的要求。所以我们就正大光明得使用Hash + Sort来做。题目比较难处理的点在于,我们对于两个后缀字符串的比较,因为比较的最坏时间复杂度为O(n)O(n)O(n),但是我们快排就已经有了O(nlogN)O(nlog{N})O(nlogN)的复杂度,显然对于3e5的数据肯定会超时,那我们应该怎么去处理呢?其实和之前的题目相似,我们使用二分答案的方法做,我们二分得出两个后缀字符串重合的最大长度,然后去找下一位比原创 2021-01-18 17:46:19 · 81 阅读 · 0 评论 -
Ac.Wing 139. 回文子串的最大长度
题解:这个题目如果单独拿出来就是一道裸的Manacher算法,但是这里希望我们强化一下Hash算法,所以我就写了两个版本的。Manacher:#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#include<cmath>#include<vector>#include<map>#include<stack&g原创 2021-01-18 11:27:33 · 117 阅读 · 0 评论 -
Ac.Wing 137 雪花雪花雪花
题解:这个题目应该说是一个比较常规的Hash但是自己太菜了写的好乱QAQ理一下Hash的思路叭:首先需要定义一个Hash函数,用来对数据进行离散化操作,然后结合链表去储存数据,一般使用邻接表比较多。理想的一个Hash表可以把算法时间复杂度优化到O(1)O(1)O(1),建立Hash函数后我们随即建表,邻接表的表头储存的就是数据的“特征值”,每一个特征值下存着对应的数据链表,这样子我们在查找的时候就可以直接通过特征值找元素了。那么对于这个题目,我们首先确定Hash函数:对于两个相同的六元组,他们的元素原创 2021-01-14 17:19:01 · 78 阅读 · 0 评论 -
Ac.Wing 106 动态中位数(Offline)
题解:这个题目和之前的邻值查找问题很相似,这个题关键就是在于弄清楚链表中中位数到底是如何变化的。我们简单分析一下这个题目:动态取值,动态取出中位数,Online做法是使用大小堆,但是这里因为刚学了链表其实是不会大小堆orz我们就用Offline的方法写了。首先我们把所有的数据加入链表并排序,记录一下他们在原链表中的位置和现在的位置,我们仍然是和136题一样采用从后取值的方式,对于第n个数据,答案肯定是a[(n+1)/2]a[(n + 1 ) / 2]a[(n+1)/2],我们知道它只有在链表长度为奇原创 2021-01-14 11:43:32 · 172 阅读 · 0 评论 -
Ac.Wing 136 邻值查找
题解:这个题目是有两种写法的,y总在视频里只讲了list的写法,这里我们也用STL set写了一个。先说一下两种写法的思路:链表写法(OffLine)其实不管是使用链表存储还是set存储,算法的核心就是找到每一个点的前驱和后继节点,然后通过比较这两个节点和选定值差的大小关系决定使用哪一个作为最后的答案。我们假设把所有数据存入链表后进行排序,同时用一个数组记录排序后的元素在原链表中的位置是多少,我们从n开始,找每一个节点的前后驱节点,比较后存入一个记录答案集合中,然后把这个节点删除,继续找下一个节点原创 2021-01-13 09:35:43 · 122 阅读 · 0 评论 -
Ac.Wing 135最大子序和 + 131最大子矩阵
关于单调队列/栈的总结其实之前看过蓝书上的单调队列/栈的解释,但是还是感觉懵懵懂懂得,今天趁着做这个题目把单调队列和栈写个小总结。首先单调队列和单调栈都是为了实现在决策队列中及时排除一定不是最优解的情况,以达到节省时间,提高效率的目的。不管是单调栈还是单调队列,其核心思想都是单调二字,也就是说,我们需要维护的永远都是队头or栈头的那个最小or最大的元素,对于单调队列而言,基本的思路就是:维护队首,如果队首超出范围那就要删除维护单调去除冗杂,像本题中,遇到队伍中比当前值还大,并且排名还靠前的元素我们原创 2021-01-12 11:12:53 · 123 阅读 · 0 评论 -
Ac.Wing 133蚯蚓 进阶指南P56 题解
写在前面的话:这道题久违了个人感觉这个题目的质量还是相当不错的,结合了队列和数学,难度上在Ac.Wing属于橙题范围,做这个题的时候发现的主要问题在于:一些数学公式的推导思路和理解还要去训练对于整体偏移和通过偏移量求值的问题的理解下面给题解:题解:这个题目可以去用最朴素的方法解决:就是说我们定义一个偏移量,每一次从队列中取出一个最大值,然后把他分得的floor(px)floor(px)floor(px)和x−floor(px)x - floor(px)x−floor(px)全部减去q后加入原创 2021-01-11 10:37:34 · 89 阅读 · 0 评论 -
AcWing 110 防晒
题解:emmm这个题目是一个贪心的问题,但是一开始理的不是很清楚…首先这个题目提供两种方法,一种是一般贪心,还有一种就是使用了一下优先队列,其实原理都是一样的。法一:我们把奶牛的minSPF从大到小排序,然后再对防晒霜按照SPF降序排序,这样我们对于每个奶牛都去选择SPF最大的那个防晒霜。可以证明的是:对于前面的奶牛,如果这个防晒霜的SPF大于minSPF,那么之后的奶牛一定也满足这个条件。也就是说,当前奶牛可用的任意两瓶防晒霜x,y,如果SPF(x) > SPF(y),那么对后面的奶牛就一定原创 2020-08-28 15:22:52 · 152 阅读 · 1 评论 -
AcWing 109 天才ACM
题解:这个题目应该说是一道综合性很强的题。首先,如果要求这个集合的校验值最大,那么肯定是排序以后最大的和最小的匹配,次大的和次小的匹配,其次还要考虑,如果二分区间,那么很有可能出现校验值T的值本身比较小,但是二分是在整个区间上开始的,所以可能出现第一次二分就查询了(N - L)/2这么长的一段但是最后右端点只拓展了一点点的情况,这样会导致时间冗余。所以我们要考虑用倍增解决,这样倍增算法的复杂度为O(logN),加上之前排序的复杂的,整个算法的复杂度大概在O(N∗log2N) O(N * log^2N)原创 2020-08-28 11:44:18 · 111 阅读 · 0 评论 -
AcWing 108 奇数码问题
题解:我们把给定序列按照次序排成一列,我们可以发现,当空格左右移动时,整个序列的逆序对数不受影响,但是当空格上下移动时,我们可以发现其实就是被交换的数和他前后的n - 1个数调换了次序,我们已知n是一个奇数,那么n - 1必然是一个偶数,相应的逆序对的变化也会是一个偶数,所以我们判断的依据就是:两个序列的逆序对数是否奇偶性相同。AC代码:#include<iostream>#include<cstdio>#include<cmath>#include<a原创 2020-08-25 19:29:46 · 108 阅读 · 0 评论 -
AcWing 107 超快速排序
题解:其实题目就是说了一个冒泡排序,但是肯定不能直接就用冒泡了…如果要求求解一共需要交换多少次次序,那就可以使用归并算法,直接计算逆序对就可以。AC代码:#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#include<cmath>#define ll long longusing namespace std;const int原创 2020-08-25 17:27:01 · 92 阅读 · 0 评论 -
AcWing 105 七夕祭
题解:这个题目是一个综合性很强的题目,可以类比为环形分纸牌的问题。我们注意到对于每一行上的相邻元素,交换次序后只会影响到每一列的结果,同样的交换每一列上的相邻元素影响的也只是每一行的结果。所以我们可以把行和列分隔开分别讨论。但是不管对于行还是对于列,我们都需要满足 K % N(M) = 0不然肯定无法均分到每一行每一列上。我们可以先在原数组中处理一下,对于每一行每一列的摊点数目,我们都先预处理为A[i] = A[i] - k/m(n),这样就相当于要把所有的A[i]都变成零,我们知道对于一般均分纸牌的原创 2020-08-25 13:08:46 · 106 阅读 · 0 评论 -
AcWing 201 可见的点
题目描述:在一个平面直角坐标系的第一象限内,如果一个点(x,y)与原点(0,0)的连线中没有通过其他任何点,则称该点在原点处是可见的。比如下面的图示:这个里面(1,0),(1,1),(0,1)就是可见的,而(2,2),(1,2)就是不可见的。编写一个程序,计算给定整数N的情况下,满足0≤x,y≤N的可见点(x,y)的数量(可见点不包括原点)。1≤N≤1000题解:首先对于任意的x,y,都会存在三个点满足:(1,1),(1,0)和(0,1)。其次,观察到所有满足题目条件的点都关于x = y对称原创 2020-08-06 20:19:26 · 137 阅读 · 0 评论 -
AcWing 200 Hankson的趣味题
题目描述:已知正整数a0,a1,b0,b1,设某未知正整数x满足:1、 x和a0的最大公约数是a1;2、 x和b0的最小公倍数是b1。Hankson的“逆问题”就是求出满足条件的正整数x的个数。题解:首先这里感谢xyw师哥的现场指导!(没有师哥csdn就不@了)关于这个题目其实就是一个推导转换的过程:gcd(x,a0) = a1 ---> gcd(x/a1,a0/a1) = 1lcm(x,b0) = b1 ---> gcd(b1/x,b0/b1) = 1我们同时发现x/a1是原创 2020-08-05 19:56:24 · 226 阅读 · 0 评论 -
AcWing 199余数之和
题目描述:给出正整数n和k,计算j(n, k)=k mod 1 + k mod 2 + k mod 3 + … + k mod n的值。例如j(5, 3)=3 mod 1 + 3 mod 2 + 3 mod 3 + 3 mod 4 + 3 mod 5=0+1+0+3+3=7。题解:这个题目关键在于看出需要用整除分块的知识做。首先对于k mod i我们可以写成:k = (k/i) * p + r所以现在的问题就转换成了如何求(k/i)我们也注意到,比如对于(5,5),我们可以展开写:5/原创 2020-08-04 23:05:53 · 175 阅读 · 0 评论 -
AcWing.198 反素数
题目描述:对于任何正整数x,其约数的个数记作g(x),例如g(1)=1、g(6)=4。如果某个正整数x满足:对于任意的小于x的正整数 i,都有g(x)>g(i) ,则称x为反素数。例如,整数1,2,4,6等都是反素数。现在给定一个数N,请求出不超过N的最大的反素数题解:首先这这个题需要用到这么几个推论:1.1 ~ N中的最大反质数其实就是1 ~ N中约束最多的数中最小的那一个。2.1 ~ N中的不同质因子数不会超过10,且所有质因子的指数总和不超过30.3.对于一个1 ~ N中的数x原创 2020-08-04 17:50:55 · 131 阅读 · 0 评论 -
AcWing 197阶乘分解
题目描述:给定整数 N ,试把阶乘 N! 分解质因数,按照算术基本定理的形式输出分解结果中的 pi 和 ci 即可。题解:首先这个题目肯定需要做一个筛子,但是N!的值实在太大,所以直接计算阶乘后打表肯定不现实。但是我们注意道,对于N!,一个质因子p的个数取决于1~N这N个数中有多少个质因子p,最后对于p的答案只需要相加即可那么问题就变成了:如何求1~N中的p的个数?我们知道,在1~N中,p的倍数有,N/p个,但是我们注意到,这N个数中可能有p的平方的倍数、p的三次方的倍数…所以我们需要在此基础上原创 2020-08-04 12:54:21 · 232 阅读 · 0 评论 -
AcWing196——质数距离
题目描述:给定两个整数L和U,你需要在闭区间[L,U]内找到距离最接近的两个相邻质数C1和C2(即C2-C1是最小的),如果存在相同距离的其他相邻质数对,则输出第一对。同时,你还需要找到距离最远的两个相邻质数D1和D2(即D1-D2是最大的),如果存在相同距离的其他相邻质数对,则输出第一对。其中L和U的差值不会超过1000000。1≤L<U≤2^31−1题解:这个题目很容易可以想到需要质数筛子,但是可以看到,我们的L,R的值都已经达到了1e10的级别,而我们在判断质数的时候需要用数组对每一个原创 2020-08-03 10:36:41 · 177 阅读 · 0 评论