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

#include <bits/stdc++.h>

template <class T> inline void read(T &x) {
  static char ch;
  static bool opt;
  while (!isdigit(ch = getchar()) && ch != '-')
    ;
  x = (opt = ch == '-') ? 0 : ch - '0';
  while (isdigit(ch = getchar()))
    x = x * 10 + ch - '0';
  if (opt)
    x = ~x + 1;
}

template <class T> inline void putint(T x) {
  static char buf[45], *tail = buf;
  if (!x)
    putchar('0');
  else {
    if (x < 0)
      putchar('-'), x = ~x + 1;
    for (; x; x /= 10)
      *++tail = x % 10 + '0';
    for (; tail != buf; --tail)
      putchar(*tail);
  }
}

template <class T> inline bool tense(T &x, const T &y) {
  return y < x ? x = y, true : false;
}

template <class T> inline bool relax(T &x, const T &y) {
  return x < y ? x = y, true : false;
}

template <class T> inline T getAbs(const T &x) { return x < 0 ? -x : x; }

typedef long long s64;
typedef long double ld;
typedef std::vector<int> vi;
typedef std::pair<int, int> pii;
#define mp(x, y) std::make_pair(x, y)

const int mod = 1e9 + 7;
inline void add(int &x, const int &y) {
  if (x += y, x >= mod)
    x -= mod;
}
inline void dec(int &x, const int &y) {
  if (x -= y, x < 0)
    x += mod;
}
inline int qpow(int x, int y) {
  int res = 1;
  for (; y; y >>= 1, x = 1LL * x * x % mod)
    if (y & 1)
      res = 1LL * res * x % mod;
  return res;
}

const int MaxN = 1 << 18 | 5;

int H, n, m;
int p[MaxN], prod[MaxN], pinv[MaxN];

int s[MaxN], sum;

void modify(int x, int opt) {
  if (x >= m) {
    int val = 1LL * prod[x] * prod[p[x]] % mod;
    for (int y = p[x]; y; y >>= 1)
      (opt == 1 ? add : dec)(s[y], val);
    return;
  }
  modify(x << 1 | 0, opt);
  modify(x << 1 | 1, opt);
}

void query(int x) {
  if (x >= m) {
    int val = 1LL * prod[x] * prod[p[x]] % mod;

    for (int y = p[x]; y > 1; y >>= 1) {
      add(sum, 1LL * val * pinv[y >> 1] % mod * s[y ^ 1] % mod);
    }
    return;
  }
  query(x << 1 | 0);
  query(x << 1 | 1);
}

int main() {
#ifdef orzczk
  freopen("a.in", "r", stdin);
#endif

  read(H);
  n = 1 << H, m = (n + 1) >> 1;

  pinv[0] = 1, prod[1] = pinv[1] = 1;
  for (int i = 2; i < n; ++i) {
    prod[i] = 1LL * prod[i >> 1] * i % mod;
    pinv[i] = qpow(1LL * prod[i] * prod[i >> 1] % mod, mod - 2);
  }

  for (int i = m; i < n; ++i) {
    read(p[i]);
    p[i] += m - 1;
  }

  int ans = 0;
  for (int x = 1; x < m; ++x) {
    modify(x << 1, +1);

    sum = 0;
    query(x << 1 | 1);
    ans = (ans + 1LL * sum * pinv[x]) % mod;

    modify(x << 1, -1);
  }

  std::cout << ans << '\\n';

  return 0;
}

Error: TLE

Fixed submission:

#include <bits/stdc++.h>

template <class T> inline void read(T &x) {
  static char ch;
  static bool opt;
  while (!isdigit(ch = getchar()) && ch != '-')
    ;
  x = (opt = ch == '-') ? 0 : ch - '0';
  while (isdigit(ch = getchar()))
    x = x * 10 + ch - '0';
  if (opt)
    x = ~x + 1;
}

template <class T> inline void putint(T x) {
  static char buf[45], *tail = buf;
  if (!x)
    putchar('0');
  else {
    if (x < 0)
      putchar('-'), x = ~x + 1;
    for (; x; x /= 10)
      *++tail = x % 10 + '0';
    for (; tail != buf; --tail)
      putchar(*tail);
  }
}

template <class T> inline bool tense(T &x, const T &y) {
  return y < x ? x = y, true : false;
}

template <class T> inline bool relax(T &x, const T &y) {
  return x < y ? x = y, true : false;
}

template <class T> inline T getAbs(const T &x) { return x < 0 ? -x : x; }

typedef long long s64;
typedef long double ld;
typedef std::vector<int> vi;
typedef std::pair<int, int> pii;
#define mp(x, y) std::make_pair(x, y)

const int mod = 1e9 + 7;

inline int qpow(int x, int y) {
  int res = 1;
  for (; y; y >>= 1, x = 1LL * x * x % mod)
    if (y & 1)
      res = 1LL * res * x % mod;
  return res;
}

inline void add(int &x, const int &y) {
  if (x += y, x >= mod)
    x -= mod;
}

const int MaxN = 1 << 18 | 5;
const int MaxE = MaxN * 18 * 18 / 2 + 5;

const int M = MaxE;

int H, n, m;
int p[MaxN], prod[MaxN], pinv[MaxN];

int ect;
int adj[M], vX[MaxE], vY[MaxE], weight[MaxE], nxt[MaxE];

void insert(int x, int y, int val) {
  int u = (x * 993244853LL + y) % M;

  for (int e = adj[u]; e; e = nxt[e])
    if (vX[e] == x && vY[e] == y) {
      add(weight[e], val);
      return;
    }

  nxt[++ect] = adj[u];
  adj[u] = ect;

  vX[ect] = x, vY[ect] = y;
  weight[ect] = val;
}

int query(int x, int y) {
  int u = (x * 993244853LL + y) % M;
  for (int e = adj[u]; e; e = nxt[e])
    if (vX[e] == x && vY[e] == y) {
      return weight[e];
    }
  return 0;
}

bool visA[MaxN], visB[MaxN];

int main() {
#ifdef orzczk
  freopen("a.in", "r", stdin);
#endif

  read(H);
  n = 1 << H, m = (n + 1) >> 1;

  pinv[0] = 1, prod[1] = pinv[1] = 1;
  for (int i = 2; i < n; ++i) {
    prod[i] = 1LL * prod[i >> 1] * i % mod;
    pinv[i] = qpow(1LL * prod[i] * prod[i >> 1] % mod, mod - 2);
  }

  int ans = 0;
  for (int i = m; i < n; ++i) {
    read(p[i]);
    p[i] += m - 1;

    for (int x = i; x > 1; x >>= 1)
      if (visA[x ^ 1])
        for (int y = p[i]; y > 1; y >>= 1)
          if (visB[y ^ 1]) {
            add(ans,
                1LL * prod[i] * prod[p[i]] % mod * query(x ^ 1, y ^ 1) % mod);
          }

    for (int x = i; x > 1; x >>= 1) {
      visA[x] = true;
      for (int y = p[i]; y > 1; y >>= 1) {
        visB[y] = true;
        insert(x, y,
               1LL * pinv[x >> 1] * pinv[y >> 1] % mod * prod[i] % mod *
                   prod[p[i]] % mod);
      }
    }
  }

  std::cout << ans << '\\n';

  return 0;
}