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

#include <algorithm>
#include <bitset>
#include <cassert>
#include <cmath>
#include <complex>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <deque>
#include <iostream>
#include <list>
#include <map>
#include <numeric>
#include <queue>
#include <random>
#include <set>
#include <stack>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <vector>

using namespace std;
template <typename T1, typename T2> inline void chkmin(T1 &a, T2 b) {
  if (a > b)
    a = b;
}
template <typename T1, typename T2> inline void chkmax(T1 &a, T2 b) {
  if (a < b)
    a = b;
}
#define files(FILENAME)                                                        \\
  read(FILENAME);                                                              \\
  write(FILENAME)
#define read(FILENAME) freopen((FILENAME + ".in").c_str(), "r", stdin)
#define write(FILENAME) freopen((FILENAME + ".out").c_str(), "w", stdout)
#define all(c) (c).begin(), (c).end()
#define sz(c) (int)(c).size()
#define left left228
#define right right228
#define y1 y1228
#define mp make_pair
#define pb push_back
#define y2 y2228
#define rank rank228
using ll = long long;
using ld = long double;
const string FILENAME = "input";
const int Mod = 1000000007;
const int MAXN = 1 << 18;

int sum(int a, int b) { return (a + b >= Mod ? a + b - Mod : a + b); }

void adds(int &a, const int b) {
  a += b;
  if (a >= Mod) {
    a -= Mod;
  }
}

int mul(int a, int b) { return ((ll)a * b % Mod); }

int powm(int a, int b) {
  int res = 1;
  while (b) {
    if (b & 1) {
      res = mul(res, a);
    }
    b >>= 1;
    a = mul(a, a);
  }
  return res;
}

int h;
int L;
int p[MAXN];
int mult[MAXN];
int rmult[MAXN];
vector<pair<int, int>> g[MAXN];
vector<int> pref[MAXN];
int l[MAXN], r[MAXN];
vector<pair<pair<int, int>, int>> z[MAXN];
vector<int> g1[MAXN];
int val[MAXN];

void inc(int i, int vals) {
  for (; i <= L; i |= (i + 1)) {
    adds(val[i], vals);
  }
}

int get(int i) {
  int res = 0;
  for (; i >= 0; i = (i & (i + 1)) - 1) {
    adds(res, val[i]);
  }
  return res;
}

