笛卡尔树大学习

前言

  • msjing要开始学笛卡尔树了
  • sbmqwm:

批注 2026-07-16 091928

  • msjing:?

笛卡尔树

  • 笛卡尔树是一棵二叉树,其有两个值 \((k,w)\),其中 \(k\) 要求满足 \(BST\) 性质,而 \(w\) 要求满足堆性质,不知道 \(BST\) 的可以看我之前的学习笔记
  • 我们发现笛卡尔树和 \(Treap\) 非常像,不过 \(Treap\)\(rand\) 一个权值,本质上 \(Treap\) 属于笛卡尔树
  • 我们不再按平衡树的方式构建,而是用数组下标作为二元组的键值 \(k\),其中数组下标 \(k\) 满足 \(BST\) 性质

构建

  • 笛卡尔树的构建通常采用单调栈,原因是我们上面规定了笛卡尔树以 \(k\) 作为下标,且满足 \(BST\) 性质,所以是单调的
  • 构建时就像插入的过程,比如已经有 \(1\)\(7\) 这两个点,要加入 \(3\),就是在 \(1\)\(7\) 中间加入 \(3\),再把 \(7\) 拐为左子树,\(e\),非常复杂,从oiwiki偷张图

cartesian-tree2

  • 然后就没了
  • 代码随便给了,msjing找了个题解贺的
点击查看代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
constexpr int maxn=1e7+10;
int read()
{
    int x=0,f=1;
    char ch=getchar();
    while (ch<'0' || ch>'9')
    {
        if (ch == '-') f=-1;
        ch=getchar();
    }
    while (ch>='0' && ch<='9')
    {
        x=(x<<1)+(x<<3)+ch-'0';
        ch=getchar();
    }
    return x*f;
}
int n,a[maxn],stk[maxn],top=1,ls[maxn],rs[maxn];
void des()
{
    for (int i=2;i<=n;i++)
    {
        while (a[stk[top]]>a[i] && top) top--;
        if (!top) ls[i]=stk[top+1];
        else ls[i]=rs[stk[top]],rs[stk[top]]=i;
        stk[++top]=i;
    }
}
int ans1,ans2;
signed main()
{
    n=read();stk[1]=1;
    for (int i=1;i<=n;i++) a[i]=read();
    des();
    for (int i=1;i<=n;i++) ans1^=i*(ls[i]+1),ans2^=i*(rs[i]+1);
    printf("%lld %lld\n",ans1,ans2);
    return 0;
}

做题

类型

  • 有两种,板板和笛卡尔dp

板板

\(solve\)

  • 徒手模一下,发现下标满足小根堆,权值满足 \(BST\),符合笛卡尔树,直接按 \(BST\) 为下标搞,由于插入顺序,跑前序遍历,输出就搞完了
  • sbmqwm:搞完搞完
  • msjing:你出去

\(code\)

点击查看代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
constexpr int maxn=1e5+10;
int read()
{
    int x=0,f=1;
    char ch=getchar();
    while (ch<'0' || ch>'9')
    {
        if (ch == '-') f=-1;
        ch=getchar();
    }
    while (ch>='0' && ch<='9')
    {
        x=(x<<1)+(x<<3)+ch-'0';
        ch=getchar();
    }
    return x*f;
}
int n,a[maxn],stk[maxn],top=1,ls[maxn],rs[maxn];
void des()
{
    for (int i=2;i<=n;i++)
    {
        while (a[stk[top]]>a[i] && top) top--;
        if (!top) ls[i]=stk[top+1];
        else ls[i]=rs[stk[top]],rs[stk[top]]=i;
        stk[++top]=i;
    }
}
void dfs(int x)
{
    if (x == 0) return;
    printf("%lld ",x);
    dfs(ls[x]);
    dfs(rs[x]);
}
signed main()
{
    n=read();stk[1]=1;
    for (int i=1;i<=n;i++) a[read()]=i;
    des();dfs(stk[1]);
    return 0;
}

\(dp\)

  • 显然msjing还没做,先撂着,咕咕咕
posted @ 2026-07-16 11:19  msjing  阅读(12)  评论(0)    收藏  举报