技巧

北战南征 提交于 2019-12-04 04:01:19
  1. 生成匹配的括号序列,只需模拟一个栈,记录栈中的括号数即可(CF1015F,CF508E)。
  2. AC自动机算法在匹配时,在fail树上的链将都被匹配,所以经常与树上算法联合使用(luogu P3796,luogu P2336喵星球上的点名)。
  3. 平面图的最小割就是对偶图的最短路(每个面看做一个点,相邻的面看做边)(luogu P2046海拔,luogu 狼抓兔子)。
  4. 求第k小值(k不大),可以采用A*算法,要保证每种状态都能被扩展出,且扩展出的状态非递减(luogu 超级钢琴,K短路,OVOO)。
  5. 互质数的选择,当质因数较大时采用分组背包,较小时状压记录,以平方根为界(luogu寿司晚宴)。
  6. 有时,权值线段树可以代替treap,能减小常数和代码量(luogu 郁闷的出纳员)。
  7. 有时,线段树可以代替splay,方法时记录每个位置是否有元素,查询第k个值时线段树上二分(NOIP2017 列队)。
  8. 在一棵树上统计子树信息,如果子树信息不能快速合并,可以采用dsu on tree算法(luogu 雨天的尾巴,回文路径计数)。
  9. 对于状态转移有环的动态规划,使用如下方式求解:
    1. 若转移里没有max/min,只有加减乘除运算,可以建立方程组,通过高斯消元在O(n^3)得出解。
    2. 若转移只是对一些元素取max/min(或第k大/小值),再加/减一个值,可以建图,使用dij或spfa求解。
    3. 若u依赖v,且若v能更新u,则dp[u]>=dp[v],且求的是min(例如dp(u)=min(S(u)+∑dp[v],K(u)))。
      每次:
      1:把值最小的点标记
      2:if 一个点u依赖的所有v都被标记
      计算dp(u),并标记u,
      3:回到1
      直到所有点被标记。
      就结束。
      4.若2,3都不满足,可以使用如下方法:
      先把每个点都入队,每次从队首取出u,并计算dp(u),若dp(u)发生更新,则把依赖u的v都加入队列(前提是v不在队列中)。
      这个方法很像spfa,但时间复杂度最坏为O(nm)。
      例题:模拟赛tiger,luogu 骑士游戏
  10. 离线处理以及强制在线:
    1. 离线处理可以把询问排序,并按照顺序求解。强制在线可以全部处理后可持久化(NOI2018 归程)。
    2. 离线处理可以倒推。
    3. 离线处理可以得出每种操作的时间序(loj121 动态图的连通性)。
  11. 当处理一个要求整体满足的问题时,可以只考虑局部,当所有的局部都满足时,整体就满足了(luogu 双栈排序,NOI2018 冒泡排序)。
  12. 当两个特别大的数相乘后取模时,要使用快速乘。
  13. 处理区间内出现过的数时,可以求出每个数的后继,然后就变成了区间内大于某数的数(luogu HH的项链)。
  14. 遇到用若干个数相加组合成一个数的问题,可以考虑同余最短路(NOIP2017 小凯的疑惑,墨墨的等式)。
  15. 边权只有0,1的图的最短路可以用bfs求解。
  16. 在涉及到连通性,以及最长路等问题要考虑缩点(受欢迎的牛)。
  17. meet-in-the-middle 算法:BSGS优化
  18. 第k小问题:容斥 (秘密袭击)
  19. 线段树分治,线段树建图,线段树扫描线
  20. 树链合并,暴力树链合并,access均摊。
  21. 后缀自动机跳fail的注意事项 (压缩字符串)
  22. 仙人掌,圆方树。
  23. 平方和问题:考虑平方的实际意义 (二维枚举,二维dp)
    24.网络流最小割模型
    25.倍增(有时可以使用fft)
    26.欧拉回路构造:
    27.矩阵乘法两种形式:
    1.数列递推,每次生成一个。 2.高维递推优化,每次推进一层
    28.枚举,算贡献
    29.启发式,有时可以做到log
    30.模拟网络流(数据结构实现增广),堆模拟反悔操作
    31.两种容斥原理:交集,并集
    32.三元环枚举,按度数将边定向。
    33.某种在线-->离线:建立线段树/树状数组,当某个区间都被加入时,离线处理,要求询问区间分裂后能合并结果。
    34.树统计(效率):线段树合并>启发式合并=dsu on tree
    35.很多树形数据结构都可以打标记(线段树,splay,左偏树)。
    36.带权二分:若选择dp等满足凸性,可以用直线切割凸包,将选的代价修改,通过二分找到合适的位置。
    37.处理类似重复子串的问题,可以考虑枚举长度L,然后每隔L放一个关键点。
    39.2-SAT:a->b即!b->!a 两条边都要连
    40.注意:不要3数连乘 不要int×int 不要忘记负数 不要忘模 (long long范围)
    41.通常的树持久化方法:每次新建一个根。
    42.持久化技巧:版本树(离线)。
    43.基环树方法:将环提出,变为森林,对每棵树计算,然后合并。
    44.分类考虑:一部分满足种类数小(预处理),一部分计算快,可以分类求(通常平方根为界,但实际上有偏差)。
    45.易忘的: 线段树合并
    分块(44)
    差分约束
    预处理
    46.在题目涉及到所有点对的最大流/最小割时,可以通过最小割树,将其转化为树链上的最小值。
    47.每次找一段删除,删除后自动合并解决方法:
    先设dp(i,j)表示考虑i~j的结果
    然后,考虑i这个点的情况:i一定是和之后的几段一起合并后删除
    例如:i j
    -----*****--@@-&&&&&--------
    而中间的几段一定不能一起删除

    因此,像
    ------####------#####-------

    这种情况是不可能的
    所以,中间的段就是单独的子问题了。
    还要加一组状态k,表示之前的连续段的信息。
    48.splay,lct注意事项:
    1.旋转时fa的连接。
    2.旋转时新根的fa。
    3.旋转时旧根的fa的儿子要赋值为新根。
    4.维护标记:
    1:旋转后,2次上传
    2:splay前,下放标记
    3:access更换重儿子时,上传
    4:cut后,上传(也许)
    49.在处理覆盖问题时,可以用并查集维护每个点向后第一个未被覆盖的位置(包括自身),比线段树快,树上覆盖也可以。
    50.传有数组的结构体要尽量用引用。
    51.模数要用define或const!!!!会快些
    52.只要两个子游戏没有关联了,就可以用sg异或了。
    53.最小生成树更新:只需判断环的最值即可
    54.笛卡尔树:RMQ之和,单调栈
    55.用54的方法,计算最大矩形时,除了单调栈,还可以递归,就是每次找到最小值,并递归它两边的区域。
    56.关于匹配的容斥:若有被多次匹配的,就有没被匹配的,按照没被匹配的进行容斥。
    57.m个节点的所有lca在O(m)级别,可以用虚树。
    58.行列式,高斯消元等的乘法值要预处理出来,否则会错,就是 int t=1llsz[j][i]ksm(sz[i][i],md-2)%md; 。
    59.除法,逆元可能被卡(虽然模数是质数,但除数模完后,可能是0)。要尽量避免求逆元。
    60.翻硬币游戏,只要选的硬币是反转的硬币中编号最大的即可。也可以把翻转理解为添加。
    61.奇环的判断使用黑白染色。
    62.图上的所有MST,满足:

    1、对于任意权值的边,所有最小生成树中这个权值的边的数量是一定的(根据克鲁斯卡尔算法即可得出)
    2、对于任意正确加边方案,加完小于某权值的所有边后图的连通性是一样的
    3、对于相同权值的边,任意顺序都是可以的。

63.给定树上若干的点,求最小生成树大小,可以按照dfs序排序后,用总深度减去相邻的lca的深度,再减去所有的lca的深度。
64.建虚树的步骤

1、将点按照dfs序为关键字排序
2、将第1个点压到栈当中,开始构建虚树
3、枚举到下一个点u,计算u与栈顶点v的公共祖先lca
4、假设栈中栈顶下方的点为w(若栈中只有1个点就直跳过这一步),若w点的深度大于lca就把v向w连一条边,并且弹掉v,重复此步,否则就到下一步
5、若lca不是当前的v,那么就把lca和v连边,把v弹出,如果栈顶没有这个lca那么就压入lca,否则不做任何操作
6、最后把u压入栈中
7、回到3操作枚举下个点,直到枚举完了所有点
8、把栈顶v与栈顶下方的点为w连边,并且把v弹掉,这么做直到栈里只有一个点,这个点就是虚树的根了

为了方便,有时把1也加进去。
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!