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

#include <bits/stdc++.h>

using namespace std;
#define rep(i, n) for (int i = 0; i < (n); i++)

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

#define INF 1001001001

template <typename T> class BinaryIndexedTree2D {
  int H;
  int W;
  vector<vector<T>> data2d;

public:
  BinaryIndexedTree2D(int H, int W) : H(H), W(W) {
    data2d.resize(H + 1, vector<T>(W + 1, 0));
  }

  T sum(int h, int w) {
    T res = 0;
    for (int i = h; i > 0; i -= i & -i) {
      for (int j = w; j > 0; j -= j & -j) {
        res += data2d[i][j];
      }
    }
    return res;
  }

  /**
   * 左上の座標(h1, w1), 右下の座標(h2, w2) に含まれる値の累積和
   */
  T sum(int h1, int w1, int h2, int w2) {
    return sum(h2, w2) - sum(h1 - 1, w2) - sum(h2, w1 - 1) +
           sum(h1 - 1, w1 - 1);
  }

  void add(int h, int w, ll x) {
    for (int i = h; i <= H; i += i & -i) {
      for (int j = w; j <= W; j += j & -j) {
        data2d[i][j] += x;
      }
    }
  }
};

int main(int, char **) {
  int n;
  cin >> n;
  vector<ll> a(n);
  rep(i, n) {
    string s;
    cin >> s;
    int j = 0;
    ll tmp = 0;
    while (j < s.size() && s[j] != '.')
      tmp = tmp * 10 + (s[j++] - '0');
    if (s[j] == '.')
      j++;
    rep(k, 9) {
      if (j < s.size())
        tmp = tmp * 10 + (s[j++] - '0');
      else
        tmp *= 10;
    }
    a[i] = tmp;
  }
  vector<P> prime25(n);
  rep(i, n) {
    int p2 = 0, p5 = 0;
    while (a[i] % 2 == 0) {
      a[i] /= 2;
      p2++;
    }
    while (a[i] % 5 == 0) {
      a[i] /= 5;
      p5++;
    }
    prime25[i] = {p2, p5};
  }
  ll ans = 0;
  const int bmax = 100;
  BinaryIndexedTree2D<int> bit(bmax, bmax);
  rep(i, n) {
    int x, y;
    tie(x, y) = prime25[i];
    x++;
    y++;
    ans += bit.sum(max(1, 20 - x), max(1, 20 - y), bmax, bmax);
    bit.add(x, y, 1);
  }
  cout << ans << endl;

  return 0;
}

Error: TLE

Fixed submission:

#include <bits/stdc++.h>

using namespace std;
#define rep(i, n) for (int i = 0; i < (n); i++)

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

#define INF 1001001001

template <typename T> class BinaryIndexedTree2D {
  int H;
  int W;
  vector<vector<T>> data2d;

public:
  BinaryIndexedTree2D(int H, int W) : H(H), W(W) {
    data2d.resize(H + 1, vector<T>(W + 1, 0));
  }

  T sum(int h, int w) {
    T res = 0;
    for (int i = h; i > 0; i -= i & -i) {
      for (int j = w; j > 0; j -= j & -j) {
        res += data2d[i][j];
      }
    }
    return res;
  }

  /**
   * 左上の座標(h1, w1), 右下の座標(h2, w2) に含まれる値の累積和
   */
  T sum(int h1, int w1, int h2, int w2) {
    return sum(h2, w2) - sum(h1 - 1, w2) - sum(h2, w1 - 1) +
           sum(h1 - 1, w1 - 1);
  }

  void add(int h, int w, ll x) {
    for (int i = h; i <= H; i += i & -i) {
      for (int j = w; j <= W; j += j & -j) {
        data2d[i][j] += x;
      }
    }
  }
};

vector<pair<ll, ll>> prime_factorize(ll N) {

  vector<pair<ll, ll>> res;
  for (ll a = 2; a * a <= N; ++a) {
    if (N % a != 0)
      continue;
    ll ex = 0; // 指数

    // 割れる限り割り続ける
    while (N % a == 0) {
      ++ex;
      N /= a;
    }
    // その結果を push
    res.push_back({a, ex});
  }
  // 最後に残った数について
  if (N != 1)
    res.push_back({N, 1});
  return res;
}

int main(int, char **) {
  int n;
  cin >> n;
  vector<ll> a(n);
  rep(i, n) {
    string s;
    cin >> s;
    int j = 0;
    ll tmp = 0;
    while (j < s.size() && s[j] != '.')
      tmp = tmp * 10 + (s[j++] - '0');
    if (s[j] == '.')
      j++;
    rep(k, 9) {
      if (j < s.size())
        tmp = tmp * 10 + (s[j++] - '0');
      else
        tmp *= 10;
    }
    a[i] = tmp;
  }
  vector<P> prime25(n);
  rep(i, n) {
    auto ps = prime_factorize(a[i]);
    for (auto p : ps) {
      if (p.first == 2)
        prime25[i].first = p.second;
      if (p.first == 5)
        prime25[i].second = p.second;
    }
  }
  ll ans = 0;
  const int bmax = 100;
  BinaryIndexedTree2D<int> bit(bmax, bmax);
  rep(i, n) {
    int x, y;
    tie(x, y) = prime25[i];
    x++;
    y++;
    ans += bit.sum(max(1, 20 - x), max(1, 20 - y), bmax, bmax);
    bit.add(x, y, 1);
  }
  cout << ans << endl;

  return 0;
}