int main() {
  ios_base::sync_with_stdio(false);
  cin.tie(0);
  cout.tie(0);
  // read(FILENAME);
  cin >> h;
  // h = 18;
  L = (1 << (h - 1));
  for (int i = 0; i < L; i++) {
    cin >> p[i];
    // p[i] = i + 1;
  }
  // mt19937 as;
  // shuffle(p, p + L, as);
  for (int i = 0; i < L; i++) {
    g[i + L].pb(mp(p[i], L + i));
    l[i + L] = i + 1;
    r[i + L] = i + 1;
  }
  rmult[0] = 1;
  mult[0] = 1;
  for (int i = 1; i < 2 * L; i++) {
    mult[i] = mul(i, mult[i >> 1]);
    rmult[i] = powm(mult[i], Mod - 2);
  }
  for (int i = L - 1; i >= 1; i--) {
    l[i] = l[i * 2];
    r[i] = r[i * 2 + 1];
  }
  for (int i = 0; i < L; i++) {
    int id = L + i;
    while (id >> 1 > 0) {
      int prev = id;
      id >>= 1;
      z[id].pb(mp(mp(prev, L + i), p[i] + L - 1));
    }
  }
  for (int i = 0; i < L; i++) {
    g1[i + L].pb(g[i + L][0].first);
    pref[i + L].pb(
        mul(mult[g[i + L][0].first + L - 1], mult[g[i + L][0].second]));
  }
  ll ans = 0;
  for (int i = L - 1; i >= 1; i--) {
    g[i].resize(sz(g[i * 2]) + sz(g[i * 2 + 1]));
    merge(all(g[i * 2]), all(g[i * 2 + 1]), g[i].begin());
    pref[i].resize(sz(g[i]));
    g1[i].resize(sz(g[i]));
    for (int j = 0; j < sz(g[i]); j++) {
      g1[i][j] = g[i][j].first;
      pref[i][j] = mul(mult[g[i][j].first + L - 1], mult[g[i][j].second]);
    }
    for (int j = 0; j < sz(g[i * 2]); j++) {
      inc(g[i * 2][j].first, pref[i * 2][j]);
    }
    for (auto x : z[i]) {
      int c = (i * 2) ^ (i * 2 + 1) ^ x.first.first;
      if (c == i * 2) {
        int posi = x.first.second;
        int mod = mul(mult[posi], rmult[i >> 1]);
        mod = mul(mod, rmult[i]);
        mod = mul(mod, mult[x.second]);
        int cur = x.second;
        while (cur >> 1 > 0) {
          int pcur = cur;
          cur >>= 1;
          int tcur = (cur * 2) ^ (cur * 2 + 1) ^ pcur;
          int fl = l[tcur];
          int fr = r[tcur];
          int res = sum(get(fr), Mod - get(fl - 1));
          res = mul(res, rmult[cur >> 1]);
          res = mul(res, rmult[cur]);
          res = mul(res, mod);
          ans = sum(ans, res);
        }
      }
    }
    for (int j = 0; j < sz(g[i * 2]); j++) {
      inc(g[i * 2][j].first, Mod - pref[i * 2][j]);
    }
    for (int j = 0; j < sz(g[i * 2 + 1]); j++) {
      inc(g[i * 2 + 1][j].first, pref[i * 2 + 1][j]);
    }
    for (auto x : z[i]) {
      int c = (i * 2) ^ (i * 2 + 1) ^ x.first.first;
      if (c == i * 2 + 1) {
        int posi = x.first.second;
        int mod = mul(mult[posi], rmult[i >> 1]);
        mod = mul(mod, rmult[i]);
        mod = mul(mod, mult[x.second]);
        int cur = x.second;
        while (cur >> 1 > 0) {
          int pcur = cur;
          cur >>= 1;
          int tcur = (cur * 2) ^ (cur * 2 + 1) ^ pcur;
          int fl = l[tcur];
          int fr = r[tcur];
          int res = sum(get(fr), Mod - get(fl - 1));
          res = mul(res, rmult[cur >> 1]);
          res = mul(res, rmult[cur]);
          res = mul(res, mod);
          ans = sum(ans, res);
        }
      }
    }
    for (int j = 0; j < sz(g[i * 2 + 1]); j++) {
      inc(g[i * 2 + 1][j].first, Mod - pref[i * 2 + 1][j]);
    }
  }
  ans = mul(ans, powm(2, Mod - 2));
  cout << ans << '\\n';
}


Error: TLE

Fixed submission:

#include <algorithm>
#include <bitset>
#include <cassert>
#include <cmath>
#include <complex>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <deque>
#include <iostream>
#include <list>
#include <map>
#include <numeric>
#include <queue>
#include <random>
#include <set>
#include <stack>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <vector>

using namespace std;
template <typename T1, typename T2> inline void chkmin(T1 &a, T2 b) {
  if (a > b)
    a = b;
}
template <typename T1, typename T2> inline void chkmax(T1 &a, T2 b) {
  if (a < b)
    a = b;
}
#define files(FILENAME)                                                        \\
  read(FILENAME);                                                              \\
  write(FILENAME)
#define read(FILENAME) freopen((FILENAME + ".in").c_str(), "r", stdin)
#define write(FILENAME) freopen((FILENAME + ".out").c_str(), "w", stdout)
#define all(c) (c).begin(), (c).end()
#define sz(c) (int)(c).size()
#define left left228
#define right right228
#define y1 y1228
#define mp make_pair
#define pb push_back
#define y2 y2228
#define rank rank228
using ll = long long;
using ld = long double;
const string FILENAME = "input";
const int Mod = 1000000007;
const int MAXN = 1 << 18;

