享受一个人在机房里面调 (DS) 的感受
感觉有些处理方式是很妙的
Luogu4655
一万年没写过斜率优化了,所以重学了斜率优化
(dp) 式子是 (trivial) 的,如下:
如果 (j>k) 同时
那么 (j) 的决策比 (k) 优
但是 (h_i) 不保证满足任何条件,所以我们并不知道这要维护个啥凸包
所以 (cdq) 分治来解决动态凸包的离线维护:
按照 (cdq) 分治优化 (dp) 的原理,先处理左侧的 (f) 区间内左边对右边的贡献,最后处理右边的答案
对于当前分治区间 ([l,r]),先按照 (id) 排序,处理左边的答案,回溯之后把左边的凸包建出来,这样满足转移都是有效的
然后把右边的点按照 (x) 排序进行转移即可
复杂度 (O(nlog n)) 或者用 (sort) 就多个 (log)
具体实现的时候也可以先把所有点的 (w) 都扔到 (f_1) 上然后每次转移可以方便一点
luogu4115
本来想套 (ZJOI2007) 捉迷藏的线段树维护直径的做法,但是交了几次发现不行
其实也就是因为那个题的边权都是正的,这题从下往上传递信息的时候会挂掉
那么还是去想点分治
每个点存到点分树夫亲的距离 (d[x]) 和 所有点分树儿子的最大值
具体维护时,用第一个堆来维护第二个堆(这里看了题解)
当然需要支持可删除堆来代替 (set) ,那么我又复习了如何写可删除堆
想了半天才懂,懂了就好说了
Luog4886
首先读明白题,当前选择的点的答案是 (dis(u,v)+dis[x o( u,v)])
可以挪的充要是所有的询问都在子树的一端,所以挪,反之就退
不太会证复杂度,但是过掉了
CF990G
大力点分治,每次直接 (O(n^2)) 合并子树信息即可
不太清楚为啥能过,但是过掉了
看题解说 (gcd) 有收敛性?
Luogu 4606
缩起来点双,那么的到一个树,显然得到只能删掉割点
所以显然搞出来圆方树,按照搞虚树的那个思想,把所有点排序
统计每两个点之间的路径上的权值和(圆点 (1) ,方点 (0))
最后统计除掉 (2) ,加上最顶上的那个点的权值得到答案
挺高明的
重新学习了如何写圆方树,写挂的一个点是
do{
g[st[top]].push_back(tot); g[tot].push_back(st[top]);
top--;
}while(st[top+1]!=t);
这里退到 (t) 就行了,不要退到 (x)
Luogu6021
这东西显然可以 (ddp)
NOIP2018 保卫王国
貌似 (ddp) 不太难写,至少求个带修最大独立集好写
那么具体问题具体分析
最小点覆盖=全集-最大独立集
必选或者不选可以权值置成 (inf/-inf) 来实现
然而不会倍增做法
HNOI2014 世界树
得到一个朴素的 (dp),设 (f_x) 表示 (f_x) 的归属,那么 (bfs) 可以得到
时间复杂度 (O(nq))
但是这样虚树的数据范围就没用了,发现其实可以分割链的贡献
不难进行若干次 (dfs/dp) 求出来每个虚树上的点的归属,设为 (bel[x])
对于一条链 ((u,v)) 分如下的情况讨论
((1)) 如果 (bel[u]=bel[v]) 那么直接找到 (u) 在 (v) 方向上的儿子 (s),贡献是 (sz[s]-sz[v])
((2)) (bel[u] eq bel[v]) 二分端点,(sz) 的贡献并不难得出来
((3)) 虚树上的点不在虚树上的子树的贡献,显然应该贡献给 (bel[u])
时间复杂度 (O(nlog^xn))
HEOI2014 大工程
建虚树,然后 (dp) 考虑每个虚树上的链的贡献即可
注意:每个链的经过次数是 (sz[x] imes (m-sz[x]))
Luogu2664
如果当前点 (x) 的颜色是从根到之的第一次出现的,那么它对于根的其它子树的答案有 (sz[u]) 的贡献
那么我们现在仅考虑如何求得跨过 (root) 的答案
考虑记在当前分治重心的总权值和为 (sum) ,那么其对于 (ans[x]) 的贡献要减掉 (x) 子树里面的点的贡献
接着考虑在 (x o root) 的路径上的点,设个数为 (num) 不难得到贡献应该是其它子树里面的和:((sz[root]-sz[x]) imes num)
大体思路并不复杂,魔鬼永远在细节:分治重心的处理和子树内部颜色的重复
需要想清楚,想清楚了并不复杂
归总,写很多个 (dfs) 就行了
注意!!点分治找重心的时候记得清空 (f[x])
Luogu3714
点分治,接着考虑如何合并两个子树的信息
按照上个题的思路,两个不同颜色的合并需要减掉对应的代价
具体而言,对于每个扫出来的子树,合并长度为 (i) 的路径信息就查 ( exttt{[L-i,R-i]}) 最大值
所以搞俩线段树,颜色不一样的时候线段树合并就好了
Codeforces150E Freezing with Style
首先把中位数都离散化下来,然后点分治的过程中进行二分
以上都是从 ( exttt{WC2010重建计划}) 中套出来的 ( exttt{trivial}) 套路
显然是考虑对于每个分治重心维护跨过其的最大的两个链进行合并
中间套个单调队列维护两个信息就行了
貌似单调队列写了一万年,为啥都快省选了单调队列这种东西还要调……
Luogu5787
线段树分治的思想维护可撤销并查集即可
重新学习了如何写可撤销并查集
同时,对于这种二分图判定的问题 ,可以考虑拆点来维护
也就是对于连边,即 (merge(u,v+n),merge(v,u+n))
如果 (find(x)=find(y)) 就等效于有奇环
Luogu DDP
如何求带修改的最大独立集?
把转移分成两个,即 (f[i][0/1]) 表示(不)选择当前点的答案
同时 (g[i][0/1]) (不)考虑重儿子当前点的答案
这东西可以写成一个矩阵乘法的形式
那么每次被更改的 (f,g) 数组构成一条链,对矩阵开线段树维护即可
卡常方式貌似是用 (LCT) 或者循环展开
有效的是每个重链开线段树来降低 (query) 的复杂度
Luogu4183
最近做的最高明的题了
奶牛想跑,走的显然是最短路径
那么如果对于路径上的所有点,都有 所有农夫到这个点的距离比牛到这个点的距离大,那么这条路径合法
所以可以得到一个 (O(n^3)) 的做法:对于当前牛在的点 (x) ,枚举这个的叶子节点 (y),如果其它的叶子 (z) 是满足 (dis(z,y)>dis(x,y)) 那么这个点需要放人
考虑到能比当前点到一个叶子节点距离更小的一定是当前点向该方向的一个子树里面的点
对于一个根到叶子的路径长度为 (d_1),设其它叶子到这个叶子的距离最小为 (d_2)
那么对于和当前分治重心的距离不超过 (d_2-d_1) 的所有点的答案加 (1)
查询叶子到叶子的最小距离可以多 (dp) 几下
所以最后就是支持距离修改,树上差分即可
代码还没写,所以以上全是口胡
HEOI2016 序列
因为已经不会写 (cdq) 了,所以写了这题
Luogu 3364
除了拗口的题面,这题还是个 (cdq) 板子
Luogu 2487
第一问是三维偏序
第二问要记录转移点,考虑 (precentage_i=frac{pass_i}{sum})
所以正反两次统计从这个点开始的和结束的乘起来就能得到答案
不再写 (cdq) 模板题了,浪费时间精力
Luogu4849
然后就写了个 (cdq) 套 (cdq) 的模板题……
由 (cdq) 的原理,考虑 (sort) 掉若干维之后剩下的维中左对右的贡献
处理低维 (cdq) 的时候我们本质上是把左侧的 (a) 只转移给右侧的 (a)
那么先做一次 (cdq) 把 (b) 也同样操作一下,标记上是 (L/R)
所以 (ain L,bin L) 的才可以添加进入 (BIT) 同时 (ain R,bin R) 的才可以查询
再套上个 (cdq) 支持多维偏序即可
代码其实 (trivial) ,想法确实有意思
Luogu6007
设 (f_{x,y}) 表示到 ((x,y)) 的最小步数
转移是 (trivial) 的,(f_{x,y}=min(min((f_{x-1,y},f_{x,y-1})+1,f_{p,q}[qle x,qle y]))
既然是个 (cdq) 的题目,那么总该有点 (cdq) 的求最大值的样子
所以考虑转化成最多节省了多少步,则答案为 (2m-f_{m,m})
每次支持查询 ((1,1) o (x_1,y_1)) 的最大的 (f) 即可
稍微转化一点的 (cdq)
目前不会 (BIT) 的 (Theta(nlog n)) 的做法