RMQ Similar Sequence http://acm.hdu.edu.cn/showproblem.php?pid=6305
Chiaki has a sequence A={a1,a2,…,an} A = { a 1 , a 2 , … , a n } . Let RMQ(A,l,r) R M Q ( A , l , r ) be the minimum i(l≤i≤r) i ( l ≤ i ≤ r ) such that ai a i is the maximum value in al,al+1,…,ar a l , a l + 1 , … , a r .
Two sequences A A and B B are called \textit{RMQ Similar}, if they have the same length n and for every 1≤l≤r≤n 1 ≤ l ≤ r ≤ n , RMQ(A,l,r)=RMQ(B,l,r) R M Q ( A , l , r ) = R M Q ( B , l , r ) .
For a given the sequence A={a1,a2,…,an} A = { a 1 , a 2 , … , a n } , define the weight of a sequence B={b1,b2,…,bn} B = { b 1 , b 2 , … , b n } be ∑i=1nbi (i.e. the sum of all elements in B B ) if sequence B B and sequence A A are RMQ Similar, or 0 otherwise. If each element of B B is a real number chosen independently and uniformly at random between 0 and 1, find the expected weight of B B .
MQ-Similar实际上就是 A A 和 B B 的笛卡尔树一样,这样我们就有了一个二叉树,然后可以在树上分析了。
考虑到B中有元素相同的概率是 0 0 ,于是可以假设 B B 里面元素互不相同,也就是说可以假定是一个排列。
显然,符合笛卡尔树的排列就是这个树的拓扑序列个数,就是 n!2∏sizei n ! 2 ∏ s i z e i 。然后显然每个排列期望的和是 n2 n 2 ,于是答案就是 n2∏sizei n 2 ∏ s i z e i 。
#include
using namespace std;
using namespace std;
typedef long long ll;
typedef pair <int, int> pii;
const ll MOD = 1000000007;
const int MAXN = (int)1e6 + 5;
int l[MAXN], r[MAXN], vis[MAXN], stk[MAXN], inv[MAXN], sz[MAXN], n, ans, T;
pii a[MAXN];
void dfs(int v) {
if(l[v]) dfs(l[v]);
if(r[v]) dfs(r[v]);
sz[v] = 1 + sz[l[v]] + sz[r[v]];
ans = (1LL * ans * inv[sz[v]]) % MOD;
}
int build() { //建笛卡尔树
int top = 0;
rep(i, 1, n + 1) l[i] = r[i] = vis[i] = 0;
rep(i, 1, n + 1) {
int k = top;
while(k > 0 && a[stk[k - 1]] < a[i]) --k;
if(k) r[stk[k-1]] = i;
if(k1, n + 1) vis[l[i]] = vis[r[i]] = 1;
int ret = 0;
rep(i, 1, n + 1) if(vis[i] == 0) ret = i;
return ret;
}
void slove() {
int ret = build();
ans = 1;
memset(sz, 0x00, sizeof(int) * (n + 1));
dfs(ret);
printf("%d\n", (int)(1LL * ans * n % MOD * inv[2] % MOD));
}
int main()
{
inv[1] = 1;
rep(i, 2, MAXN) inv[i] = 1LL * inv[MOD%i]*(MOD-MOD/i)%MOD;
while(scanf("%d", &T) != EOF) {
while(T--) {
scanf("%d", &n);
rep(i, 1, n + 1) {
scanf("%d", &a[i].first);
a[i].second = -i;
}
slove();
}
}
return 0;
}