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

笛卡尔树笔记

时间:2024-12-20 22:10:37浏览次数:6  
标签:10 le cur 笛卡尔 int 笔记 权值

笛卡尔树笔记

【模板】笛卡尔树

题目描述

给定一个 \(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\)。


思路

以当前为根,从左往右走,如果能放在当前右子树,否则就一直往上找,直到找到当前的权值 \(p_i\) 比当前点的权值 \(p_i\) 大,则符合条件,放在其右子树。对于向上找时跳过的不符合条件的点,则将其放在当前接入点的左儿子。
那么,这样子的复杂度就是 \(O(N^2)\) 。考虑将向上遍历直到找到当前的权值 \(p_i\) 比当前点的权值 \(p_i\) 大这一步骤优化,即找到先前序列中位于该位置之前的以一个大于该值的树。由此想到了单调栈。
所以做法大致是“贪心 \(+\) 单调栈”。

code

注意要输入解绑,不然会 \(TLE\) (实践出真知)。

#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N=1e7+5;
int st[N];
int a[N];
int n;
int l[N],r[N];
void build(){
	int top=0,cur=0;
	for(int i=1;i<=n;i++){
		while(cur&&a[st[cur]]>a[i]) cur--;
		//cur:插在某个结点的右子树上
		if(cur) r[st[cur]]=i;
		//cur<top:插在某个结点的左子树上
		if(cur<top) l[i]=st[cur+1];
		st[++cur]=i;
		top=cur;
	}
}
signed main(){
	ios::sync_with_stdio(NULL);
	cin.tie(NULL);
	cin>>n;
	for(int i=1;i<=n;i++) cin>>a[i];
	build();
	int ans=0;
	for(int i=1;i<=n;i++) ans^=1LL*i*(l[i]+1);
	cout<<ans<<" ";
	ans=0;
	for(int i=1;i<=n;i++) ans^=1LL*i*(r[i]+1);
	cout<<ans<<endl;
	return 0;
}

标签:10,le,cur,笛卡尔,int,笔记,权值
From: https://www.cnblogs.com/yingxilin/p/18620030

相关文章

  • numpy的indexing学习笔记
    numpy的indexing学习笔记np.newaxis效果等价于None,放在哪儿哪儿就增加一个单位长度的维度高级索引高级索引如果用了一个ndarray的tuple,即同时使用多array进行索引,那么这些ndarray必须保证他们可以被广播到同样的shape,否则就会抛出异常。而如果有多个索引,那么它们一次索引第1......
  • BMF学习笔记
    引言学习了Haskell、学习了Agda,我们已经初步掌握了使用函数式编程进行编写程序、编写证明的方法。但是目前我们使用Agda进行的证明还是十分规范的代数形式的证明。如果想要严格地证明两个算法的等价性(而不是像OI题解里一样各种画图、感性理解之类的),我们就需要一种方法把算法写成......
  • Linux学习笔记(一) Linux目录结构
    下图显示的为Linux中的目录结构:/bin[常用](/usr/bin、/usr/local/bin)是Binary(二进制)的缩写,这个目录存放着经常使用的命令。/sbin(/usr/sbin、/usr/local/sbin)s就是SuperUser的意思,这里存放的是系统管理员使用的系统管理程序。/home[常用]存放普通用户的家目录,在Linux中每......
  • 笛卡尔树 (附洛谷模板题代码)
    前言打了一场\(\rm{codeforces}\),其中F使用了笛卡尔树,看起来这个东西的优先级比矩快还高,那就学一下似乎这道题并没有使用很多笛卡尔树的性质,但是\(\rm{yishu2}\)开了个专题,这下不得不学了笛卡尔树之前预习的时候看了一下首先复习一下二叉查找树的性质每个......
  • 服务器笔记2——frp配置
    参考了网络文章和官网文档只是记录一下自己需要的配置,防止忘记服务端配置#配置服务IP以及端口bindPort=7000bindAddr="0.0.0.0"#配置http穿透端口vhost_http_port=7600#配置管理页面webServer.addr="0.0.0.0"webServer.port=7500webServer.user="用户名......
  • YOLOv9-0.1部分代码阅读笔记-callbacks.py
    callbacks.pyutils\callbacks.py目录callbacks.py1.所需的库和模块2.classCallbacks: 1.所需的库和模块importthreading2.classCallbacks: #这段代码定义了一个名为Callbacks的类,它用于管理和执行在训练过程中的不同阶段调用的回调函数。classCallbacks:......
  • 快速幂笔记
    快速幂笔记快速幂,可以优化指数计算,将朴素的\(O(n^2)\)的时间复杂度优化到\(O(n\logn)\)原理是,将幂通过二进制拆分,只需要计算拆分后的值,就能组合出完全幂的答案举例如下:有\(a^{14}=a^{1110_{(2)}}=a^{1*2^3}*a^{1*2^2}*a^{1*2^1}*a^{0*2^0}\)又有\(a^{2^i}=a^{2^{i......
  • 【Cadence射频仿真学习笔记】IC设计中电感的分析、建模与绘制(EMX电磁仿真,RFIC-GPT生成
    一、理论讲解1.电感设计的两个角度电感的设计可以从两个角度考虑,一个是外部特性,一个是内部特性。外部特性就是把电感视为一个黑盒子,带有两个端子,如果带有抽头的电感就有三个端子,需要去考虑其电感值、Q值和自谐振频率这三个参数电感的Q值表达式如下,可以发现当电感等效电阻......
  • Ubuntu 笔记本设置合盖不息屏
    编辑logind.conf文件你可以通过编辑/etc/systemd/logind.conf文件来控制盖子关闭时的行为:找到以下几行(如果不存在,可以手动添加):#HandleLidSwitch=suspend#HandleLidSwitchExternalPower=suspend#HandleLidSwitchDocked=ignore将它们修改为如下:HandleLidSwitch=ignore......
  • Web APIs - 第6章笔记
    正则表达式什么是正则表达式?正则表达式(RegularExpression)是一种字符串匹配的模式(规则)使用场景:例如验证表单:手机号表单要求用户只能输入11位的数字(匹配)过滤掉页面内容中的一些敏感词和高亮搜索关键字(替换)从字符串中获取我们想要的特定部分(提取)正则基本......