Problem p02591 (C++) — buggy submission, verdict: Time Limit Exceeded

///****In the name of ALLAH, most Gracious, most Compassionate****//

#pragma GCC target("avx2")
#pragma GCC optimization("O3")
#pragma GCC optimization("unroll-loops")

#include <bits/stdc++.h>
using namespace std;

typedef long long ll;
typedef pair<int, int> pii;

#define ALL(a) a.begin(), a.end()
#define FastIO                                                                 \\
  ios::sync_with_stdio(false);                                                 \\
  cin.tie(0);                                                                  \\
  cout.tie(0)
#define IN freopen("input.txt", "r+", stdin)
#define OUT freopen("output.txt", "w+", stdout)

#define DBG(a)                                                                 \\
  cerr << "line " << __LINE__ << " : " << #a << " --> " << (a) << endl
#define NL cout << endl

template <class T1, class T2>
ostream &operator<<(ostream &os, const pair<T1, T2> &p) {
  os << "{" << p.first << "," << p.second << "}";
  return os;
}

const int N = 3e5 + 5;
const ll oo = 1e9 + 7;

int p[N];

vector<int> child[N][2];

ll Tree[N];

void update(int idx, ll x, int n) {
  // Let, n is the number of elements and our queries are
  // of the form query(n)-query(l-1), i.e range queries
  // Then, we should never put N or MAX in place of n here.
  while (idx <= n) {
    Tree[idx] = (Tree[idx] + x) % oo;
    idx += (idx & -idx);
  }
}

ll query(int idx) {
  ll sum = 0;
  while (idx > 0) {
    sum = (sum + Tree[idx]) % oo;
    idx -= (idx & -idx);
  }
  return sum;
}

ll root_to_node[N];
ll root_to_node_inv[N];

ll extended_euclidean(ll a, ll b, ll &x, ll &y) {
  if (a == 0) {
    x = 0;
    y = 1;
    return b;
  }
  ll x1, y1;
  ll d = extended_euclidean(b % a, a, x1, y1);
  x = y1 - (b / a) * x1;
  y = x1;
  return d;
}
ll mod_inverse(ll a, ll m) {
  ll x, y;
  ll g = extended_euclidean(a, m, x, y);
  if (g != 1) {
    cout << "No solution!";
    return -1;
  } else {
    x = (x % m + m) % m;
    return x;
  }
}

int32_t main() {
  FastIO;
  int h;
  cin >> h;
  int l = 1 << h - 1;
  for (int i = 1; i <= l; i++)
    cin >> p[i];
  for (int i = 1; i <= l; i++) {

    int u = l + i - 1;
    bool par = u % 2;
    int p = u / 2;

    do {

      child[p][par].push_back(i);
      par = p % 2;
      p = p / 2;
    } while (p);
  }

  root_to_node[0] = 1;
  root_to_node_inv[0] = 1;

  int total_node = (1 << h) - 1;
  for (int i = 1; i <= total_node; i++)
    root_to_node_inv[i] =
        mod_inverse(root_to_node[i] = (root_to_node[i / 2] * i) % oo, oo);

  ll ans = 0;

  for (int lca = 1; lca < l; lca++) {

    for (int leaf : child[lca][0]) {
      ll g = root_to_node[l + leaf - 1] * root_to_node_inv[lca] % oo;
      g = (g * root_to_node[l + p[leaf] - 1]) % oo;
      update(p[leaf], g, l);
    }

    for (int leaf : child[lca][1]) {
      ll g = root_to_node[l + leaf - 1] * root_to_node_inv[lca / 2] % oo;
      int u = l + p[leaf] - 1;
      int par = u % 2;
      int p = u / 2;

      g = (g * u) % oo;
      g = (g * p) % oo;

      do {

        ll now =
            (query(child[p][!par].back()) - query(child[p][!par].front() - 1)) %
            oo;

        now = now * root_to_node_inv[p] % oo;

        now = (now * g) % oo;

        ans = (ans + now) % oo;

        par = p % 2;
        p /= 2;

        g = (g * p) % oo;
      } while (p);
    }

    for (int leaf : child[lca][0]) {
      ll g = root_to_node[l + leaf - 1] * root_to_node_inv[lca] % oo;
      g = (g * root_to_node[l + p[leaf] - 1]) % oo;
      update(p[leaf], -g, l);
    }
  }

  ans = (ans + oo) % oo;

  cout << ans << "\\n";
}


