学习笔记——线段树合并

前言

好像机房人人都会这个东西,就我不会,只能爬去学一下。。。

这是啥

好像是个挺没用的东西,感觉主要处理树上数数什么的问题,都可以用 dsu 神器来替代。但也有的问题不能用 dsu 的,比如这题

来考虑这样一件事,就是说,我们有的时候希望对于每个点都维护一棵线段树,并且希望能够实现一些鬼畜的♂操♂作♂,这时候需要用到线段树合并。

但是我们考虑这样一件事就是说,由于是合并,那么在合并之前必然是有很多的线段树,所以传统的线段树肯定是没法用的。于是——

动态开点线段树

这个东西还是比较简单的,就在插入元素的时候不采用堆式建树,而是采用记录左右儿子,然后在插入的时候访问到一个节点才会去开这个点的空间,这样就可以开下空间了。

注意一点是:动态开点的空间要开 20 倍以上,不然一开始空间会不太够。

void ins(int &i,int l,int r,int v){
	if(l>r) return;if(!i) i=++tot;
	tr[i].l=l;tr[i].r=r;
	if(l==r){tr[i].mx++;tr[i].id=l;return;}
	int mid=l+r>>1;ins(ls[i],l,mid,v);ins(rs[i],mid+1,r,v);
	pushup(i);
}

线段树合并

和 fhq 的合并差不多。

int merge(int a,int b){
	if(!a) return b;
	if(!b) return a;
	ls[a]=merge(ls[a],ls[b]);
	rs[a]=merge(rs[a],rs[b]);
	pushup(a);return a;
}

习题

我们掏出这个题单

发现最后只询问一次,不需要树剖,直接树上差分。但是发现需要维护很多不同的颜色,所以考虑对每个节点维护一个线段树,然后向上做的时候合并就可以了。

上一篇:ChannelSftp.ls()在windows系统下性能缓慢的说明


下一篇:python-rong-day04