笛卡尔树初学
学了新算法,不管怎么样也要记录一下吧
笛卡尔树有以下两个特点:
1.是一个堆结构
2.它的中序遍历顺序等于原序列的顺序
性质:
[i,j]区间的最值等于lca(i,j)的值
如何构建?
首先先建一个0号节点,a[0]=inf
然后构建一个栈,来维护右链
栈底为root,s[top]是s[top-1]的右儿子
考虑加入元素k
判断两种情况:
- 它比栈顶还大。因为是单调栈,可以直接加到栈顶。
- 它不比栈顶大。我们只需要在栈里找到它插入的位置,把比它大的一段链全都变成它的左子树,然后再把它插入。这样,在中序遍历的时候仍然是先遍历其左子树再遍历它自身,满足第二条性质;因为左子树都比它大,显然满足性质
代码如下:
a[0]=1e9;s[top=1]=0; for (int i=1;i<=n;i++){ while (top&&a[s[top]]<a[i]) top--; int x=s[top]; fa[i]=x; l[i]=r[x]; fa[r[x]]=i; r[x]=i; s[++top]=i; }