Error: TLE

Fixed submission:

///****In the name of ALLAH, most Gracious, most Compassionate****//

#pragma GCC target("avx2")
#pragma GCC optimization("O3")
#pragma GCC optimization("unroll-loops")

#include <bits/stdc++.h>
using namespace std;

typedef long long ll;
typedef pair<int, int> pii;

#define ALL(a) a.begin(), a.end()
#define FastIO                                                                 \\
  ios::sync_with_stdio(false);                                                 \\
  cin.tie(0);                                                                  \\
  cout.tie(0)
#define IN freopen("input.txt", "r+", stdin)
#define OUT freopen("output.txt", "w+", stdout)

#define DBG(a)                                                                 \\
  cerr << "line " << __LINE__ << " : " << #a << " --> " << (a) << endl
#define NL cout << endl

template <class T1, class T2>
ostream &operator<<(ostream &os, const pair<T1, T2> &p) {
  os << "{" << p.first << "," << p.second << "}";
  return os;
}

const int N = 3e5 + 5;
const ll oo = 1e9 + 7;

int p[N];

vector<int> child[N][2];

ll Tree[N];

void update(int idx, ll x, int n) {
  // Let, n is the number of elements and our queries are
  // of the form query(n)-query(l-1), i.e range queries
  // Then, we should never put N or MAX in place of n here.
  while (idx <= n) {
    Tree[idx] = (Tree[idx] + x) % oo;
    idx += (idx & -idx);
  }
}

ll query(int idx) {
  ll sum = 0;
  while (idx > 0) {
    sum = (sum + Tree[idx]) % oo;
    idx -= (idx & -idx);
  }
  return sum;
}

ll root_to_node[N];

ll extended_euclidean(ll a, ll b, ll &x, ll &y) {
  if (a == 0) {
    x = 0;
    y = 1;
    return b;
  }
  ll x1, y1;
  ll d = extended_euclidean(b % a, a, x1, y1);
  x = y1 - (b / a) * x1;
  y = x1;
  return d;
}
ll mod_inverse(ll a, ll m) {
  ll x, y;
  ll g = extended_euclidean(a, m, x, y);
  if (g != 1) {
    cout << "No solution!";
    return -1;
  } else {
    x = (x % m + m) % m;
    return x;
  }
}

int32_t main() {
  FastIO;
  int h;
  cin >> h;
  int l = 1 << h - 1;
  for (int i = 1; i <= l; i++)
    cin >> p[i];
  for (int i = 1; i <= l; i++) {

    int u = l + i - 1;
    bool par = u % 2;
    int p = u / 2;

    do {

      child[p][par].push_back(i);
      par = p % 2;
      p = p / 2;
    } while (p);
  }

  root_to_node[0] = 1;

  int total_node = (1 << h) - 1;
  for (int i = 1; i <= total_node; i++)
    root_to_node[i] = (root_to_node[i / 2] * i) % oo;

  ll ans = 0;

  for (int lca = 1; lca < l; lca++) {

    for (int leaf : child[lca][0]) {
      ll g =
          root_to_node[l + leaf - 1] * mod_inverse(root_to_node[lca], oo) % oo;
      g = (g * root_to_node[l + p[leaf] - 1]) % oo;
      update(p[leaf], g, l);
    }

    for (int leaf : child[lca][1]) {
      ll g = root_to_node[l + leaf - 1] *
             mod_inverse(root_to_node[lca / 2], oo) % oo;
      int u = l + p[leaf] - 1;
      int par = u % 2;
      int p = u / 2;

      g = (g * u) % oo;
      g = (g * p) % oo;

      do {

        ll now =
            (query(child[p][!par].back()) - query(child[p][!par].front() - 1)) %
            oo;

        now = (now * mod_inverse(root_to_node[p], oo)) % oo;

        now = (now * g) % oo;

        ans = (ans + now) % oo;

        par = p % 2;
        p /= 2;

        g = (g * p) % oo;
      } while (p);
    }

    for (int leaf : child[lca][0]) {
      ll g =
          root_to_node[l + leaf - 1] * mod_inverse(root_to_node[lca], oo) % oo;
      g = (g * root_to_node[l + p[leaf] - 1]) % oo;
      update(p[leaf], -g, l);
    }
  }

  ans = (ans + oo) % oo;

  cout << ans << "\\n";
}