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值。*/

posted @ 2018-08-16 20:35  sewage  阅读(124)  评论(0编辑  收藏  举报