正是懵懂的眼眸才将世事看通透,内心始终笃信爱与温柔。
- 2-sat构造方案需要学一下(另外,为什么tarjan跑出来的编号就是拓扑序的逆序?)。
好的写法
- 长链剖分好的写法。可以在dfs序列上进行长剖就是说。
- tarjan 跑出来的编号拓扑序列,因为找到一个强联通分量一定是在遍历他的所有出边走到的点之后。
- 虚树可以考虑直接给相邻lca找出来,然后排序去重,再找相邻lca即为后面那个点的父亲。
要注意的
- 想要写NTT的时候需要思考一下模数是否合适。
- 注意时间限制对常数的要求,比如三模NTT。
- 写平衡树的时候注意有点上也代表一个数。
- 动态开点线段树注意左儿子不是 o<<1,而是ls[o]。右儿子也有同样的问题。
- 写半平面交:
- 线段可以用一个点和一个方向向量表示
- 求两条直线的交点可以解方程
- 一个半平面可以通过一个向量和这个向量的左边还是右边表示。
- 每次判断上两条线的交点与这条线的左右关系来判断上一条线是否弹出
- 注意判断两条线没有交点的情况。就是说平行的线只取一条其实就可以。
- 写斜率优化:
- 注意除了计算斜率不要使用除法!
- 计算斜率也得判断分母为 0 时分子的正负来决定是 +inf 还是 -inf。
- 克鲁斯卡尔重构树
- \(n\) 个点的图的话,树上恰好 \(2n-1\) 个节点。每个点有恰好两个儿子,或者没有儿子。
- 并查集可以边新建节点边初始化。
- dijkstra算法(好像没啥特殊要记的)
- 扩展中国剩余定理
- 注意乘法的时候开 __int128 。
- 注意写扩展欧几里得的时候要注意取模。这个过程可以取模,如果只是用来求合数逆元的话。
- 常系数齐次线性递推
- 注意多项式取模的时候,如果模 \(m\) 次多项式,模完之后不见得是 \(m-1\) 次的,因为本身可能就是 1 次的,模 3 次的还是 1 次的。
- 动态凸包
- 凸包让人感觉神秘的是它需要维护的是一个圈,这是我们不希望看到的。因此考虑改成维护两个凸壳。两个凸壳公用两个端点。有人问如果两个凸壳左边右边公用的是线段怎么办。我说如果真的按照 \(y\) 轴从小到大排序,那么是不会有问题的。因为下凸壳左侧如果从小到大排序就不会出现竖直的情况。具体写的时候其实可以只写一个维护上凸壳的东西,然后将所有 \(y\) 坐标正负取反,按照上凸壳的方式将所有点排序(如果重新自己排序的话就需要按照 \(x\) 坐标相同时 \(y\) 坐标从大到小的顺序排序)就可以做到这件事情。
- 用动态开点线段树维护这件事情。如果需要分裂,可以写线段树分裂。线段树每个节点维护区间最左和最右。
- 二分的时候可以看这个节点在这个区间左儿子的最优解点和右儿子的最左节点连线的上方/下方。具体来说可以通过叉积来实现这件事情。
- 如果想回退(回退插入或者合并操作)可以通过记录目前一共有多少个节点来实现,把新加入的节点都删掉就可以了。
- push up 的同时可以维护面积。
- 平面最近点对
- 01bfs
- 注意一个点就是可能被更新多次。所以不能在第一次被更新的时候就直接标记为走过不要再走了。另外这个东西的实质好像就是双端队列在边权只有01的图上优化 dijkstra。
- bfs
- 写的时候可能要注意不要忘记弹出队首?就是说取出队首之后。
- 树套树
- 注意内层 set 的使用(比如迭代器是否合法之类的)。
- 可以优化建图。
- 主席树
- 区间修改的主席树,标记永久化。当然也可以标记下放,当成一次修改,完了之后再把这样的修改都退回去,但是常数有点大。
- wqs二分
- 看成凸壳。如果两个相邻点之间的斜率都是整数,那么二分斜率的时候可以直接使用 int 存储而不是 double 。double 容易掉精度,不好。
- 高斯消元
- 消元的时候注意每次选出的那一行必须目前还没有被当作主元行。