HDU 6305 RMQ Similar Sequence(笛卡尔树,期望)

版权声明:本文为博主原创文章,转载请附带博主链接。 https://blog.csdn.net/pashuihou/article/details/81216477

【题目链接】
http://acm.hdu.edu.cn/showproblem.php?pid=6305

题目意思

定义RMQ(A,l,r)为:序列A中,满足A[i] = max(A[l],A[l+1],…,A[r])的最大的i。如果对于任意(l,r)都满足RMQ(A,l,r)=RMQ(B,l,r)则为A和B是RMQ Similar。现在出A序列,B序列的每个数都是0~1之间的实数,问满足与A是RMQ Similar的所有B序列中所有数之和的期望。例如1,3,2和4 7 2值的大小排序一样。如果数值相同算前个大于后一个。

解题思路

不难看出如果A和B是RMQ Similar,则A和B的笛卡尔树同构(反正我是没看出来)。因为笛卡尔树每棵树的根节点都是本树最大值,所以构建B的笛卡尔树和A一样的概率为每棵树的节点数分之一的乘积 1 n 1 s z [ i ] ,(因为对于每棵树的最大值必须是根节点,概率全部节点分之一)。之后B每个节点满足均匀分布期望是1/2,n个节点就是n/2.总的期望就是 n 2 1 n s z [ i ]

推荐个笛卡尔树解释的博客:https://www.cnblogs.com/gtarcoder/p/4702853.html

代码部分


#include <iostream>
#include <algorithm>
#include <stdio.h>
#include <string.h>
#include <queue>
#include <string>
#include <map>
#include <math.h>
#include <set>
using namespace std;
#define LL long long
#define inf 0x3f3f3f3
const int mod = 1e9+7;
const int N = 1e6+7;

int n;
int l[N],r[N],d[N];
LL inv[N],ans;

pair<int, int> a[N];
int dfs(int rt)  ///计算节点数 
{
    int s = 1;
    if (l[rt]) s += dfs(l[rt]);
    if (r[rt]) s += dfs(r[rt]);
    ans = ans*inv[s]%mod;
    return s;
}
void build()  ///笛卡尔树模板 
{
    int top = 0,k;
    for (int i = 1; i <= n; i++)
        r[i] = l[i] = 0;
    for (int i = 1; i <= n; i++)  ///模拟堆 
    {
        k = top;
        while (k > 0 && a[d[k-1]] < a[i])   
            k--;
        if (k) r[d[k-1]] = i;
        if (k < top) l[i] = d[k];
        d[k++] = i;
        top = k;
    }
    dfs(d[0]);
}
int main()
{
    int t;
    inv[1] = 1;
    for (int i = 2; i <= N; i++)  ///打逆元表 
        inv[i]=inv[mod%i]*(mod-mod/i)%mod;
    scanf("%d",&t);
    while (t--)
    {
        int x;
        scanf("%d",&n);
        for (int i = 1; i <= n; i++)
        {
            scanf("%d",&x);
            a[i] = make_pair(x,n-i);  ///防止有相同数值,标记要反过来 
        }
        ans = n*inv[2]%mod;   ///期望 
        build();
        printf("%lld\n",ans);
    }
    return 0;
} 

猜你喜欢

转载自blog.csdn.net/pashuihou/article/details/81216477