笛卡尔树

笛卡尔树

image-20200824215225144

介绍

笛卡尔树是形如上图的一棵树,满足

①堆的性质,如本图,小根堆,儿子的值大于等于父亲的值

②二叉搜索树性质,即左子树的点key(默认为下标)比根小,右子树的点key(默认为下标)比根大

显然,按中序遍历这棵树,可得原序列

和treap不同的是,树高不保证是log

③询问下标i到下标j之间(i<j)的最小值,只需寻找[i,j]的lca

构建

每次插入一个新节点时,为了确保二叉搜索树的性质得到满足(别忘了我们按照 key顺序插入),我们需要将新节点插入到尽可能靠右端的位置。

我们维护最右链,同时,注意到最右链中val单调

因此可以维护一个单调栈,来即时地找到插入位置

模板

#include <iostream>
#include <utility>
#include <cstdio>
#include <cctype>
using namespace std;
const int N=1e7+5;
inline int read() {
	int x=0;char ch=getchar();
	while(!isdigit(ch)) ch=getchar();
	while(isdigit(ch)){x=x*10+ch-'0';ch=getchar();}
	return x;
}
int n,dat[N],st[N],ls[N],rs[N],top;
inline void insert(int x) {
    while(top&&dat[st[top]]>dat[x]) top--;
    ls[x]=rs[st[top]],rs[st[top]]=x;
    st[++top]=x;
}
long long ans1,ans2;
int main() {
    n=read();
    for(int i=1;i<=n;i++) dat[i]=read();
    for(int i=1;i<=n;i++) insert(i);
    for(int i=1;i<=n;i++) 
        ans1^=(i*(ls[i]+1ll)),ans2^=(i*(rs[i]+1ll));
    printf("%lld %lld
",ans1,ans2);
    return 0;
}

建树的方法2

每次选取区间最大值作为根,然后往两边递归也可以建树

直接暴力是O(n^2)

线段树优化一下O(nlogn)

树的序

Description

给一个生成序列,建出一棵笛卡尔树,求字典序最小的可以得到相同笛卡尔树的生成序列

Solution

按题意建好笛卡尔树之后输出先序遍历即可

建树注意题目中的序列是模板中的key 序列,所以输入这里稍微转换一下

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>

using namespace std;
const int N=100005; 
inline int read(){
	int x=0,f=1;char ch=getchar();
	while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
	while(isdigit(ch)){x=x*10+ch-'0';ch=getchar();}
	return f*x;
}
int n,dat[N],st[N],top,ls[N],rs[N];
void insert(int x) {
    while(top&&dat[st[top]]>dat[x]) top--;
    ls[x]=rs[st[top]];rs[st[top]]=x;
    st[++top]=x;
}
void dfs(int x) {
    if(!x) return;
    printf("%d ",x);
    dfs(ls[x]); 
    dfs(rs[x]);
}
int main() {
    n=read();
    for(int i=1,x;i<=n;i++) x=read(),dat[x]=i;
    for(int i=1;i<=n;i++) insert(i);
    dfs(st[1]);
    return 0;
}

Periodni ——题解https://www.luogu.com.cn/blog/Alansp/solution-sp3734

https://www.luogu.com.cn/problem/P3246

https://www.luogu.com.cn/problem/P5044

https://www.luogu.com.cn/problem/P4755

http://codeforces.com/problemset/problem/1117/G

https://www.luogu.com.cn/problem/P2611

参考文章:

https://www.cnblogs.com/LiuRunky/p/Cartesian_Tree.html

https://www.cnblogs.com/Miracevin/p/10373626.html

原文地址:https://www.cnblogs.com/ke-xin/p/13574169.html