请转到 https://blog.csdn.net/hzx616599/article/details/139567004
处理进度(仅仅处理了作者做过的题目,且不保证顺序!)
- 绿:P10475
- 蓝:P2573
致CSDN网友:
本文章不定期更新!文章链接:https://blog.csdn.net/hzx616599/article/details/139567004
经典问题分析
基础知识与编程环境
-
了解树的中序遍历的性质来设计算法→P1040
-
按二进制每一位分开算→记前缀异或值X[0…N],一段区间[L, R]的异或值就是X[L-1] xor X[R]→那么就是统计有多少个区间的异或值是1,那只需要统计X[0…N]中是0和1的分别有多少个,两个个数相乘就是区间个数。→P3917
-
每一位拆开→定义f_j为以a_j结尾的答案,g_i为到a_j时第i位为1的长度→P4310
-
预处理→P8865
-
构造一个x,使得满足a_i
^
(异或)x<k的i最多→对每个a_i考虑,发现使a_i^
x<k的x是连续的一段→逐位考虑,求出x的区间,相当于一条线段→求出覆盖线段最多的那个x就是答案→P6824 -
简单构造→P7049→先黑白相间,然后再在一整块颜色a中点几个b。行宽为1时特判。
-
H形计数→枚举H中的横线,矩形中的“扫描线”优化→P7715
-
模拟→P8289
-
栈的模拟→P8815(不是普通的模拟,而是含有递归结构的模拟,是一类重要的题目)
-
考虑异或和有前缀和的性质,化简式子→逐位考虑→P9236
-
P9571→用map<,map<>>存每个k,b线段即可。
-
P9588→set记录队尾,维护每个序列的队尾下标s[],以及弹出了多少数字pre→对操作3,直接在s上二分出pre+pos,找到对应队列即可。操作4直接找set中最大值
-
O(n)求mex→桶+指针→P10032←模拟后发现会出现周期为2的循环,于是在模拟几次后直接讨论奇偶性
-
诈骗
P10114→看上去又是类似求所有(a_i,a_j)的a_i^
a_j之类的,但是发现不是特别好写→观察数据范围,有一项很特别,为\sum a_i→推导出不同的a值为1e3范围→O(cnt^2)两两枚举不同的a值,然后算上计数,暴力统计。 -
P10500→二进制套路:逐位判断,分类讨论,计算期望
-
插队求最终排列问题→P10497→O(n^2)暴力模拟→更优的做法:从后往前考虑,使用树状数组维护(二叉查找树)
-
P1966→必须让第一列中第i高的火柴与第二列中第i高的火柴对齐。这好像是一个不等式(顺序积的和≤乱序积的和)→我们把A序列作为标准,B计算逆序对即可
-
P3941→O(n^3)的扫描线,再加上一个同余桶→即ton_i记录的是扫描线前pre_j\mod K=i的j的个数
思维
-
考虑每一个数字的贡献而不是考虑每一种情况那个数字做贡献→mna.816/p4
-
观察数据访问,发现一个范围很小→将这个数据作为最外层循环,每次考虑这个数据取特定值时的答案的求解→P1311
-
求最优化一个计算式,并且里面有一个值需要你来确定,并且不好直接求→二分→优化每一次计算过程→O(n)求多个询问区间内>m的数字的个数之和→先把≤m的数字赋0,然后跑前缀和,再对每个询问O(1)处理→P1314
-
将字符串哈希后离散化→双指针,右端点不断扩散(右移),左端点贪心地缩小(右移)→P1381
-
正确计算求因数的复杂度(是O(\sqrt n)而不是O(n))→发现暴力可行→P1483
-
转化为模型→求集合中小于k的最大值和大于k的最小值→set→P1503
-
简单的数学贪心→连接1n加热第1杯,再连接2n加热第2杯,再……→P1984
-
结论题→P2041
-
逐位考虑后贪心取每一位的最大值→P2114
-
直接搜索不行,因为发现m较小,考虑结合贪心→贪心先分出最短的木板→二分答案→搜索验证→剪枝→P2329
-
贪心的线段覆盖问题→线段按右端点排序后,再从小到大将每个点排序→P2887
-
直接模拟→先把所有牛的高度设为最高值,如果某两头牛之间能互相看到的话,那直接把中间这些牛的高度都减一→证明合法:唯一不合法的就是给出关系[a,b][c,d],且b>c,那么按上面模拟就会不满足[a,b],但是发现这种情况本来就无解,所以上面的是正确的→P2879
-
结合数据范围,直接使用map记录每个单词的出现文章,规避正解→P3879
-
当贪心有时不能证明时,就在时间复杂度允许的情况下多算一点→P4395,——也许会像只填1或者2,但是实际上可能填3,所以我们考虑只填1\sim 20即可。
-
等价集合问题→把 能够被其他钱凑出来的钱 给筛掉,剩下的就是我们必须要保留的面值→P5020
-
合并果子加强版,每次取出最小的两堆,不能使用优先队列(log n)→维护两个递增队列,p,q,p为原果子桶排后的结果。每次从两个队头比较并取出两个最小的,然后放入q的队尾。可以保证单调性→P6033
-
日期转化模拟→P7075
-
廊桥分配→先忽略限制,我们维护2个空闲的廊桥队列,每到达一架航班,就给它安排编号最小的廊桥(分国内/国外)供其使用→处理 cnt1 和 cnt2 数组,分别表示国内和国际航班分配 i 个廊桥的答案数→最后答案就是 max(cnt1_i+cnt2_{n−i})
-
从双端队列中取数,使得取出来的是回文→找出与 a1 的唯一一个位置,记作 p。则序列被划分为两段(看成两个栈)→转化为每次可以取走这两个栈之一的栈顶,令最终得到的串是回文串→只有存在某个数 x,既在栈顶,又在栈底才能取走。否则无解→构造→P7915
-
乘客优先选择最近的座位,并且让位给离那个座位更近的乘客,求矛盾(多个乘客到同一目标距离相同)数→贪心,按第一目标从近到远排序→逐个考虑每个乘客,分类讨论→P8073
-
P9744→观察数据范围,发现时间复杂度和m有关→考虑每次最多只进行一次前缀染色→枚举那次前缀染色的i→发现i+1只能在P中选,于是时间复杂度和m挂钩→前缀和,树状数组优化使得枚举了i后可以O(\log n)计算代价
-
在稀疏图上选一个点,使得其与其它点的哈夫曼距离和最大→结论:最优选点必定为上述四个点之一,或者某个已知点的邻点→维护一下横纵坐标前缀和,问题变成多次回答某定点到所有点距离之和→P10025
-
打表找规律,发现答案是等差数列→贪心求出首项和末项→根据序列中存在F的位置确定公差,因为公差 ∈ [ 1 , 2 ] \in[1,2] ∈[1,2]→P9183
-
找规律。我们发现每一个连通块在竖着划分时都可以划分为 2 0 + 2 1 + ⋯ + 2 i 2^0+2^1+\dots+2^i 20+21+⋯+2i个方块,并且每一个连通块的第一竖(即 2 0 2^0 20)都在第一行,也就是说我们只需要找到其右端点即可→找到右端点为第j列后,答案就是20+\dots+2j。如果j>64,就直接顶到n→P9915
-
数字变化类题目:-1或者\times 2,求最小操作数→转化为+1,\div2(a 为偶数时可选)。他们的最小次数也是一样的→考虑尽可能多的 \div 2 即可→P10026
-
P10033→构造特殊填法
-
P10118→x+y=2×(x AND y)+x XOR y,记C=x XOR y→并且为了保证y>x,于是C的最高位1必须分配给y→剩下的popcnt©-1位自由分配,会产生2^{popcnt©-1}个方案
-
P10412→当且仅当 ∑a_i≥0 时,数列 b 美妙,将 a_i 升序排序,之后依次考虑每个 ai,判断使用加一操作和删除操作哪个更优
-
P10454→将序列展开后,考虑移动带来的影响→发现无论如何逆序对数量不会改变→比较前后两个情况的逆序对数量以得出答案。
-
P10449→美剧第一行的情况后发现,为了实现目标,后面的操作情况是确定的→模拟即可。
-
P1712→题目要求的答案跟“最大”,“最小”有关,所以我们就会联想到单调性→将区间按长度排序后,逐个加入区间直到有点覆盖≥m(线段树)→统计答案,弹出旧区间,加入新区间,重复过程。
-
P2332→我们花 O(n4) 来枚举一下 x,y 轴,对于 z 轴,我们通过同余+桶来优化。时间复杂度为 O(n^5)
-
P2512→考虑类似均分纸牌→推式子→转换为求到数轴上n个点最近的点→中位数
-
P3620→反悔贪心→题意简化为选择两两点配对使得总距离最短→每次从优先队列中取出最优的一对,如果和当前有冲突,就把冲突对减去最优对加入优先队列,作为一个候选项→如果后来选上了这个,那么就相当于“反悔”操作
-
P2827→考虑O(m\log m)的做法,优先队列模拟即可→但是题目卡\log,我们想到了一道题“石子合并”,也是用多个队列替代了一个优先队列→这种方法适用于原数据是单调的,新产生的数据也是一样单调的→本题就可以开3个队列,每次比较对头数据,取出最大的,然后把拆分后的数据加入另外两个队列尾部
-
P2859→贪心,类似区间覆盖问题的思路→将每段时间的左端点从小到大排序,然后一个个插入,插入时比较是否先前的牛棚中已经有牛挤完了奶,如果没有就新增一个牛棚,否则用挤完奶的牛棚,类“廊桥分配”
-
P2862→O(n^3)扫描线即可
-
P3045→我们先把c值最小的k个元素的c值之和变成答案→再维护c的小根堆,为c值最小的+p和c的差值最小的。即为这个东西的价格+这个东西替换的那个东西的差价→再维护p值的小根堆→那么我们比较两种取值的花费,那个小就取哪个即可。
-
P3514→重要结论1:如果 k(k>2) 可以得到,则k-2 也可以(考虑从区间两端减点)→找到最大的奇数,最大的偶数即可
STL 模板
-
P2161→使用自定义数据类型的set要重载运算符,自定义两个区间重叠为相等
-
P2202→先对所有点排序,然后维护与当前点横坐标差值小于k的所有点的集合,每次查找点集中纵坐标最接近当前点的点,更新答案即可
排序算法&分治
-
在DAG中,更新一个点的信息如果需要先更新其来点→拓扑排序→P1038
-
一些偏序问题(非计数类),考虑拓扑排序进行顺序确定→考虑不同情况反映在DAG中的情况→一定有序:存在n长链/错误:有环→P1347
-
分层问题→给出一些节点的层级关系,要求分层→P1983
-
考虑使用分治→扫描左部,将答案记录到树状数组中,然后扫描右部u,在树状数组中取符合要求的范围的区间和即可→权值树状数组→P5459
-
cdq分治→P5459
-
点分治→P1429
搜索算法
-
打表→P1549,P1790(也可使用搜索究极优化,插头dp)
-
O ( 2 40 ) O(2^{40}) O(240)的搜索→Meet in the middle→P4799,P10484
-
数据范围小的时候可以考虑直接搜索(填表)→P1004
-
有些时候看上去n不适合搜索(e.g. n=50),但是加上剪枝也许就是正解→剪枝优化时间复杂度的证明和计算→P1034
-
常见数矩阵个数优化(n4变n3)→P1191
-
结合计算性质进行剪枝→P1092
-
枚举/搜索→P1378,P1441,P1731,P1120。P2476,P4537
-
结合dfs继续树上递推→f_{x,dep}=\sum f_{v,dep-1}→P3047
-
bfs→P3956,P5195,P10485
-
P10488→有“超过X步就输出more”→迭代加深→优化:估价函数
-
P1528→可行答案是一段前缀,考虑二分答案→贪心分配蛋糕,得到局部最优解
-
P3067→考虑对于每一头奶牛来说有3种状态,放在一组,放在另一组,不放任何一组,如果暴力枚举时间复杂度为O(3^n)→折半搜索
-
P3716→广搜,一步一步去走的话一定会TLE→冰块的数量不多,可以在广搜的时候枚举所有冰块,求出距离当前点上下左右最近的冰块,判断一下能否直接跳到终点
图论算法
-
应用分层图思想【模型】→P1073
-
记录附加信息的最短路→P1078,P1144,P1608,P2047
-
给定关系求层级数最小值→先整理出约束(e.g. A在B之上),连有向边→求最长链→拓扑排序→P1983
-
总结出最后的图的特点→生成树→最大生成树→证明某些很难解决的情况不存在→简单解决→P1265
-
结合数据范围,考察floyd算法可以实现的内容→求出任意两个点之间的距离→枚举配对→考察答案的几个情况→P1522
-
预处理图后再跑最短路→删除不合法的点→P2296
-
考虑到一个点要是有出度到v,那么一定要有从v来的入度,这个点才可能全员可达→点属于强连通分量→强连通分量找到唯一一个没有出度的集合,集合内所有点都合法→如果有两个集合满足,则无答案。→P2341
-
将决策转化位图论模型→留在原地:自环,自爆:超级汇点→从floyd算法的角度考虑,A^k(A为邻接矩阵)的第i行第j列的数字含义是从i到j经过k步的路径方案总数→矩阵快速幂→累加A_{1,i}→P3758,P5789
-
二分图最大匹配→P3386
-
Tarjan→P3387,P3388,P2863
-
Tarjan处理链和环→P2921
-
判断x和y之间是否存在长度为k的非简单路径(无环)→路径长度可以是 l + 2 k , k ∈ N l+2k,k\in \N l+2k,k∈N,l为最短距离→P5663
-
差分约束→将不等式条件转化为图(x_i≤x_j+d_k,就按照最劣的建边,把x看成点,x的值看成dis,所以就建x_i→x_j,w=d_k)最后跑最短路,得到x的解。如果有负环,则无解,可以跑出来,就有解→P5960
-
P5663→考虑在一条边上往返奇偶性不变→对要求的阶段分奇偶讨论→求出1到其它节点的最短奇/偶数长度路径,O(1)回答
-
对有大量边权相同(分组)的图建最小生成树→考虑kruskal本质:不断取出边权最小的边且保证没有环出现→一次取多条边
-
每次构造一条边(损坏或者完好),使得最后一条边构造出来后才知道图是否被完好边联通→首先必须是生成树,并且最后被询问到的边一定要是树边,并且最后一条边的建立要实现这颗生成树而不能不联通→让每个点最后被构造的连边为树边→可以证明是生成树且符合要求→P5884
-
对每个水流模拟→拓扑排序→附带分数的运算→P7113
-
欧拉路径→P7771
-
在一个 n 个点 m 条边的无向图中构造出每条边的长度 zi(1≤zi≤k),使得点 1 到任何一个点的最短路径都是唯一的→先写 dijkstra 板子,然后边权全部初始化为 1,如果碰上路径长度相同,则将当前这条边的边权加一,最后判断如果最大边权超过 k,则无解,否则有解,输出答案即可→P10178
-
P1407→将所有 现在或曾经交往过的 男孩和女孩连接起来,可以发现出现了一些环,而处在环中的婚姻不安全。→给无向图定向,均为男女之间连边,但是夫妻和前任的连边方向相反→如果一对夫妻在同一个scc内,则不安全
-
次短路模板→P1491→首先找出一条最短路,之后一次去掉一条最短路上的边,对于每一次去掉一条边后的图都跑一次最短路
-
P1613→我们把每对可以1s内到达的点都连上1的边,跑最短路即可→为了预处理每对符合要求的点,我们记录g_{i,j,k}为i,j能否通过2^k路径到达,类floyd预处理。
-
P1653→先按题目所说的条件建边,然后scc缩点→考虑选择有n个入度0的点和m个出度0的点,那么答案就是max(n,m)
-
P1772→先看懂题目,发现都是从1到m,且路径+k\times 改变次数 最小→预处理c_{i,j}表示i\sim j天都走同一条路径的最小划分,f_i为前i天的最小花费→f_i很好转移,c_{i,j}的预处理:断掉i\sim j内所有不行的边,跑最短路。→结合数据范围,可以暴力完成。
-
P2057→将源点和汇点相连的人视为两个立场,要求立场相同的关系建一条有向边→为了解决冲突,我们就要断掉所有流量→最小割
-
P2149→对两个人分别建出其最短路DAG,然后用有向图dp求出最长重叠部分→注意可能是反向图的重叠,即答案可能是甲A→B,乙B→A时的最长路径
-
P2656→scc缩点后每个scc内的边都可以全部取完,其它的边只能走一次→最长路
-
P2756→网络流的建图策略
-
P2761→我们参考网络流建图的策略,将111…作为初始状态,000…作为最终状态(这里的1表示存在bug)→将每一个补丁作为一条边,边权为1跑最短路→不需要建边,只需要在最短路转移时枚举每一个补丁看看能否使用即可。
-
P3627→Tarjan scc缩点
-
P2746→第一问:我们采用局部思想:如果一个点有入度,那么就不用管他,所以我们统计出入度为0的点即可→第二问:问加多少边可以让图变成一个scc→设入度为0的点有S个,出度为0的点有T个,那么就是max(S,T)。这是一个常用结论!(证明https://www.luogu.com.cn/article/vmrnb8m9)
-
最小费用流→将最大流中的bfs改为spfa即可。
-
P2860→我们要做的,就是连边将整张图变成一张边双连通图→缩点,建树,现在我们就要将一颗树变成一个edcc→ans=(leaf+1)÷2
-
P2865→次短路模板
-
P2886→floyd维护信息转移→矩阵快速幂优化
-
P2939→可以存下KM条边→经典模型:分层图
-
P3403→模型:同余最短路
-
P3225→讨论割点→用Tarjan跑出割点,然后DFS搜索所有的联通快→计算每一个联通快中的割点数目:如果没有割点,需要从任意非割点的地方选择两个点建立;只有一个割点,设立在任意一个非割点的地方;如果有两个及以上个割点,则无需建立
-
P3254→网络流的建图
-
P3275→差分约束
-
P3469→vdcc→如果是割点,那么乘法原理,否则无影响→记得加上自己和其它点的答案(n-1)
线性结构
- 单调队列优化dp→P1725
集合与森林
-
使用并查集额外维护集合信息→将集合信息统一整理至某一个集合的代表元素上去,注意清空过期的代表元素→P1196
-
断边维护连通块个数→化断边为加边→P1197
-
扩展域并查集→P1525,P1892,P2024
-
简单并查集维护,先处理相等的约束→P1982
-
、先解决环的情况→缩点→然后拓扑排序→P1262
-
区间2反转求和问题→线段树维护异或tag→P3870
-
树上的括号栈问题→括号序列计数问题→出现一个
)
,它可以和之前的形成一个(..)
的括号序列,这个序列还可以和前面的一些序列并列,形成更多合法序列→对每一个位置x记录以其为结尾的括号序列个数c_x,下一次若以son(x)为开头形成了一个括号序列,那么实际上有c_x+1个序列被形成,并且维护c数组→P5658 -
给出若干条件:[l,r]之和为奇数/偶数,求最早矛盾→扩展域并查集→维护左右端点处前缀和的奇偶性→若给出区间[l,r]为奇数,那么pre_l,pre_r应该在不同并查集内,检查矛盾;另外一种类似。→P5937
-
P2391→倒序模拟→考虑优化,用并查集加速往前跳的流程。即维护f_i表示i前面的最靠近i的那个未染色的下标
树形结构
-
维护树链上的信息→树上倍增,树剖
-
维护子树信息→dfn线段树
-
从题目中整理出树的性质→设计树形dp进行最优方案求解→P1131
-
结合数据范围,预估复杂度→搜索→设计搜索→因为每一层只能切断一个,所以就可以对每一个节点搜索其最优的切断方式(使用回溯的数据来贪心选择)→P1041
-
理清题意→整理出答案的几种来源/情况→对于每一种情况独立思考做法,最后组合起来→P1099←答案有两种情况:来自直径两端,来自最长的侧链。并且来自最长的侧链的那个答案只需要计算侧链端点到直径的距离即可。不需要考虑侧链+一部分直径的情况,因为如果这种情况可以作为答案,那么直径就要改了!
-
考虑每一个路线对那些点有贡献→树上路径加→树上前缀和→P3128
-
判断树上两条路径是否有交→分类讨论→求lca→P3398
-
求树上所有一段为根节点的串上的合法括号串数量→dfs中维护栈→P5658
-
树上子树修改,单点查询→dfn序对应→P7746
-
树上有点权,多次询问路径上点权和→预处理任意点到根的点权和,询问时求lca→P8805
-
P9619→答案肯定是k\sum w,k为每条边在所有生成树中出现的次数,可以证明k对每条边都是相同的。w为边权→由 Cayley 公式知完全图 K n K_n Kn 有 n n − 2 n^{n-2} nn−2 个生成树。由于是无向图,每条边是等价的,所以所有边共出现了 n n − 2 × ( n − 1 ) n^{n-2} \times (n-1) nn−2×(n−1) 次,共 n × ( n − 1 ) 2 \frac{n \times (n-1)}{2} 2n×(n−1) 条边,所以一条边出现次数为: n n − 2 × ( n − 1 ) n × ( n − 1 ) 2 = 2 × n n − 3 \frac{ n^{n-2} \times (n-1) }{\frac{n \times (n-1)}{2}} = 2 \times n^{n-3} 2n×(n−1)nn−2×(n−1)=2×nn−3→再考虑快速计算\sum w→因为是异或,所以每一个二进制位分开讨论,想要产生贡献的情况只能是一条边所连的两个端点同一二进制位一个为 1,另一个为 0,又因为是完全图,所以组合计数即可。均摊。
-
P1505→树链剖分
-
P1967→这道题可以用很多经典算法解决,如树链剖分,树上倍增,kruskal重构树
-
P2573→我们发现最后最优的走法是一棵树→建边后跑最小生成树
-
P3942→令f(x)表示编号为x的节点与以其为根节点的子树中最近一个未被控制的节点的距离+k,如果没有这样的节点,则f(x)表示编号为x的节点与以其为根节点的子树中最近一个驻有军队的节点的距离→当f(x)>k时,在以x为根节点的子树中,存在不被控制当节点。f(x)>2k时,节点x必须驻扎军队。
-
P2634→可以使用点分治,但是有dp做法→定义 f[x][i=0,1,2] 表示在点x及其子树中,距离点x的距离在模3意义下为0,1,2的点分别有多少个→统计答案时匹配i和3-i即可
-
P2680→二分答案→Check函数:判定对于len>t的所有链,能不能找到找到至少一条长为k公共边,使得最长链的长度len-k≤t
-
P3621→性质题→考虑最少交换次数:其实对于每一个节点的左右子树,三种情况需要交换,1,左边全是小深度的,右边全是大深度的2,左边全是小深度的,右边大小深度都有3,左边大小深度都有,右边全是大深度的→dfs搜一遍就好了。
-
P3605→ans[x]=x的下属中比x强的=树状数组中加了x下属后比x强的−原来就比x强的→dfs过程中线段树/树状数组维护即可
-
P3541→交换子树只会对横跨左右子树的逆序对产生影响→只需要在合并线段树的过程中统计交换子树的逆序对个数和不交换子树的逆序对个数,取 min加入答案
数据结构
-
动态维护数字序列信息→权值线段树→P1168
-
线段树模板→P1198,P1253,P3372,P3373
-
偏序问题,又带有一点dp(上升序列)→使用数据结构优化dp→树状数组优化转移→P1637
-
平衡树查询寻值前驱和后继→P1110
-
维护区间极值+正负性分讨→P8818
-
树状数组→P5094
-
统计区间和在[l,r]的区间个数→考虑类似逆序对的树状数组做法,右端点扫右边,左端点O(1)统计→离散化→P5459
-
可以使用multiset模拟二叉搜索树→P5076
-
快速求01序列区间内最长上升子序列长度→预处理前后缀0/1个数,因为一定是0…01…1→max:i∈[l,r]{pre_i+lst_i}−pre_l−lst_r→结合时限,采用ST表求区间最大值
-
区间修改,求区间gcd→发现区间修改很难办→证明差分数组的区间gcd和原数组的gcd相同(更相减损术)→维护差分数组→P10463
-
P10589→树状数组/权值线段树
-
P1456→多个可合并集合,多次询问合并后求集合max→线段树合并,或者可并堆→使用平衡树实现(merge)
-
P1533→因为区间不互相包含,所以将区间排序后从前往后双指针,每次在线段树中弹出一些,插入一些,然后线段树上二分查找即可。
-
P2073→平衡树
-
P2146→一道树链剖分的模板题→每次安装软件,把根节点到x软件路径上的值全部变为1,每次卸载软件,把x以及它的子树的值变为0、
-
P2572,P2894→线段树维护区间最长连续1串
-
P2590→树链剖分
-
P1471→推导出方差图中的公式为:
S 2 = ( x 1 2 + x 2 2 + … + x n 2 ) n − x ‾ 2 S^2=\frac{(x_1^2+x_2^2+\ldots +x_n^2)}{n}-\overline{x}^2 S2=n(x12+x22+…+xn2)−x2后,用线段树维护。 -
使用平衡树也可以首先可并堆→P3377
-
P3105→qzw[i]-qzw[j-1]>=qzs[i]-qzs[j-1]转化为qzw[i]-qzs[i]>=qzw[j-1]-qzs[j-1]→线段树维护最小的j-1
-
P3466→枚举一个长度为k的所有区间→很明显是变成中位数最优→将中位数左边的数分别加到中位数,右边的数分别减到中位数→使用平衡树来维护,或者权值线段树
-
P3567→主席树→也可以使用随机化算法,因为一个数字出现次数多余一半,则随机到的次数也应该在一半左右以上
-
P3834→主席树
算法策略
-
P2464,P1972,P1494→莫队模板
-
P2709→莫队维护计数平方和
-
维护4指针2区间信息→莫队,将4指针拆为2指针及多个询问→P5268
-
查询最大的和≥0的子矩阵→O(n^3 \log n)的做法可以枚举i,j,扫描线一遍,用线段树维护信息→O(n^3)的做法可以用最优化剪枝,即在扫描线时,设之前的已有答案宽度为l,那么此后答案至少为l。即双指针l,r,r向右一格,l也向右一格,并尝试左移→需要找到单调性,可以是对前缀和进行前缀最小值→P1565
-
P1903→带修莫队
字符串算法 哈希表
-
kmp→P3375,P10475(将kmp数组进行横向扩展、寻找循环节类题型),P2375
-
字典树→建树技巧与树上匹配→P2922
-
P1383→带撤销的打字机→将操作视为在trie树上的操作,每一次操作就是从当前节点向外连边,并走到指向的点出→撤销就是当前节点向之前的每一个节点连边。为了快速找到这个节点,我们使用倍增。
-
字符串ss的最小循环子串,就是ss的最大公共前后缀→P4391
-
树哈希(树同构)→P5018
-
二维哈希→对横着的哈希再次哈希,并且维护其类二维前缀和性质→P10474
-
P1659→求一个字符串中前k长的奇回文串的长度之积→马拉车算法
-
P3065→设这个字符串的第 i 个字母为 u,我们可以连单向边 u→v,表示我们指定了 u 的字典序比 v 小,其中 v 是第 i 层的其它字母→若这个字符串是其它某个字符串的前缀,则这个字符串不可能成为字典序最小的串;当 26 个字母间的关系形成环时,也不能成为字典序最小的串。
-
P3455→一个字符串的最大周期长度就是这个字符串的长度减去它最短的公共前后缀长度→注意这个公共前后缀的长度必须小于等于字符串长度的一半,否则不存在周期→kmp求解
-
P3796→Trie树,ac自动机
-
P3805→马拉车
动态规划
-
用“非法情况一定更劣”来消去需要考虑非法的情况→P1006
-
dp不就是枚举情况并选最优吗?→P1040
-
断环为链→P1043,P1063
-
题目中有明显的“合并”流程,则考虑区间dp→P1063,P1880(与贪心的那道题区分),P1220,P3146
-
依赖背包嗯可以看成树形dp来做→P2014,如附件数量很少则可以枚举每个主件和附件的配对情况并作为一个物品的多种情况。当遇到一个物品有多个挡位时的背包问题也可以参考本题→P1064
-
从题目信息中构造出背包(f_{i,j})的物品(i)及两个维度(价值(f)和容量(j))→P1156,P1282,P5322
-
考虑树形dp并考虑复杂度→P1273
-
主要考验dp转移的设计以及dp优化→思维→P1070
-
一开始考虑贪心→给定方案计算答案很快→不好实现,所以使用搜索(计算每一种可行情况)→使用dp实现记忆化搜索→压维优化→P1284
- 期望dp→得出概率的计算式→使用dp求出计算式中的值并计算→本题:第i题对的概率=i-1题答案=i题答案→P1297→其它题目:P2111
-
树形dp,最大权独立集→P1352
-
简单树形dp→P2015,P2016,P2585
-
非常规最长公共子序列→转化为最长上升子序列→P1439
-
记忆化搜索(dp状态设计)→P1541
-
数位dp→从高位到低位,逐位考虑非限制,递归非限制→P1836,P2602,P4999
-
带方案输出的简单dp→P1854
-
抽象出模型→转化为背包dp→P1941
-
dp状态的设计→在设计dp状态时,考虑如何使用最少的状态表现出我们所有需要的信息→f_{i,j}表示考虑了前i个人,1其中在窗口1打菜的总时间为t时完成所有活动的总用时→P2577
-
查看数据范围,发现可以O(nmk)→定义f_{i,j,k}为S_{1→i}与T_{1→j}匹配且分为k块→循环i,j,k,要求快速判断S,T中两个片段能否匹配→预处理g_{i,j,k}为S_i,T_j结尾的两个长度为k的字符串是否相同→P2679
-
小规模最优分组问题→状态压缩→f[i]代表当前状态为i时最小的分组数→P3052
-
区间dp转移式的推导→P3205
-
换根dp→P2986,P3478
-
树形dp→考虑到有以及染色的,所以在dp时砍掉不符合的f值→P4084
-
类似括号匹配的(如决策为扩展一边/同时扩展两边)→P4170
-
f_{i,j}定义为保留第i个点塔,差值为j的方案数,枚举上一个保留的塔→P4933
-
看到数据范围n≤20→状态压缩→P8733,P10447
-
P10115→动态规划与括号序列结合→在栈上维护信息
-
P10236→一开始想搜索,然后发现期望复杂度为 O(n^2)→把搜索看成是dp,交换状态和值,我们就得到了有决策的填表搜索→其实就是dp,设 dp_{i,j,0} 为 i∼j 且从 左0右1 端开始取的最大值,模拟搜索即可
-
P1220→区间dp,定义f[i][j][0]表示关掉i到j的灯后,老张站在i端点,f[i][j][1]表示关掉[i][j]的灯后,老张站在右端点,转移即可。
-
P1270→考验从深度优先的顺序读入树→变成一道树形dp→设f[i,j]表示在结点i,拿了j幅画需要的最少时间,转移即可。
-
P1272→首先不一定存在一颗子树的大小恰好满足要求,所以我们设计dp→定义f_{i,j}为将i的子树切下大小为j的连通块,最少需要切断的边数。→转移为f[u][s] = min(f[u][s], f[u][s - sv] + f[v][sv]),这里枚举子树v可以给到的大小sv
-
P1365→期望dp,问\sum l2,l是每一个1连通块的长度。→考虑向一个1连通块末尾加上一个1,那么应该是x2→x2+2x+1,因此维护两个期望数组,分别代表x,x2的期望→当遇到0时,将x的期望清零,避免算成和前面的1相连的情况
-
P1450→有4种不同数量和面值的硬币,求凑出数值x的方案数→计算4种硬币都不超过限制不太好办,但是我们可以先让一个硬币超过限制,其它硬币随便,这我们可以得到→因此考虑容斥,把所有情况-至少一种硬币超过限制就是答案。
-
P1453→基环树版本的没有上司的舞会→短环为链,我们发现只需要随便选择一条边s-t断掉,然后从s,t分别跑一次树形dp,最后在f_{s,0}和f_{t,0}里面取最优值即可。
-
P1654→连续段贡献期望(段贡献为l3)→分别维护x3,x^2,x的期望。用低次的更新高次的。数学式子。
-
P1896→状态压缩,O(2^{2n})dp枚举当前行和上一行。
-
P1779→首先发现确定了技能集合,效果和顺序无关→先考虑集体攻击,枚举集体攻击的伤害,然后对剩余的单体另外攻击,O(NHp)可过→用背包对集体/单体攻击分别预处理出f_i为造成至少i攻击需要的最少代价
-
P1850→定义dp[i][j][0/1]来表示当前为第i个阶段,连同这一次已经用了j次换教室的机会,当前这次换(1)不换(0)的最小期望路程总和。→转移:这次不换: dp[i][j][0]= min(上次不换的dp+这两次之间的路程 , 上次概率换了之后的dp+p[i−1]×上次换了的教室与这次不换的教室之间的距离+(1−p[i−1])×上次不换的教室与这次不换的教室之间的距离)
-
P1879→带限制的状态压缩枚举方案计数→O(2^{2n}),类似P1896
-
P2034→题意变为选择一些数字使得和最小,并且间隔不超过K→写出转移式→单调队列维护
-
P2051→每一行每一列的炮的数量≤2→f[i][j][k]代表放了前i行,有j列是有一个棋子,有k列是有2个棋子的合法方案数.
-
P2167→关注到n很小,所以状态压缩记录前i个字符匹配那些字符串
-
P2215→首先求出最长的LIS,预处理f_i为i往后最长的LIS→对于询问L,从左往右扫,找到第一个满足 fi ≥L 的 i,显然它必定是答案序列的第一位;然后再从第 i+1 个数开始向右扫,找到第一个满足 fj≥L−1 且 aj>ai 的 j,那么 j 肯定是答案序列的第二位。以此类推
-
P2365→用 dpi 表示前 i 个任务都被完成,所需的时间最小值→优化
-
P2396→定义 f[i] 表示使用了集合 i 内的卡片有多少种赢的方案。
-
求最长公共子序列的个数→要求长度为 d(i,j) 的 LCS 的个数,只需要知道长度为 d(i,j) 转移来源的 LCS 的个数→在dp时维护f,g分别代表长度和个数→P2516
-
P2567,P2657→数位dp
-
P2593→记忆化搜索→定义 f_{i,j,k,0/1} 为点数为 i,点数为 i−1 的有 j 张牌,点数为 i 的有 k 张牌,是否有对子,能否把 1∼i 出完,为一个 bool 数组→最后判断 f_{100,a_99,a_100,1} 即可。
-
P2606→题意转化为求1到n的所有排列中,满足小根堆性质的排列的个数。→ f [ i ] = C i − 1 l ∗ f [ l ] ∗ f [ r ] f[i]=C_{i−1}^l*f[l]*f[r] f[i]=Ci−1l∗f[l]∗f[r]。
-
P2627→转化为选出若干奶牛,使得两两间距<K,且价值最小→f_i 为考虑前i且选i时的最优值→单调队列优化。
-
P2704→状态压缩
-
P2831 →dp[S] 表示已经死了的猪的集合状态为 S 时最少要发射的鸟数。dp[S∣line[i][j]]=min(dp[S]+1),dp[S∣(1<<(i−1)]=min(dp[S]+1),其中 line[i][j] 表示经过 i,j 两点的抛物线能经过的所有点的集合→考虑优化,若令 x 为满足 S&(1<<(x−1))=0 的最小正整数,则由 S 扩展的转移的所有线都要经过 x→优化原理:因为我们要消灭所有小猪,所以我们强制转移时一定要消除最小的,没被消除的小猪,这样可以减少搜索量(枚举line时少了一维)
-
P2890→区间dp→设f[i][j]为从i到j这段区间被修正为回文串的最小花费→当前区间[i,j]满足s[i]==s[j],直接用[i+1,j−1]转移
-
P3147→由n的范围得出最后合成的数字很小(≤56) →定义f[i][j],里面存的值是左端点为j,能合并出i这个数字的右端点的位置→f[i][j]=f[i−1][f[i−1][j]]→ 很有意思的倍增dp
-
P3177→因为是要求max,所以我们考虑树形dp→考虑统计的常用套路,就是统计每条边的贡献,那么这里我们也这样做→定义f_u,j为子树u在有j个黑点的贡献,f[u][j]=max(f[u][j],f[u][j−k]+f[v][k]+tot∗e[i].w),tot是边u-v被经过的次数
-
P3572→一眼动态规划→单调队列优化
-
P3694→状态:f[i]表示i状态下最小的出列(不一致)的个数。比如f[1101]表示从头到位为1/3/4乐队的偶像的最小出列个数→f[i]=min(f[i xor 2^j]+num[j]−(sum[length][j]−sum[length−num[j]][j])); j表示团队编号,sum表示某种团队的前缀和,length表示到此已经排到的长度。
-
P3861→先求出 n 的所有因数: x_1,x_2,…,x_d(n) →考虑 dp ,设 dp_{i,j} 为把 x_i 分解成若干个 ≤x_j 的数的乘积的方案数→转移有两种情况,1,分解中不包含x_j,可以从dp_{i,j-1}转移;2,包含x_j,要求x_j|x_i,那么就是 d p p o s ( x i x j ) , j − 1 dp_{pos(\frac{x_i}{x_j} ) ,j-1} dppos(xjxi),j−1,其中 x p o s ( x i x j ) = x i x j x_{pos(\frac{x_i}{x_j})}=\frac{x_i}{x_j} xpos(xjxi)=xjxi
-
P3970→如果没有"两个上升子序列相同,那么只需要计算一次",我们用dp[i]表示以i结尾的上升子序列个数,那么就有 d p [ i ] = ∑ j = 1 i − 1 d p [ j ] dp[i]=∑_{j=1}^{i−1}dp[j] dp[i]=∑j=1i−1dp[j]→考虑去重,什么时候会出现重复呢?我们之前更新了一个dp_i,后面有遇到一个i,此时我们可能会把之前的dp_i加入进去→我们记录下lst_i表示上一个i时新加入的答案 ∑ j = 1 i − 1 d p [ j ] ∑_{j=1}^{i−1}dp[j] ∑j=1i−1dp[j],在遇到一个dp_i时减去它即可。
数学与其他
初等数学
-
总结出性质来优化枚举的复杂度→P1072
-
要勤于推导式子→推导后得出贪心算法而不是一开始选择dp→P1080
-
因子和的相关性质→因子和= ∏ j ( ∑ i ( 0 k ) p j i ) \prod_j( \sum_{i(0~k)} p_j^i) ∏j(∑i(0 k)pji)→P1593
-
给出数列递推公式快速求第K项目(K很大)→矩阵快速幂→特殊情况还要使用龟速乘→P2044
-
数学推导约束优化枚举→前缀和优化方案统计→P2119
-
推导数学规律→两个点一起向上走→由数学推导快速得出一个点的祖先编号→模拟上跳→P3938
-
期望dp的逆推法→P4316
-
递推逆元快速计算→P5431
-
区间交换,求每次操作后的的逆序对数量奇偶性→若ABCDE,交换B,D,那么有影响的只有BCD→因为所有数都不相同 , 所以是/不是逆序对前后必发生转化,即逆序对数量=原顺序对数量→O(1)计算→P8449
-
列出答案关于因子个数的表达式,发现是 ∏ a i \prod a_i ∏ai→每次操作都是在一个项目上+1→每次贪心选择最小的项目执行→P9836
-
P1463→求不超过n的最大highly composite number(高合成数)→高合成数一定是由另一个高合成数乘一个素数得来→发现这类数分解质因数,随质因数增大,指数显然单调不增(贪心)→体现高合成数在LL范围内很少,所以打表。
-
P1486→平衡树→不是修改验收员工的工资,而是堆工资标准反方向修改→辞职处理:按值分裂后丢弃
-
P2152→高精度求gcd
-
P2158→发现只要x,y坐标互质即可→问[1,n]中有多少对(x,y)互质→欧拉函数是小于x的整数中与x互质的数的个数,一般用φ(x)表示→用欧拉筛筛出即可
-
P2261→把mod写出除法形式,然后数论分块
-
P2303→设gcd(i,n)=d,i/d,n/d互质→计算出[1,n/d]中有多少个数和n/d互质,假设为x→当前贡献就是xd→欧拉筛
-
P2568→枚举质数:p∈prime∑i=1∑nj=1∑n[gcd(i,j)=p]→对 gcd 进行套路式的变形:p∈prime∑i=1∑⌊pn⌋j=1∑⌊pn⌋[gcd(i,j)=1]→整理后得到欧拉函数→欧拉筛,O(n)枚举统计答案
-
P3579→枚举 [1,min(b,d)] 的所有正整数 i,看看是否可以满足a≤b/ii and c≤d/ii即可→发现b/i,d/i是一个区间,所以数论分块,每次取最大的i即可。
-
P3812→线性基
初等数论
-
扩展欧几里得变形与理解→P1082
-
扩展欧几里得→P5656,P2421
-
矩阵乘法→P1349,P1962,P1306,扩展矩阵乘法→P1939
-
同余方程组的求解→P1516,P2613
-
先写出f的递推式→矩阵优化→P5789
-
将题目转化为数学语言→欧拉函数求解→P8015
-
CRT→P1495
-
莫比乌斯反演→P2522,P3455
-
高斯消元→P3389
-
BSGS→P3846→类似折半搜索(匹配机制很像)
离散与组合数学
-
考虑划分问题为子问题→考虑递推公式→卡特兰数→P2532
-
数据范围允许杨辉三角递推→考虑答案的递推式→理解组合数的递推式→
ans[i][j]=ans[i-1][j]+ans[i][j-1]-ans[i-1][j-1]; if(c[i][j]%k==0)ans[i][j]++;
→P2822 -
简单组合→发现没有取模,需要高精度→P3223
-
Lucas 定理→P3807→$C(k_1p + r_1, k_2p + r_2) \equiv C(k_1, k_2) \cdot C(r_1, r_2) \pmod{p} $
-
类似数位dp的逐位考虑→组合数计算方案→P5367
线性代数
高等数学
最优化
-
博弈论→P1247,P2197
-
舞蹈链及其变形→P1074,P10481
-
一个单调队列→P3522
计算几何
- 二维凸包→P2742
信息论
P1494