Language: C++

#include "asl.hpp"

#define endl '\n'

using namespace std;
using namespace asl;


class STP {
    class Node {
    public:
        Mint sum;
        int left, right;
    };
public:

    vector<Node> node;
    int root;

    STP(int n) : node(0) {
        root = build(0, n);
    }

    int new_node(int s=0) {
        node.push_back({ Mint(s), 0, 0 });
        return node.size() - 1;
    }

    int build(int b, int e) {
        auto root = new_node();

        if (b + 1 < e) {
            int m = (b + e) >> 1;
            auto le = build(b, m);
            auto ri = build(m, e);

            node[root].left = le;
            node[root].right = ri;
        }

        return root;
    }

    int clone(int u) {
        auto cur = node[u];
        node.push_back(cur);
        return node.size() - 1;
    }

    int update(int root, int b, int e, int x, Mint v) {
        root = clone(root);

        if (b + 1 == e) {
            node[root].sum = v;
        }
        else {
            int m = (b + e) >> 1;
            if (x < m) {
                auto le = update(node[root].left, b, m, x, v);
                node[root].left = le;
            }
            else {
                auto ri = update(node[root].right, m, e, x, v);
                node[root].right = ri;
            }

            node[root].sum = node[node[root].left].sum + node[node[root].right].sum;
        }

        return root;
    }

    Mint query(int root, int b, int e, int x, int y) {
        if (x <= b&& e <= y) {
            return node[root].sum;
        }
        else {
            int m = (b + e) >> 1;

            Mint res;

            if (x < m) res += query(node[root].left, b, m, x, y);
            if (m < y) res += query(node[root].right, m, e, x, y);

            return res;
        }
    }
};

pair<int, int> get_interval(int root, int h, int x, int delta) {
    int b = root << h;
    int e = b + (1 << h);

    if (x < (b + e) / 2) {
        b += (1 << (h - 1));
    }
    else {
        e -= (1 << (h - 1));
    }

    return { b - delta, e - delta };
}

int main()
{
    ios_base::sync_with_stdio(0);
    cin.tie(0);

    set_mod(m1000000007);

    int h; cin >> h;
    int l = (1 << (h -1));
    prepare_factorials(4 * l);

    vec<int> P(l);
    cin >> P;
    for (auto &x : P)
        --x;

    vec<Mint> acc(l);
    vec<Mint> curi(1 << h);
    curi[0] = 1;

    auto dfs = y_combinator([&](auto self, int s, Mint v, Mint i) -> void {
        curi[s] = i;

        if (s >= l) {
            acc[s - l] = v;
        }
        else {
            self(2 * s, v * 2 * s, i * inv[2 * s]);
            self(2 * s + 1, v * (2 * s + 1), i * inv[2 * s + 1]);
        }
        });

    dfs(1, 1, 1);

    STP st(l);

    vector<int> roots ={ st.root };

    for (int i = 0; i < l; ++i) {
        int r = roots.back();
        r = st.update(r, 0, l, P[i], acc[i] * acc[P[i]]);
        roots.push_back(r);
    }

    auto query = [&](int b1, int e1, int b2, int e2) {
        // b2--; e2--;
        // swap(b1, b2);
        // swap(e1, e2);
        auto ans = st.query(roots[e1], 0, l, b2, e2) - st.query(roots[b1], 0, l, b2, e2);
        // debug(b1, e1, b2, e2);
        // cout << ans << endl;
        return ans;
    };

    Mint fin = 0;

    for (int i = 0; i < l; ++i) {
        int u = l + i;
        int v = l + P[i];

        int tu = u;

        Mint pp = 0;
        for (int a = 1; a < h; ++a) {
            tu /= 2;
            auto iu = get_interval(tu, a, u, l);

            int tv = v;
            for (int b = 1; b < h; ++b) {
                tv /= 2;
                auto iv = get_interval(tv, b, v, l);

                auto cur = query(iu.first, iu.second, iv.first, iv.second);

                pp += curi[tu / 2] * curi[tu / 2] * curi[tv / 2] * curi[tv / 2] * cur * inv[tu] * inv[tv];
            }
        }

        fin += pp * acc[u - l] * acc[v - l];
    }

    cout << fin * inv[2] << endl;

    return 0;
}

Compiler output:
a.cc:1:10: fatal error: asl.hpp: No such file or directory
    1 | #include "asl.hpp"
      |          ^~~~~~~~~
compilation terminated.