int sum(int a, int b) { return (a + b >= Mod ? a + b - Mod : a + b); }

int mul(int a, int b) { return ((ll)a * b % Mod); }

int powm(int a, int b) {
  int res = 1;
  while (b) {
    if (b & 1) {
      res = mul(res, a);
    }
    b >>= 1;
    a = mul(a, a);
  }
  return res;
}

int h;
int L;
int p[MAXN];
int mult[MAXN];
int rmult[MAXN];
vector<pair<int, int>> g[MAXN];
vector<int> pref[MAXN];
int l[MAXN], r[MAXN];
vector<pair<pair<int, int>, int>> z[MAXN];
vector<int> g1[MAXN];

int main() {
  ios_base::sync_with_stdio(false);
  cin.tie(0);
  cout.tie(0);
  // read(FILENAME);
  cin >> h;
  // h = 18;
  L = (1 << (h - 1));
  for (int i = 0; i < L; i++) {
    cin >> p[i];
    // p[i] = i + 1;
    g[i + L].pb(mp(p[i], L + i));
    l[i + L] = i + 1;
    r[i + L] = i + 1;
  }
  rmult[0] = 1;
  mult[0] = 1;
  for (int i = 1; i < 2 * L; i++) {
    mult[i] = mul(i, mult[i >> 1]);
    rmult[i] = powm(mult[i], Mod - 2);
  }
  for (int i = L - 1; i >= 1; i--) {
    l[i] = l[i * 2];
    r[i] = r[i * 2 + 1];
  }
  for (int i = 0; i < L; i++) {
    int id = L + i;
    while (id >> 1 > 0) {
      int prev = id;
      id >>= 1;
      z[id].pb(mp(mp(prev, L + i), p[i] + L - 1));
    }
  }
  for (int i = 0; i < L; i++) {
    g1[i + L].pb(g[i + L][0].first);
    pref[i + L].pb(
        mul(mult[g[i + L][0].first + L - 1], mult[g[i + L][0].second]));
  }
  ll ans = 0;
  for (int i = L - 1; i >= 1; i--) {
    g[i].resize(sz(g[i * 2]) + sz(g[i * 2 + 1]));
    merge(all(g[i * 2]), all(g[i * 2 + 1]), g[i].begin());
    pref[i].resize(sz(g[i]));
    g1[i].resize(sz(g[i]));
    for (int j = 0; j < sz(g[i]); j++) {
      g1[i][j] = g[i][j].first;
      pref[i][j] = mul(mult[g[i][j].first + L - 1], mult[g[i][j].second]);
      if (j) {
        pref[i][j] = sum(pref[i][j - 1], pref[i][j]);
      }
    }
    for (auto x : z[i]) {
      int c = (i * 2) ^ (i * 2 + 1) ^ x.first.first;
      int posi = x.first.second;
      int mod = mul(mult[posi], rmult[i >> 1]);
      mod = mul(mod, rmult[i]);
      mod = mul(mod, mult[x.second]);
      int cur = x.second;
      int pl = -1;
      int pr = -1;
      int realL;
      int realR;
      while (cur >> 1 > 0) {
        int pcur = cur;
        cur >>= 1;
        int tcur = (cur * 2) ^ (cur * 2 + 1) ^ pcur;
        int fl = l[tcur];
        int fr = r[tcur];
        if (pl != fl) {
          realL = lower_bound(all(g1[c]), fl) - g1[c].begin();
          pl = fl;
        }
        if (pr != fr) {
          realR = upper_bound(all(g1[c]), fr) - g1[c].begin() - 1;
          pr = fr;
        }
        if (realL <= realR) {
          int res = sum(pref[c][realR], Mod - (realL ? pref[c][realL - 1] : 0));
          res = mul(res, rmult[cur >> 1]);
          res = mul(res, rmult[cur]);
          res = mul(res, mod);
          ans = sum(ans, res);
        }
      }
    }
  }
  ans = mul(ans, powm(2, Mod - 2));
  cout << ans << '\\n';
}