首页 > 其他分享 >笛卡尔树

笛卡尔树

时间:2022-11-12 13:01:18浏览次数:60  
标签:sz 笛卡尔 int tp st BST ans

堆+BST

性质

  1. 笛卡尔树的子树是对应序列上一段连续的区间
    考虑 BST,最初 \([1,n]\),考虑划分开 rt,分割成左右 2 个区间,且两个区间对应 2 棵子树,分治下去得证。

构造

考虑对于一个新节点 \(a_i\) 的加入势必只会影响当前树的最右链,因为要满足下标 BST 性质。

然后既然已经满足了 BST 性质,不妨先假设我们维护的是个小根堆,即点的权值小于等于其子树内的所有权值。

考虑当前右链满足自父亲到儿子权值单增,那么显然你 \(a\) 的插入本质上就是抽离出来 \(\ge a_i\) 的底部链,并将这条链接到 \(a\) 的左儿子,这条链自身的结构并不需要改变,然后再将 \(a_i\) 接到抽完的链的底部,作为其右儿子。

这个构造过程是很自然的,但为啥把这条链直接抽,并不需要改变其形态就是对的呢?

考虑这条链所挂着的其他儿子。

  • 堆性质,由于其最上的点满足 \(\ge a_i\),所以其子树也一定满足。

  • BST,显然,你各个点的子树都是 BST,自然不需要更改。

https://acm.hdu.edu.cn/showproblem.php?pid=1506

#include <bits/stdc++.h>
#define int long long
#define pb push_back
using namespace std;
const int N=(int)(1e5+5);
vector<int>g[N];
int n,a[N],sz[N],ls[N],rs[N],ans,tp,st[N],du[N];

void dfs(int x) {
    sz[x]=1;
    for(int y:g[x]) {
        dfs(y); sz[x]+=sz[y];
    }
    ans=max(ans,sz[x]*a[x]);
}

void sol() {
    ans=-(int)(2e18);
    for(int i=1;i<=n;i++) {
        cin>>a[i];
        ls[i]=rs[i]=du[i]=0;
        g[i].clear();
    }
    tp=0;
    for(int i=1;i<=n;i++) {
        while(tp&&a[st[tp]]>a[i]) {
            ls[i]=st[tp]; --tp;
        }
        if(tp) rs[st[tp]]=i;
        st[++tp]=i; 
    }
    for(int i=1;i<=n;i++) {
        if(ls[i]) g[i].pb(ls[i]),++du[ls[i]];
        if(rs[i]) g[i].pb(rs[i]),++du[rs[i]];
    }
    int rt=0;
    for(int i=1;i<=n;i++) {
        if(!du[i]) {
            rt=i; break ;
        }
    }
    dfs(rt);
    cout<<ans<<'\n';
}

signed main() {
    cin.tie(0); ios::sync_with_stdio(false);
    while(1) {
        cin>>n;
        if(!n) return 0;
        sol();
    }
    return 0;
}

标签:sz,笛卡尔,int,tp,st,BST,ans
From: https://www.cnblogs.com/xugangfan/p/16883492.html

相关文章

  • 浅谈笛卡尔树
    笛卡尔树(CartesianTree),是一种二叉树,每个节点都有两个信息\((x_i,y_i)\),其中把\(x_i\)单独拎出来看是一棵二叉搜索树(\(ls_u<u<rs_u\)),而把\(y_i\)拎出来是一个小根堆(\(......
  • P5854 【模板】笛卡尔树
    【模板】笛卡尔树题目描述给定一个\(1\simn\)的排列\(p\),构建其笛卡尔树。即构建一棵二叉树,满足:每个节点的编号满足二叉搜索树的性质。节点\(i\)的权值为\(p......
  • 【UOJ424】count(笛卡尔树,DP,生成函数,矩阵快速幂)
    首先可以发现两个序列\(A,B\)同构当且仅当它们的笛卡尔树同构。那么可以考虑枚举笛卡尔树,然后判断它能否构成满足题目条件的序列。发现一棵笛卡尔树满足条件当且仅当它......
  • 数据结构#1 笛卡尔树学习笔记
    笛卡尔树数据结构结构介绍笛卡尔树是一种树形的数据结构,它的每一个节点都有两个值key和weight,其中key满足二叉搜索树的性质,而weight满足堆的性质。在使用时,我们通常将ke......
  • 笛卡尔树
    笛卡尔树1.权值\(\text{pos}\)满足二叉搜索树的性质,通常用序列的下标作为权值;2.权值\(\text{val}\)满足二叉堆的性质。实现方法我们考虑将元素按照键值\(k\)排序......
  • P5854 【模板】笛卡尔树
    题目链接P5854【模板】笛卡尔树题目描述给定一个\(1\simn\)的排列\(p\),构建其笛卡尔树。即构建一棵二叉树,满足:每个节点的编号满足二叉搜索树的性质。节点\(i......
  • 笛卡尔树
    在我的心里NOI大纲内提高级最难的知识点是圆方树、平衡树和笛卡尔树,平衡树自从自学了DHQ-treap后倒是有所改观,今天又重学笛卡尔树,发现貌似并不是那么难(原理上)。看来是......
  • kruskal重构树and笛卡尔树
    为什么放在了一起因为我个人旗帜鲜明的认为这是一个东西前者可以旗帜鲜明的解决图上(包括树上)限定最值的联通问题建立方式:跑kruskal时每连接两个点时建立一个新点把原......
  • 笛卡尔树
    概念Link笛卡尔树的节点各有两个权值,其中一个权值满足二叉搜索树的性质,另一个满足小(大)根堆的性质。所以说Treap也是一种笛卡尔树。构造知乎以下均假设原序列元素......
  • 笛卡尔树
    笛卡尔树是一种二叉树,每个节点有两个键值\(x,y\),一个满足BST,一个满足堆。上图:一个性质是如果键值确定那么笛卡尔树是唯一的。笛卡尔树如果暴力构造很简单:找到整个序列......