HDU 6305 RMQ Similar Sequence

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6305

意识到RMQ相同的含义就是序列的相对大小关系保持一致,而相同的大小关系建立出的笛卡尔树相同(特殊的不是笛卡尔树,而是建树的方式)。
考虑B数组的排列中能够符合A数组构成的笛卡尔树的概率为 1/sz[i] 1 / ∏ s z [ i ] ,可以简单理解为,在对应笛卡尔树的节点上,当前位置作为这个子树中的最大值的概率是 1/sz[i] 1 / s z [ i ] ,因此得到上式,B数组取值任取且均匀分布,因此对于每种方案的期望值都是 n/2 n / 2 ,所以答案即为 1/(2sz[i]) 1 / ( 2 ∗ ∏ s z [ i ] )

#define others
#ifdef poj
#include <iostream>
#include <cstring>
#include <cmath>
#include <cstdio>
#include <algorithm>
#include <vector>
#include <string>
#include <map>
#include <set>
#endif // poj
#ifdef others
#include <bits/stdc++.h>
#include <ext/rope>
#include <ext/pb_ds/priority_queue.hpp>
#endif // others
//#define file
#define all(x) x.begin(), x.end()
using namespace std;
using namespace __gnu_pbds;
using namespace __gnu_cxx;
#define eps 1e-8
const double pi = acos(-1.0);

typedef long long LL;
typedef long long ll;
typedef unsigned long long ULL;
void umax(int &a, int b) {
    a = max(a, b);
}
void umin(int &a, int b) {
    a = min(a, b);
}
int dcmp(double x) {
    return fabs(x) <= eps?0:(x > 0?1:-1);
}
void file() {
    freopen("data_in.txt", "r", stdin);
    freopen("data_out.txt", "w", stdout);
}
const LL mod = 1e9+7;

ll powmod(ll a,ll b) {ll res=1;a%=mod; assert(b>=0); for(;b;b>>=1){if(b&1)res=res*a%mod;a=a*a%mod;}return res;}

namespace solver {
    const int maxn = 1e6+10;
    const LL mod = 1e9 + 7;
    int t, n;
    LL Inv[maxn];
    void init() {
        int p = mod;
        Inv[1] = 1;
        for (int i = 2, k; i < maxn; ++i) {
            t = p / i;
            k = p % i;
            Inv[i] = (p - t) * Inv[k] % p;
        }
    }
    struct Tree {
        int val;
        int l, r;
        Tree() {
            l = r = 0;
        }
    } tr[maxn];
    stack<int> stk;
    int rt;
    void ins(int x) {
        while (!stk.empty() && tr[x].val > tr[stk.top()].val) {
            stk.pop();
        }
        if (stk.empty()) {
            tr[x].l = rt;
            rt = x;
        } else {
            int tp = stk.top();
            tr[x].l = tr[tp].r;
            tr[tp].r = x;
        }
        stk.push(x);
    }
    LL res;
    int dfs(int x) {
        int sz = 1;
        if (tr[x].l) sz += dfs(tr[x].l);
        if (tr[x].r) sz += dfs(tr[x].r);
        res = (res * Inv[sz]) % mod;
        return sz;
    }
    void dfs_destory(int x) {
        if (tr[x].l) dfs_destory(tr[x].l);
        if (tr[x].r) dfs_destory(tr[x].r);
        tr[x].l = tr[x].r = tr[x].val = 0;
    }
    void solve() {
        init();
        cin >> t;
        while (t--) {
            while(!stk.empty()) stk.pop();
            rt = 1;
            cin >> n;
            cin >> tr[1].val;
            stk.push(1);
            for (int i = 2; i <= n; i++) {
                cin >> tr[i].val;
                ins(i);
            }
            res = n * Inv[2] % mod;
            dfs(rt);
            cout << res << '\n';
            dfs_destory(rt);
        }
    }
}

int main() {
    ios::sync_with_stdio(0);
    cin.tie(0);
//    file();
    solver::solve();
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值