2018杭电多校第一场1008(笛卡尔树,期望)
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod = 1e9+7;
const int inf = 0x3f3f3f3f;
const int mx = 1e6+5;
struct node
{
int val,siz;
int l,r,top;
}tree[mx];
stack<int>stk;
ll inv[mx];
void init(int n)
{
for(int i=0;i<=n;i++)
{
tree[i].l=0;
tree[i].r=0;
tree[i].top=0;
tree[i].siz=0;
}
tree[0].val=inf;
while(!stk.empty())
stk.pop();
stk.push(0);
}
void build(int n)
{ //从右端插入,建立一颗笛卡尔树
for(int i=1;i<=n;i++)
{
while(!stk.empty()&&tree[stk.top()].val<tree[i].val)//找到第一个大于等于tree[i].cal的元素
stk.pop();
int top=stk.top();
tree[i].top=top;
tree[i].l=tree[top].r;
tree[tree[top].r].top=i;
tree[top].r=i;
stk.push(i);
}
}
void dfs(int u)
{
if(u==0)
return;
tree[u].siz=1;
dfs(tree[u].l);
dfs(tree[u].r);
tree[u].siz+=tree[tree[u].l].siz+tree[tree[u].r].siz;
}
void modd()
{//求逆元模板,以免取模时除法产生误差
inv[1]=1;
for(int i=2;i<mx;i++)
inv[i]=inv[mod%i]*(mod-mod/i)%mod;
}
int main()
{
int tt,n;
cin>>tt;
modd();
while(tt--)
{
scanf("%d",&n);
init(n);//初始化
for(int i=1;i<=n;i++)
scanf("%d",&tree[i].val);
build(n);
dfs(tree[0].r);
ll ans=n*inv[2]%mod;
for(int i=1;i<=n;i++)
ans=ans*inv[tree[i].siz]%mod;
printf("%lld\n",ans);
}
return 0;
}
/*笛卡尔树:
1.树中的元素满足二叉搜索树性质,要求按照中序遍历得到的序列为原数组序列(左儿子的key值小于自己,右儿子的key值大于自己)。
2.树中节点满足堆性质,节点的val值要大于其左右子节点的val值。*/