OI中一些常见实用的套路【更新中】

数据结构

  • 在维护树上路径时,如果只是点的独立的加减,可以考虑用括号序来维护(拆成两部分)
  • 需要求树上很多路径中k近/距离和 一类,考虑点分治/在点分树上解决。
  • 子树求和可以转化为DFS序上区间求和
  • 树状数组可以区间查询/修改(差分)
  • 需要查询序列上区间数据结构,只要满足总和是可以接受的范围,可以用线段树,每个区间维护一个这样的数据结构(例如AC自动机等)
  • 多维偏序问题,排序可以降维,CDQ分治可以降维,剩下只需要树状数组/线段树
  • 树上连通块有概率出现,再加上和的次方,往往可以拆开来,变成任意选K个可重,有序的点,考虑贡献。
  • 当又需要分块,每个块维护数据结构时,块的大小考虑调整(不再一定是 n \sqrt n n )(平衡规划)
  • 同理,对于图论中度数总和固定、多组询问查询的点数固定,查询点需要枚举出边,但可能一直查询度数比较大的点。此时考虑平衡规划。(询问点个数/度数 大于/小于 n \sqrt n n 分开来做)
  • 对于点分治时两个不同的子树的结果混在一起需要判掉,可以考虑几种办法:
    • 在点分树上儿子记录当前点分树子树中的节点到父亲的结果,计算父亲时在这里减去。
    • 维护DFS序,两个子树对应两个无交的区间,可以考虑区间分裂一类的做法。
  • 对于有很多颜色的点,需要对相同颜色计算影响,可以把每个颜色拉出来在DFS序上搞事情(相邻+1,lca-1一类)
  • 如果又加上了深度限制,那么相当于除了DFS序这一维,还多出了深度这一维,可以考虑(主席树/CDQ分治/二维数据结构),也可以将点排序以后用线段树维护DFS序。
  • 对于这样一类问题:每个元素(边/点之类)具有权值/权值范围,每次只需要考虑权值是一定值/一定范围的元素的影响,可以考虑建立权值线段树,将元素的影响挂在线段树对应的所有区间上,查询就查询区间。
  • 当需要查询树上是否存在一条路径过两个点时,可以将路径端点记在DFS序上,然后两点子树查询,这就变成了两个区间数点的问题(二维偏序/扫描线/DFS动态树状数组维护增量)
  • 需要维护序列轮转问题时,不一定非要splay,如果轮转很特殊时可以采用线段树+预留空位的形式转化为单点修改。
  • 想要存储很多东西的0/1状态,且需要支持xor/or/and等操作时,bitset是个非常好的选择(计算复杂度可以除以32),别忘了bitset还有左移右移操作,可以用来处理+或-
  • 替罪羊树跑的很快。
  • 带旋转的平衡树是很难在内层套上线段树的,所以平衡树套线段树应考虑替罪羊树或无旋treap
  • 一堆操作+询问的题,如果很容易处理一堆操作对一堆询问的贡献,可以考虑分治,你可以考虑权值/时间分治
  • 一棵Trie如果要维护+1异或,那么不妨从低位到高位建Trie
  • 线段树分治往往应用在一些对象知道插入和删除时间时,维护合法情况很容易,但撤销非法情况比较困难时。
  • 要算一个点和一堆点的距离的时候,可以考虑将距离拆成两点深度和-2*lca深度,lca深度可以表示成lca到根的节点数,那么直接树链剖分链上区间加区间求和即可。
  • 要做一堆数的lcm的时候,可以考虑每个质因子的指数最大值,然后将每一个 p 1 , p 2 . . . , p k p^1,p^2...,p^k p1,p2...,pk都看做一种颜色,每种颜色的权值为p,然后相当于是求每种出现过的权值的积。
  • 对路径边权最大值有限制,可以考虑克鲁斯卡尔重构树。
  • 矩形加,单点求值,可以考虑拆贡献带修主席树前缀和,也可以直接KD树(线段树+splay显然很蠢)

图论

  • 求点双连通分量栈中仍然可以存点,圆方树维护起来很方便。
  • 无向图中最大值最小的路径一定在最小生成树上
  • 合并两个连通块的直径,直接比较四个端点两两连起来的长度即可。
  • 一些有代价的完美覆盖问题,选格子有行列限制有代价/收益的题往往考虑网络流。
  • 看到数据范围只有几十或者几百,然后诸多限制,要最优化一些东西,也可以考虑网络流。

多项式

  • 碰到诸如 ∏ i = 1 n ( 1 + p i x ) , ∏ i = 1 n ( 1 + i x ) , ∏ i = 1 n ( i + x ) \prod\limits_{i=1}^{n}(1+p^ix),\prod\limits_{i=1}^{n}(1+ix),\prod\limits_{i=1}^{n}(i+x) i=1n(1+pix)i=1n(1+ix)i=1n(i+x)的时候,先不急着分治NTT,它可以倍增在一个log的复杂度求出。

计算几何

  • 要处理出一个平面图的所有区域时,有一个很方便的做法:将所有点的连边按极角排序,每条边的两边各建一个点,枚举每个点的所有连边,相邻的边夹着的区域对应的两个点用并查集连起来,这样得到连通块,每个连通块就是一个区域了。

其他

  • 如果遇到 n 3 n^3 n3的转移矩阵,但是我们一次只想知道的结果是一维的(即暴力乘的复杂度是 n 2 n^2 n2),那么可以考虑倍增预处理转移矩阵的幂,求出转移矩阵 2 0 , 2 1 , 2 2 . . . 2^0,2^1,2^2... 20,21,22...次的结果。询问的时候只需要 n 2 log ⁡ n^2\log n2log而不是 n 3 log ⁡ n^3\log n3log,预处理则是 n 3 log ⁡ n^3\log n3log,总的复杂度就可以变成 q ∗ n 2 log ⁡ + n 3 log ⁡ q*n^2\log+n^3\log qn2log+n3log
  • DP时,如果状态很大,结果很小,可以考虑能否将结果与状态互换。
  • 涉及网格图带权,行列选择限制/覆盖一类的问题,可以考虑网络流。
  • 一个经典问题:有一个序列,给出若干个区间,问有多少种选法使得选出的区间能覆盖整个序列。 我们考虑容斥,显然容斥系数是(-1)^强制不覆盖的位置个数,记f[i]为前i个位置都已经确定了,第i个位置不选的方案数和,它可以从 f [ j ] ∗ ( − 1 ) ∗ 2 k f[j]*(-1)* 2^k f[j](1)2k转移而来,我们把所有区间挂在右端点,从左到右扫的时候做区间乘法即可。
  • 一个小数如果结果很多位,算乘积之类得到,可以考虑用对数
  • 6
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值