笛卡尔树~cartesian-tree

笛卡尔树

简介

笛卡尔树是一种平衡树,它的结构和treap相同,但是由于它能在O(n)时间构造,同时具有一些很有意思的性质。

构造

笛卡尔树的节点由键值对 (k,w) 组成。其中键值 k 满足二叉搜索树性质,而键值 w 满足小根堆性质。

一个有趣的事实是,如果笛卡尔树的 (k,w) 键值确定,且 k 互不相同 ,w 互不相同,那么这个笛卡尔树的结构是唯一的。

构建笛卡尔树需要用到栈,其步骤如下:

1.首先,将节点按照 k 值排序,保证树具有BST性质;

2.然后一个个插入,由于BST性质,我们只能插入到右链的末端;

3.将我们插入的节点 u 向上跳,直到找到一个w比它小的节点v,然后使u成为v的右儿子;

4.对于v本身的右子树,则成为u的左子树,由于v的右儿子的w一定大于wu因此堆性质得以保证;

我们的栈维护的是笛卡尔树的右链,由于每个元素在栈中停留的时间是一个连续的区间,所以可以用栈维护,而这个栈显然在(k,w)的视角都是单调的。

1.单纯实现一个最小堆,我们使用栈作为辅助空间来构造堆.当一个数组元素要构造节点时,他可以成为右链元素的子节点(比右链元素大),或者成为右链元素的父节点(比栈顶元素小)

2.还要将最小堆变成二叉搜索树。一个已入栈元素的下标<后入栈元素的下标,所以在第一步中,变成子节点的元素必须要成为右节点;变成父节点的元素,栈中的元素必须成为他的左子树,这样才保持了基于下标的二叉搜索树性质——votrubac

代码实现:

for(int i=1;i<=n;i++){
	int k=top;
	while(k>0&&w[s[k]]>w[i])k--;
	if(k)r[s[k]]=i;//如果u是堆顶,那就不需要成为任何壬的儿砸
	if(k<top)l[i]=s[k+1];//如果刚开始爬就被截停了,那他也没有儿砸了
	s[++k]=i;
	top=k;
}

以点 u 为根的子树是一段连续极长区间,wu 是区间的最小值,区间在保证最小值不变的情况下不能再向两边延长。区间 [a,b]的最小值为 w[lca(a,b)]

例题

Removing Blocks

N 块砖块排列成一行,从左到右编号为 1N 。每一个砖块都有一个重量,砖块 i 的重量为 Ai。 Snuke 会对这些 N 个砖块执行如下操作:

  • 选择一个还没有被移除的砖块,然后移除它。这个操作的代价是与被移除的砖块相邻的砖块(包括它自己)的重量之和。我们定义两块砖 xy (xy) 是相邻的,当且仅当对于所有 z(xzy) ,砖块 z 仍然没有被移除。

N! 种移除砖块的可能顺序。你需要对于所有可能的顺序计算出移除完所有 N 块砖块的代价,并计算这些代价的和。由于答案可能非常大,答案需要对 109+7 取模。

考虑以()构建键值对,以删除时间为 w ,设点权为ai.

则一个元素子树内的权值和就是删去它的贡献,设每个元素深为hi,则有总代价为

i=1nhi×ai

再考虑对于一个 j , i 是它祖先的充分必要条件是 ji1i之前被删去,这个事件的期望是

(ij)!(ij+1)=1ij+1

所以E(hi)

x=1i11ix+1+i1n1xi+1+1

所以答案为

n!×i=1n(x=1i11ix+1+i1n1xi+1+1)×ai

由于中间那一坨可以预处理,所以总时间复杂度O(n);

代码实现

#include<bits/stdc++.h>
#define int  long long
using namespace std;
const int N=1e5+10,mod=1e9+7;
int fac[N],inv[N],s[N];
int n,a[N],ans;
signed main(){
	cin>>n;
	fac[0]=fac[1]=1;inv[0]=inv[1]=1;
	for(int i=2;i<=100000;i++)fac[i]=fac[i-1]*i%mod;
	for(int i=2;i<=100000;i++)inv[i]=(mod-mod/i)*inv[mod%i]%mod;//线性求逆元
	for(int i=1;i<=100000;i++)s[i]=(s[i-1]+inv[i])%mod;
	for(int i=1;i<=n;i++)cin>>a[i];
	for(int i=1;i<=n;i++)ans=(ans+(s[i]+s[n-i+1]-1)*a[i])%mod;
	cout<<ans*fac[n]%mod;
	
}

模意义下的逆元和实数意义下的逆元是同余的——hzm

posted @   狐适之  阅读(142)  评论(3编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示