Loading

学习笔记——线段树合并

前言

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

这是啥

好像是个挺没用的东西,感觉主要处理树上数数什么的问题,都可以用 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){
		//加上信息 
		return;
	}
	int mid=l+r>>1;
	if(v<=mid) ins(ls[i],l,mid,v);
	else ins(rs[i],mid+1,r,v);
	pushup(i);
}

线段树合并

由于这个空间比较玄学,我找了好多地方,总结:空间一般能开多大开多大,一般开到 \(O(n(\lceil\log n\rceil+1))\) 就可以了。

为什么是这个东东?

由于我们是动态开点,那么初始的时候每个节点上的线段树空间是 \(\log\) 的,由于线段树两倍的尿性,我们向上取整。

而合并的时候相当于把两棵线段树叠在一起,所以总空间就是 \(n\log n\),但是又考虑到线段树两倍的尿性,我们加个 \(1\)

下面是代码。

int merge(int a,int b){
	if(!a) return b;
	if(!b) return a;
	if(tr[a].l==tr[a].r){
		//按需合并信息
		return a;
	}
	ls[a]=merge(ls[a],ls[b]);
	rs[a]=merge(rs[a],rs[b]);
	pushup(a);return a;
}

习题

我们掏出这个题单

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

record

好像 DSU 能艹,但是我们在学线段树合并,坚决不用 DSU!

套路一样,权值线段树合并就可以了。

record

挺牛逼题,考虑到子树内你无论怎么换,是不会影响到子树外的,所以贪心就可以了。

对每个节点维护一棵权值线段树,然后合并之前,先算一下左儿子的右区间中的数和右儿子左区间中的数,这些可以两两组成逆序对。同样的,由于可以交换,所以我们对于左儿子的左区间和右儿子的右区间也要算,然后取个较小的。递归继续合并。

record

这里是 DSU 水的题,实在不想用线段树合并

题目大致是求对于每个询问求一个点,有多少个点与其拥有共同的 \(k\) 级祖先(除本身)。

哦哟很可以 DSU。但是我们在学线段树合并,坚决不用 DSU!

艹不太会用线段树合并做,先用 DSU 过了再说。。。

哦哟苦痛,DSU 倍增卡空间,不会长剖,于是看了讨论区,发现这题并不需要 DSU 或者线段树合并,只需要一个奇怪的 trick,在深度遍历一个子树的前后你差分求出深度为 \(k\) 的节点个数就行了。诶但是问题是还是要倍增啊……

djwj233 给出了维护递归栈的做法。吊了,直接查,空间是 \(O(n)\) 的。

record

牛了,zzmg 题。。。考虑把题意翻译一下:

每次给定一个 \(p,k\)。求满足条件的二元组 \((b,c)\) 的个数。

  1. \(p,b\) 都是 \(c\) 的祖先
  2. \(p,b\) 之间距离不超过 \(k\)

然后我们发现,由于 \(p\) 是固定的,所以如果 \(b\)\(p\) 上方,那么 \(c\) 的选法就是 \(siz_p-1\)。但是如果 \(b\)\(p\) 的下方——

这样 \(c\) 选的方案数就与 \(b\) 有关了,具体地,就是 \(siz_b-1\)。而 \(b\) 的选法就是在 \(p\) 的子树中并且深度差不超过 \(k\) 的节点数。

那第一种可以直接算,第二种似乎可以 DSU……啊不,线段树合并!个鬼啊,写 DSU 去了。

record

诶哟李超树,不会,先咕了。

哦 Ynoi,准备苦痛了。

posted @ 2021-11-15 07:39  ZCETHAN  阅读(68)  评论(0编辑  收藏  举报