跳转至

笛卡尔树

2025-04-01

我暂时也不太知道这玩意能干啥。。。因为好像难点的题有点难了,而且也没怎么遇到过需要用这个的题目。

是因为杭州M要用这个才来看看。

简单说下吧,就是单调栈来建树。左右孩子都是比它小或大的数字。且顺序是按原序列的顺序。好像非常简单。建树之类的,代码也是非常好理解。

P5854 【模板】笛卡尔树

模板题写了就是完全不知道它会有什么用。

void ChatGptDeepSeek()
{
    int n;
    cin >> n;
    vector<int> p(n + 1), l(n + 1), r(n + 1);
    for (int i = 1; i <= n; i++)
        cin >> p[i];
    auto build = [&]()
    {
        vector<int> stk;
        for (int i = 1; i <= n; i++)
        {
            while (!stk.empty() && p[stk.back()] > p[i])
                l[i] = stk.back(), stk.pop_back();
            if (!stk.empty())
                r[stk.back()] = i;
            stk.push_back(i);
        }
    };
    build();

    long long L = 0, R = 0;
    for (int i = 1; i <= n; i++)
    {
        // cerr << l[i] << " " << r[i] << " \n";
        L ^= 1LL * i * (l[i] + 1);
        R ^= 1LL * i * (r[i] + 1);
    }
    cout << L << " " << R << '\n';
}

2024ICPC杭州区域赛M

这个感觉还稍微能体现一点用途。

这里是用于检查对于每一个子区间,都满足子区间的最小值可以整除子区间里的所有数字。实际上只需要建笛卡尔树,然后整除是具有传递性的,且笛卡尔树是满足原序列的顺序,就是左孩子一定是在原序列中这个数字的左边。

只需要判断每一个节点,可以整除它的两个子节点,即满足条件。检查了所有子区间,时间复杂度却只有 \(O(n)\)