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

#include <algorithm>
#include <bitset>
#include <cassert>
#include <chrono>
#include <cmath>
#include <complex>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <iostream>
#include <map>
#include <queue>
#include <random>
#include <set>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <vector>
using namespace std;

#ifdef LOCAL
#define eprintf(...)                                                           \\
  fprintf(stderr, __VA_ARGS__);                                                \\
  fflush(stderr);
#else
#define eprintf(...) 42
#endif

using ll = long long;
using ld = long double;
using uint = unsigned int;
using ull = unsigned long long;
template <typename T> using pair2 = pair<T, T>;
using pii = pair<int, int>;
using pli = pair<ll, int>;
using pll = pair<ll, ll>;
mt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count());
ll myRand(ll B) { return (ull)rng() % B; }

#define pb push_back
#define mp make_pair
#define all(x) (x).begin(), (x).end()
#define fi first
#define se second

clock_t startTime;
double getCurrentTime() {
  return (double)(clock() - startTime) / CLOCKS_PER_SEC;
}

const ll MOD = (ll)1e9 + 7;
ll add(ll x, ll y) {
  x += y;
  if (x >= MOD)
    return x - MOD;
  return x;
}
ll sub(ll x, ll y) {
  x -= y;
  if (x < 0)
    return x + MOD;
  return x;
}
ll mult(ll x, ll y) { return (x * y) % MOD; }
ll bin_pow(ll x, ll p) {
  if (p == 0)
    return 1;
  if (p & 1)
    return mult(x, bin_pow(x, p - 1));
  return bin_pow(mult(x, x), p / 2);
}
ll rev(ll x) { return bin_pow(x, MOD - 2); }

const int N = (1 << 17);
const int M = N + 5;

int n;
int p[M];
int m;
vector<pii> a[2 * M];

int tryGet(int v, int p, int q) {
  q = max(0, min(q, (int)a[v].size() - 1));
  while (q >= 0 && a[v][q].first > p)
    q--;
  if (q < 0)
    return 0;
  while (q < (int)a[v].size() && a[v][q].first < p)
    q++;
  if (q == (int)a[v].size())
    return 0;
  if (a[v][q].first == p)
    return a[v][q].second;
  else
    return 0;
}
void tryAdd(int v, int p, int x) {
  if (a[v].empty() || a[v].back().first != p)
    a[v].push_back(mp(p, x));
  else
    a[v].back().second = add(a[v].back().second, x);
}

int main() {
  startTime = clock();
  //	freopen("input.txt", "r", stdin);
  //	freopen("output.txt", "w", stdout);

  scanf("%d", &n);
  n = 1 << (n - 1);
  for (int i = 0; i < n; i++) {
    scanf("%d", &p[i]);
    p[i]--;
  }
  /*
          n = 1 << 17;
          for (int i = 0; i < n; i++)
                  p[i] = i;
          shuffle(p, p + n, rng);
  */
  int ans = 0;

  for (int i = 0; i < n; i++) {
    int x = n + i;
    int u = n + p[i];
    while (u > 1) {
      x = mult(x, u);
      a[n + i].push_back(mp(u, x));
      u /= 2;
    }
    reverse(all(a[n + i]));
  }
  for (int v = n - 1; v > 0; v--) {
    int p = 0, q = 0;
    while (p < (int)a[2 * v].size() || q < (int)a[2 * v + 1].size()) {
      if (p < (int)a[2 * v].size() &&
          (q == (int)a[2 * v + 1].size() || a[2 * v][p] < a[2 * v + 1][q])) {
        int x = mult(a[2 * v][p].second,
                     tryGet(2 * v + 1, a[2 * v][p].first ^ 1, q));
        x = mult(x, mult(v, a[2 * v][p].first / 2));
        ans = add(ans, x);
        tryAdd(v, a[2 * v][p].first, mult(a[2 * v][p].second, v));
        p++;
      } else {
        tryAdd(v, a[2 * v + 1][q].first, mult(a[2 * v + 1][q].second, v));
        q++;
      }
    }
  }
  printf("%d\\n", ans);

  return 0;
}


Error: TLE

Fixed submission:

#include <algorithm>
#include <bitset>
#include <cassert>
#include <chrono>
#include <cmath>
#include <complex>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <iostream>
#include <map>
#include <queue>
#include <random>
#include <set>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <vector>
using namespace std;

#ifdef LOCAL
#define eprintf(...)                                                           \\
  fprintf(stderr, __VA_ARGS__);                                                \\
  fflush(stderr);
#else
#define eprintf(...) 42
#endif

using ll = long long;
using ld = long double;
using uint = unsigned int;
using ull = unsigned long long;
template <typename T> using pair2 = pair<T, T>;
using pii = pair<int, int>;
using pli = pair<ll, int>;
using pll = pair<ll, ll>;
mt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count());
ll myRand(ll B) { return (ull)rng() % B; }

#define pb push_back
#define mp make_pair
#define all(x) (x).begin(), (x).end()
#define fi first
#define se second

clock_t startTime;
double getCurrentTime() {
  return (double)(clock() - startTime) / CLOCKS_PER_SEC;
}

const ll MOD = (ll)1e9 + 7;
ll add(ll x, ll y) {
  x += y;
  if (x >= MOD)
    return x - MOD;
  return x;
}
ll sub(ll x, ll y) {
  x -= y;
  if (x < 0)
    return x + MOD;
  return x;
}
ll mult(ll x, ll y) { return (x * y) % MOD; }
ll bin_pow(ll x, ll p) {
  if (p == 0)
    return 1;
  if (p & 1)
    return mult(x, bin_pow(x, p - 1));
  return bin_pow(mult(x, x), p / 2);
}
ll rev(ll x) { return bin_pow(x, MOD - 2); }

const int N = (1 << 17);
const int M = N + 5;

int n;
int p[M];
pii b[20], c[20];
int m;
unordered_map<ll, int> mapchik;

int main() {
  startTime = clock();
  //	freopen("input.txt", "r", stdin);
  //	freopen("output.txt", "w", stdout);

  scanf("%d", &n);
  n = 1 << (n - 1);
  for (int i = 0; i < n; i++) {
    scanf("%d", &p[i]);
    p[i]--;
  }

  for (int i = 0; i < n; i++) {
    int v = n + i, u = n + p[i];
    int x = v, y = u;
    int k = 0;
    while (v > 1) {
      b[k] = mp(v, x);
      c[k] = mp(u, y);
      k++;

      v /= 2;
      u /= 2;
      x = mult(x, v);
      y = mult(y, u);
    }
    for (int p = 0; p < k; p++)
      for (int q = 0; q < k; q++) {
        int v = b[p].first, u = c[q].first;
        ll x = mult(b[p].second, c[q].second);
        mapchik[(ll)v * M + u] = add(mapchik[(ll)v * M + u], x);
      }
  }
  ll ans = 0;
  for (auto t : mapchik) {
    int v = t.first / M, u = t.first % M;
    if (v & 1)
      continue;
    ll val = t.second;
    ll h = (ll)(v ^ 1) * M + (u ^ 1);
    if (mapchik.count(h) == 0)
      continue;
    val = mult(val, mapchik[h]);
    val = mult(val, mult(v / 2, u / 2));
    ans = add(ans, val);
  }
  printf("%lld\\n", ans);

  return 0;
}