各知识点运用技巧总结

动态规划板块

背包

  有负体积的时候可以把数组下标平移一段,01背包压维时,正的倒着跑访问的是上一层的,负的正着跑也访问的是上一层的。

  二进制拆包:多重背包问题枚举for(j=1;j<=num;(j<<=1))之后当成01背包倒序枚举V

期望

  如果转化为建图模型,对于边(u,v)有的题目是从v->u,这样是由u的后继推u

树形

  换根dfs的时候一定要把图画出来,比如对于节点u,其父亲为根的情况已经被处理,那么就以fa为根,画至少3个儿子(包括u),然后u也多画几个儿子,一定要把情况枚举完。

  时刻注意状态转移时for循环是正序还是倒序。

  边界一定要清楚,把i,j能跑到的地方都看一下有没有意义。

区间

状压

记忆化

线性

数学板块

数论

  有的gcd的题目是可以打表找规律的。

  有的gcd的题目是可以大概感性证明一下就开始写的。

  

组合数

递推&矩阵乘法

图论板块

最短路

  类似于华容道,要会表达状态,建模过程:表达状态$->$找到状态间的代价$->$建图。

  最短路可以记录起点,如找集合V内两两之间最短路的最小值,可以记录起点的颜色,在最短路算法中转移,正反跑两边,把最短路连接起来。

  如果从多个起点开始跑,那么dist的意义就是到这些点最短路的最小值。

  Floyd判负环:dist[i][i]初始为0,跑完之后<0则有负环。

  spfa在队列中保存的更新信息的意义是"这个点被更新过,因而有可能通过与它连接的边更新这些边的其它端点"。直到队列为空,此局面表示"没有一个结点可能更新其它的结点"。

  spfa可以转移有后效性的带环的图上DP

  模意义最短路dist[i][j]表示起点到i,在%p意义下为j,所用的最小代价。

强连通

  tarjan+toposort+dp懂得。

双联通

差分约束

  有的题统计个数,可能出现SCC,且每个SCC之间的限制不会影响SCC内部的限制,那么答案就是每个SCC内的最长路+颜色数。

2-SAT

基环树

欧拉回路

网络流

生成树

拓扑排序

LCA

  有的题可以转化为LCA问题,类似于跳跳棋的神题。

  

数据结构板块

并查集

  并查集缩边乱搞。

栈和队列(单调栈和单调队列)

  单调栈:一般用来找向左向右第一个比当前元素大(小)的值,一般在弹栈的时候更新,许多题目都是在弹栈的时候用栈顶元素的信息更新下面的,或者用栈顶元素的信息更新加入的,从而达到统计的目的,如最大子矩阵,每次弹栈时,如果栈顶大于当前高度,那么比第一个比栈顶小的就是第一个比当前高度小的,我们用栈顶更新当前高度再入栈。还有的题目用单调栈统计信息,总之单调栈的题目基本都是围绕左(右)边第一个比当前元素大(小)的元素,有时还有他们之间的距离在一起搞事。

  单调队列:先弹队首,再弹队尾,再入队,(再转移)。

堆(可并堆)

  堆的删除:q1为有的元素,q2为要删除的元素,控制q2不为空且q1的堆顶等于q2的堆顶,把q1,q2的堆顶一起弹掉,记得判断q1是否为空

  堆可以用来维护可反悔的贪心,一般要推一下式子,考虑如果开始对i进行了处理,并认为它是最优解,那么如果后面j可以同时消除i,j的影响,那么显然此时有更优解,那么就用当前的代价减去之间的最优解,得到中间的差值就相当于反悔了一步,重新选择。

线段树(权值线段树,主席树)

  线段树的区间维护能力还是很强的,权值线段树一般用来解决第k大问题,就是线段树二分,线段树可以套很多东西。

  套堆维护带删除的区间最值,不需要pushup和pushdown,把元素扔进去自动就更新区间信息了

  套权值线段树维护区间k大值。

  还有套路就是开K棵线段树维护区间K元素的信息

  还有一些不同于区间和,区间最值的东西,比如颜色数,最长单调子串,或最长0串等,只考虑把两个区间的信息合并成一个这一步即可

  比如维护最长上升子串,我们可以维护从l开始的子串长度,从r往前的子串长度,以及区间[l,r]的子串长度,然后用锁区间线段树的写法query时直接返回结构体,跨越smid时重载一下运算符合并一下就行了。

树状数组

  学会对各种东西建BIT,可以是值域,可以是区间,还有对某个权值,如前缀和建BIT的。

  

线段树合并

  遇到动态加边时,可以用并查集维护根节点,把其中一棵树的根上的线段树合并到另一棵上并以之为新根,并查集要定向merge。

  一般想到每个点开vector合并的东西都可以拿线段树合并写。

平衡树

Link-Cut tree

树链剖分

算法板块

迪法师

  对于一棵树,有的题目可以把每个dep的点用vector存起来然后按照dep跑dfs,一般题目意思比较明显。

  一定要理解统计语句放在dfs前后的区别。

  

 

博法师

  跑棋盘类的题目,比如一个点到达的是一个矩形之类的,可以用对每一行用并查集把终点所在列缩起来,强制让每个点被遍历一次。

  getid(x,y)=(x-1)*m+y,懂得。

  getid(x,y,k)=((x-1)*m+y)*4+k),加入了一个点和它四周的某一点的状态,相当于分层图。

  

二分

模拟

贪心

  靠智商吧QWQ。

  有的题可以按二进制位贪心

A*

启发式合并&dsu on tree

字符串

hash

  $SH[i]=(SH[i-1]*base\bmod p+s[i])\bmod p$

  取出$[l,r]的hash$值:$hash[l,r]=(SH[r]-SH[l]*base^{r-l+1}+p)\bmod p$

  如果维护集合且带删除的,可以个集合中的点赋随机值异或起来,这样就能删了。

  hsah值和排序常连用。

kmp

trie

  Trie上可以跑DP。

  Trie可以解决许多字符串前缀的问题。

  Trie解决异或最大值。

STL

vector

  众所周知,vector+二分可以处理很多东西,,,vector<int>().swap(a)(a为vector)可以有效节省空间,真的有效。

set&multiset

  可以重载运算符,自带二分查找且更快,对于维护有修改和删除的信息,或者第k大的信息,一般用这东西维护,删除set可以支持s.erase(val),s.erase(iter),set.erase(begin,end),multiset还是用s.erase(find(val))或者s.erase(iter)吧。

  有的时候要在收尾加inf和-inf来判边界

map

  可以用来节省空间,比如map<int,各种东西>a,相当于开了任意多个(各种东西),也可以时stl。map还可以看成一个pair,定义指针it:typedef<map<int,各种东西> >::iterator it,那么it->first就是前面的int,it->second就是后面的(各种东西),而且用it从a.begin(),到a.end()可以遍历当前map的所有元素,至于按照啥顺序,,,蒟蒻不知道,也不会有这么鬼畜的题目吧。。

posted @ 2019-11-09 23:05  EPs1l0h  阅读(195)  评论(0)    收藏  举报