数据结构
线段树
注意:空间开4倍
神奇标记
From8.26 Test_zsy(CPU监控)
如果一个点权为\(val\)的点被打上了\((a,b)\)标记,那么他的实际点权为\(max(a+val,b)\)
干啥滴?
标记不下放
- 区间加标记不下放,维护区间max或者最大值
方法是当前\(tag\)维护当前区域标记,\(t\)维护左右儿子的\(max+tag[now]\),并没有快多少,如果仍然忘记见提交记录
并查集
维护二分图
并查集每个点维护是否要改颜色,然后按秩合并/按大小合并即可
实际上可以说是用期望树高为\(logn\)的树形结构维护信息
维护后继位置
快速得到后继位置
- [BZOJ2054]疯狂的馒头 维护数列的后继位置
对一个数列进行\(10^7\)次区间覆盖,查询最终颜色。
倒序做,每次做完一个区间把\([l,r]\)的并查集父亲指向\(r+1\),表示扫到该区间,要从\(r+1\)开始染色,这样就可以快速得到下一个染色的位置,复杂度为\(O(n)\)
- [BZOJ2238]Mst 维护树形结构的后继位置
对树上路径进行染色,查询最终颜色。
路径拆成直上直下的两条,\(x,lca、y,lca\),于是每次弄完把\([x,lca]\)的并查集父亲指向\(fa[lca]\),就可以类似数列一样快速求得下一个位置了,复杂度为\(O(n)\)
堆
对于所有的父子结构,一定都有父亲的优先级大于左右儿子的优先级
可并堆的可持久化
左偏树可持久化,每次合并两个堆,只需要给经过的\(log\)个结点复制一遍就好了
#define lc H[x].ch[0]
#define rc H[x].ch[1]
struct heap {int ch[2],dis;double w;}H[M];
int Merge(int x,int y)
{
if(!x||!y) return x+y;
H[++node]=H[x];x=node;
if(H[x].w>H[y].w) swap(x,y);
rc=Merge(rc,y);
if(H[lc].dis<H[rc].dis) swap(lc,rc);
H[x].dis=H[rc].dis+1;
return x;
}
这个可以用来完成\(k\)短路问题
dsu on tree
姑且叫它数据结构
方式&原理
步骤:
- 先递归做轻儿子的答案,再递归做重儿子的答案
- 暴力把当前结点的轻儿子扫一遍统计答案
- 如果当前结点是递归下来的轻儿子,扫一遍把答案清空,否则不做处理
要求: 离线算法
复杂度: \(O(nlogn)\)
分析:只需要考虑每个点被扫的次数,树剖下来每个点到根的路径最多有\(log\)条链,每逢轻重链交替的时候就会暴力去扫,于是每个点最多只会被扫\(log\)次,复杂度得证
适用范围
适用一些子树信息不好统计的题,可以类比于树上莫队
- 统计子树内数量最多的颜色的编号之和(Codeforces600E)
- 统计子树内距离\(i\)点不超过\(k\)的点的颜色数/某权值之和(BZOJ4771七彩树离线版/[湖南集训]谈笑风生)
?
原文地址:https://www.cnblogs.com/xzyxzy/p/9903894.html
时间: 2024-10-03 20:43:31