专栏文章
杂项全家桶
个人记录参与者 1已保存评论 0
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 0 条
- 当前快照
- 1 份
- 快照标识符
- @miql95w8
- 此快照首次捕获于
- 2025/12/04 06:38 3 个月前
- 此快照最后确认于
- 2025/12/04 06:38 3 个月前
二分队列
这玩意浪费了我12h。
考虑设 表示坐 号列车刚到终点时的最小花费,将 按照发车时间 排序,则有:
其中 表示 。
注意到 里面的东西具有决策单调性:将 按照下车时间 排序,当 时,设 由 转移, 由 转移,则有 。
( 从 增加到 的过程中,所有决策点 的代价都增加了 ,相对大小不变)
对于每一个决策点,维护其作为最优决策点时 的取值区间,用队列维护。产生新决策 时,在最靠后的一个取值区间 (对应决策 )上二分,找到满足 的最小的 ,使 的决策区间变成 , 的决策区间为 。加入队列。
由于询问的 单增,所以查找最优决策点时,弹出前面所有 的决策点即可。
而 本身的值离散化后用主席树维护即可。
注意事项:
-
因为有 的限制,所以需要对每一个岛屿维护一个二分队列。
-
需要以 单增的顺序转移,而 却需要以 单增的顺序插入队列。所以不能转移完一个 就把它扔到队列里。
-
二分队列本身复杂度 ,查询 的复杂度 ,总共 ,需要大力卡常。
性质
-
树形dp时,如果一个节点的 只有 个值是有用的,则 一遍只需要 的复杂度。
-
有时题目要求维护的东西有效期是一个区间,那么可以考虑在时间轴升序的过程中模拟/整活。例えば:CSP-S 2024 T4,this
长链剖分
如果要维护的dp方程为 ,即信息均以绝对深度为下标,则可以通过长链剖分达到 O(n) 的复杂度。
具体地,每次将深度小的子树向深度大的子树合并。因为一条长链只会在链首完成一次合并,而所有长链的长度和为 ,所以总长就是 。
2-SAT
考虑将一个变量 拆成两个点 和 。一条边 表示如果 成立, 一定也成立。连了 一定也要把 (逆否命题)连上,虽然我还不知道为什么。
如果 可达 ,则 只能取 False。如果 可达 ,则 只能取 True。如果互相可达,没救了。否则都行。
可达性可以缩SCC后看拓扑序。
可持久化线段树
怎么维护一个支持区间加、区间求和、区间复活的可持久化线段树。正经的主席树是单点加、区间求和,全局复活。先考虑做出来单点加。
考虑对于每个节点维护一个 lazytag,pushdown 的时候将左右儿子都复制一个新的出来,下传到新的节点上。
然后是区间复活。找到要复活的版本,把该版本需要复活的 个节点 copy 出来,把当前版本对应的 个节点直接改成复活节点的样子就可以。
点减边容斥
如果题目描述了一个函数 ,要求我们得出序列上每一个区间 的值之和,但是我们只能得到 的话,考虑怎么容斥。
考虑得出 ,那此时每一个长度 的区间 被算了 次,需要减掉 次。那可以再减去 ,此时正好就对了。
wqs 二分
F 题放 wqs 二分板子,喜欢我们 Educational Round 吗。
设原序列已经有 个
docker 了。则我们可以分别得到最多两个备选的 docker 数量 ,最优解一定在 或 取到。达到 只需要破坏 docker,故 的答案为 。难点在于计算 的答案。我们可以设 表示在 上创建出一个
docker 的修改次数。然后容易得到一个 的 dp。设 表示在 上创建 个 docker 所需的最少修改次数,则有:注意我们其实只需要 , 且若设 ,则 是单增且下凸的,所以可以直接进行 wqs 二分。
具体地,二分一个斜率 ,转为求 的最小值。在 dp 中的意义是,每做出一个
docker 可以额外赠送 个修改次数。此时不需要记录做了多少个 docker,故第二维可以省略:转移的时候同时记录做了多少个
docker,这样做完一遍 dp 可获得一个二元组 分别表示消耗的修改次数(可以是负数)和做出来的 docker 数量。若 ,代表取到 的 更大,反之更小。直接二分即可。但是多点共线的时候有概率挂掉。我们在二分过程中用每一个 得到的一对 都可以算出一个 。共线时,。因为 是下凸壳,这个计算出来的答案只会 真实值。直接取 即可得到真实值。
凸包闵可夫斯基和分治优化dp
以下所有凸包不妨全认为是下凸。
两个凸包 的闵可夫斯基和 可以在 的复杂度内求得,且 同样为凸包。设 为 和 的差分序列,则 本质上是要在其上选择两个长度和为 的前缀,使得求和后最小。因凸性, 和 均单调不减,直接贪心(归并)选择就是对的。具体来说:
CPPvector<int> Conv(const vector<int> &f,const vector<int> &g){
vector<int> h; int p1=0,p2=0;
while(p1<f.size()&&p2<g.size()){
h.push_back(f[p1]+g[p2]);
if(p1==f.size()-1) p2++;
else if(p2==g.size()-1) p1++;
else (f[p1+1]-f[p1]<g[p2+1]-g[p2]?p1++:p2++);
}
return h;
}
若一转移 ,其中 均为凸函数,直接操作可能是 的。但是这是凸包连加,若化为 (其中 , 是求闵可夫斯基和),分治递归下去即为 。
这个操作和求一次函数连乘(分治,)相似。
记 表示在 上做出来一个
MOO 的花费,然后设 表示区间 中,左边空出 个格子,右边空出 个格子,做出至少 个 MOO 的最小花费。转移时枚举 是 MOO 的哪一位(或者根本不在这里放 MOO),闵可夫斯基和后直接取 即可。复杂度 ,因为对于长度为 的区间来说,其上的凸包长度只有 。相关推荐
评论
共 0 条评论,欢迎与作者交流。
正在加载评论...