hdu 6305 RMQ Similar Sequence(笛卡尔树模板)

题意:
设RMQ(A,l,r)为最小的 i ,使得a[i]是a[l]-a[r]中的最大值。若A、B两个数组RMQ相似,则A、B等长,且在1<=l<=r<=n内,RMQ(A,l,r)=RMQ(B,l,r)。现在A数组已知,B数组在[0,1]均匀分布,设B数组的权重为数组内各元素的和。若A与B相似,求B权重的期望。

题解:
RMQ-Similar实际上就是 A和 B的笛卡尔树一样(同构),这样我们就有了一个二叉树,然后可以在树上分析了。考虑到B中有元素相同的概率是 0,于是可以假设 B里面元素互不相同,也就是说可以假定是一个排列。显然,符合笛卡尔树的排列就是这个树的拓扑序列个数,就是。然后显然每个排列期望的和是,于是答案就是\frac{n}{2\prod size[i]}

笛卡尔树的性质:
1.树中的元素满足二叉搜索树性质,要求按照中序遍历得到的序列为原数组序列(左儿子的key值小于自己,右儿子的key值大于自己)。

2.树中节点满足堆性质,节点的val值要大于其左右子节点的val值。

 

判断树同构 : 最小表示法
树是DAG(有向无环图)的一种, 
求n个点的树的拓扑序列的个数? 
考虑1~n的全排列,有n!个排列 
设A子树的大小为size[A] 
对于每个节点A , A在拓扑序列中要在其子树中所有其他点的后面,于是我们只考虑A的子树中的点的排列,发现只有1/size[A]的排列是符合上述要求的,又每个点的要求之间都无关(要求只是对当前点有关),所以符合所有要求的排列为

参考:https://blog.csdn.net/luyehao1/article/details/81280093、

https://blog.csdn.net/qq_35950004/article/details/81356898。

代码:

#include
using namespace std;
typedef long long ll;
const int N = 1e6+10;
const ll mod = 1e9+7;

int n, l[N], r[N], vis[N], stk[N], inv[N], siz[N];
ll a[N];

///建笛卡尔树模板,返回的是树的根节点下标
int build() {
    int top = 0;
    for(int i=1;i<=n;i++) l[i] = r[i] = vis[i] = 0;
    for(int i=1;i<=n;i++){
        int k = top;
        while(k > 0 && a[stk[k - 1]] < a[i]) --k;
        if(k) r[stk[k-1]] = i;
        if(k

 

你可能感兴趣的:(笛卡尔树)