P5854 【模板】笛卡尔树

题目描述

给定一个 \(1 \sim n\) 的排列 \(p\),构建其笛卡尔树。

即构建一棵二叉树,满足:

  1. 每个节点的编号满足二叉搜索树的性质。
  2. 节点 \(i\) 的权值为 \(p_i\),每个节点的权值满足小根堆的性质。

输入格式

第一行一个整数 \(n\)

第二行一个排列 \(p_{1 \dots n}\)

输出格式

\(l_i,r_i\) 分别表示节点 \(i\) 的左右儿子的编号(若不存在则为 \(0\))。

一行两个整数,分别表示 \(\operatorname{xor}_{i = 1}^n i \times (l_i + 1)\)\(\operatorname{xor}_{i = 1}^n i \times (r_i + 1)\)

输入输出样例 #1

输入 #1

5
4 1 3 2 5

输出 #1

19 21

说明/提示

【样例解释】

\(i\) \(l_i\) \(r_i\)
\(1\) \(0\) \(0\)
\(2\) \(1\) \(4\)
\(3\) \(0\) \(0\)
\(4\) \(3\) \(5\)
\(5\) \(0\) \(0\)

【数据范围】

对于 \(30\%\) 的数据,\(n \le 10^3\)

对于 \(60\%\) 的数据,\(n \le 10^5\)

对于 \(80\%\) 的数据,\(n \le 10^6\)

对于 \(90\%\) 的数据,\(n \le 5 \times 10^6\)

对于 \(100\%\) 的数据,\(1 \le n \le 10^7\)

题解

#include <bits/stdc++.h>
using namespace std;
const int N=1e7+10;
typedef long long ll;
int n;
ll a[N];
ll sl[N],sr[N];
ll stk[N];
int top = 0;

void build()
{
    for(int i=1;i<=n;i++)
    {
        int pos = top;
        while(pos>0&&a[stk[pos]]>a[i])
        {
            pos--;
        }

        if(pos>0)sr[stk[pos]]=i;
        if(pos<top)sl[i] = stk[pos+1];
        stk[++pos] = i;
        top = pos;
    }
}


void solve()
{
    cin>>n;
    for(int i=1;i<=n;i++)cin>>a[i];
    build();
    ll res1=0,res2=0;
    for(ll i=1;i<=n;i++)
    {
        res1 ^= i*(sl[i]+1);
        res2 ^= i*(sr[i]+1);
    }
    cout<<res1<<' '<<res2<<'\n';
}

int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    int t=1;
    // cin>>t;
    while(t--)
    {
        solve();

    }


    return 0;
}
posted @ 2025-12-01 22:39  屈臣  阅读(0)  评论(0)    收藏  举报