笛卡尔树 学习笔记
作者:互联网
简介
笛卡尔树是一种特殊的二叉树,处理一些序列问题
有一些二元组\(k,w\),那么如果对他们建出一棵树来,满足\(k\)满足\(BST\)性质,\(w\)满足堆性质,那么就是一颗笛卡尔树
容易发现\(treap\)就是一种特殊的笛卡尔树,只不过他是平衡的
通常情况下笛卡尔树不保证平衡,所以不能作为平衡树维护东西,但由于它形态唯一,所以可以用来解决一些序列问题
一般当题目出现区间最值时,或者明显具有笛卡尔树性质时可以考虑这个方向
构建
用单调栈有\(O(n)\),板子来源于wiki,养生选手懒人stl
for(int i=1;i<=n;i++)
{
int p=0;
while(s.size()&&a[s.top()]>a[i])p=s.top(),s.pop();
if(s.size())rs[s.top()]=i;
if(p)ls[i]=p;s.push(i);
}
这里是小根堆,大根堆是小于号
建出来之后栈底元素就是树根
HDU4125
这个比较裸基本是板子,要求权值满足\(BST\),下标满足小根堆,重新排序就好
建完树之后中序遍历的欧拉序就是答案,随便哈希匹配一下就行
HDU6305
将题目中的条件转化为笛卡尔树上的条件
会发现RMQ相似就是笛卡尔树同构,所以求同构的概率
对于一个节点它必须成为子树中的最大值,那么概率就是\(\frac {1}{sz[x]}\),所有点的概率乘在一起就是树同构的概率
而随机变量的期望值是\(\frac{1}{2}\),所以答案就是\(\frac{n}{2\prod sz[x]}\)
SPOJ2616/P6453
经典的笛卡尔树dp题
建小根堆笛卡尔树,这样就可以划分子问题,儿子之间相互独立互不影响
首先\(n*m\)棋盘放\(k\)个车答案是\(\dbinom{n}{k}\times \dbinom{m}{k} \times k!\)
设\(f_{x,i}\)表示在\(x\)子树对应的区间内放了\(i\)个的方案数,考虑树上背包做
先把子树合并起来,这个比较简单
然后统计当前这个区间自己的答案,相当于在最底下再放,枚举子树中放了多少个
减去的原因也好理解,就是已经放了的列不能再放
注意不能相互覆盖,还有组合数要处理到值域\(10^6\)
标签:同构,概率,frac,笛卡尔,笔记,学习,满足,就是 来源: https://www.cnblogs.com/PMZG/p/15401575.html