HDU 6305 RMQ Similar Sequence(笛卡尔树)

RMQ Similar Sequence

Time Limit: 4000/2000 MS (Java/Others)    M`emory Limit: 255535/255535 K (Java/Others)
Total Submission(s): 953    Accepted Submission(s): 310


 

Problem Description

Chiaki has a sequence A={a1,a2,…,an}. Let RMQ(A,l,r) be the minimum i (l≤i≤r) such that ai is the maximum value in al,al+1,…,ar.

Two sequences A and B are called \textit{RMQ Similar}, if they have the same length n and for every 1≤l≤r≤n, RMQ(A,l,r)=RMQ(B,l,r).

For a given the sequence A={a1,a2,…,an}, define the weight of a sequence B={b1,b2,…,bn} be ∑i=1nbi (i.e. the sum of all elements in B) if sequence B and sequence A are RMQ Similar, or 0 otherwise. If each element of B is a real number chosen independently and uniformly at random between 0 and 1, find the expected weight of B.

 

 

Input

There are multiple test cases. The first line of input contains an integer T, indicating the number of test cases. For each test case:
The first line contains an integer n (1≤n≤106) -- the length of the sequence.
The second line contains n integers a1,a2,…,an (1≤ai≤n) denoting the sequence.
It is guaranteed that the sum of all n does not exceed 3×106.

 

 

Output

For each test case, output the answer as a value of a rational number modulo 109+7.
Formally, it is guaranteed that under given constraints the probability is always a rational number pq (p and q are integer and coprime, q is positive), such that q is not divisible by 109+7. Output such integer a between 0 and 109+6 that p−aq is divisible by 109+7.

 

 

Sample Input

 

3 3 1 2 3 3 1 2 1 5 1 2 3 2 1

 

 

Sample Output

 

250000002 500000004 125000001

 

考虑B中的每个数是0~1之间的实数,因此出现相同数字的概率为0,可以假设B是每个数都不相同排列。设A的笛卡尔树每个子树的大小为sz[u],则任一B排列与A同构的概率是\prod_{1}^{n} \frac{1}{sz[i]},因为B中每个数满足均匀分布,因此期望值为\frac{1}{2},和的期望为\frac{n}{2},因此满足与A同构的B中所有数之和的期望为\frac{n}{2\prod_{1}^{n}sz[i]}

#include<bits/stdc++.h>
using namespace std;
#define ll long long 
const int maxn=1e6+10;
const ll mod=1e9+7;
int n,st[maxn],son[maxn];
ll fac[maxn],inv[maxn];
struct node
{
	int l,r,fa,v;
}tree[maxn];
void init()
{
	fac[0]=1;
	for(int i=1;i<maxn;i++) fac[i]=fac[i-1]*i%mod;
	inv[1] = 1;
    for (int i = 2; i < maxn; i++) inv[i] = inv[mod % i] * (mod - mod / i) % mod;
}
int build()
{        
	int len=0;st[++len]=1;
	for(int i=2;i<=n;i++)
	{
		while(len&&tree[st[len]].v<tree[i].v) len--;
		if(len)
		{
			tree[i].l=tree[st[len]].r;
			tree[tree[st[len]].r].fa=i;
			tree[i].fa=st[len];
			tree[st[len]].r=i;
		}
		else
		{
			tree[st[1]].fa=i;
			tree[i].l=st[1];
		}
		st[++len]=i;
	}
	return st[1];
}
void dfs(int v)
{
	if(v==0) return;
	son[v]=1;
	dfs(tree[v].l);
	dfs(tree[v].r);
	son[v]=son[v]+son[tree[v].l]+son[tree[v].r];
}
int main()
{
	init();
	int T;scanf("%d",&T);
	while(T--)
	{
		scanf("%d",&n);
		for(int i=1;i<=n;i++) 
		{
		    scanf("%d",&tree[i].v);
		    tree[i].fa=tree[i].l=tree[i].r=0;
		}
		int id=build();
		dfs(id);
		ll ans=n*inv[2]%mod;
		for(int i=1;i<=n;i++)
		ans=ans*inv[son[i]]%mod;
		printf("%lld\n",ans%mod);
	}
	return 0;
} 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值