【题目链接】
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一样的概率为每棵树的节点数分之一的乘积 ∏n11sz[i] ∏ 1 n 1 s z [ i ] ,(因为对于每棵树的最大值必须是根节点,概率全部节点分之一)。之后B每个节点满足均匀分布期望是1/2,n个节点就是n/2.总的期望就是 n2∏n1sz[i] 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;
}