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

#include <bits/stdc++.h>

using namespace std;

int num_times_div(long long A, int d) {
  int ret = 0;
  while (A % d == 0) {
    A /= d;
    ret++;
  }
  return ret;
}

const int MAXN = 200100;

int st[4 * MAXN][20][20];

int left(int p) { return (p << 1); }

int right(int p) { return (p << 1) + 1; }

void update(int p, int L, int R, int pos, long long A) {
  if (L > pos or R < pos)
    return;

  if (L == R) {
    for (int i = 0; i < 20; i++) {
      for (int j = 0; j < 20; j++) {
        st[p][i][j] = 0;
      }
    }
    int d2 = num_times_div(A, 2);
    int d5 = num_times_div(A, 5);
    st[p][min(18, d2)][min(18, d5)] = 1;
    return;
  }

  int mid = (L + R) >> 1;
  update(left(p), L, mid, pos, A);
  update(right(p), mid + 1, R, pos, A);

  for (int i = 0; i < 20; i++) {
    for (int j = 0; j < 20; j++) {
      st[p][i][j] = st[left(p)][i][j] + st[right(p)][i][j];
    }
  }
}

void update(int pos, long long A) { update(1, 0, MAXN - 1, pos, A); }

void query(int p, int L, int R, int i, int j, int cnt[][20]) {
  if (L > j or R < i)
    return;

  if (L >= i and R <= j) {
    for (int k = 0; k < 20; k++) {
      for (int l = 0; l < 20; l++) {
        cnt[k][l] += st[p][k][l];
      }
    }
    return;
  }

  int mid = (L + R) >> 1;
  query(left(p), L, mid, i, j, cnt);
  query(right(p), mid + 1, R, i, j, cnt);
}

void query(int i, int j, int cnt[][20]) { query(1, 0, MAXN - 1, i, j, cnt); }

char s[100];

long long read_value() {
  scanf("%s", s);

  int i = 0;
  while (s[i] and s[i] != '.')
    i++;
  int x = 9;

  if (!s[i]) {
    s[i++] = '.';
    s[i] = 0;
  } else {
    i++;
  }

  while (s[i]) {
    i++;
    x--;
  }

  while (x--) {
    s[i++] = '0';
  }
  s[i] = 0;

  long long ret = 0;
  for (int i = 0; s[i]; i++) {
    if (s[i] != '.')
      ret = ret * 10 + s[i] - '0';
  }

  return ret;
}

int main() {
  int N;
  while (scanf("%d", &N) > 0) {
    long long ans = 0;
    int cnt[20][20];
    memset(cnt, 0, sizeof cnt);

    for (int i = 0; i < N; i++) {
      long long A = read_value();

      int d2 = num_times_div(A, 2);
      int d5 = num_times_div(A, 5);

      for (int k = 0; k < 20; k++) {
        for (int l = 0; l < 20; l++) {
          if (min(k + d2, l + d5) >= 18) {
            ans += cnt[k][l];
          }
        }
      }

      cnt[min(d2, 19)][min(d5, 19)]++;
    }

    printf("%lld\\n", ans);
  }
}


Error: TLE

Fixed submission:

#include <bits/stdc++.h>

using namespace std;

int num_times_div(long long A, int d) {
  int ret = 0;
  while (A % d == 0) {
    A /= d;
    ret++;
  }
  return ret;
}

const int MAXN = 200100;

int st[4 * MAXN][20][20];

int left(int p) { return (p << 1); }

int right(int p) { return (p << 1) + 1; }

void update(int p, int L, int R, int pos, long long A) {
  if (L > pos or R < pos)
    return;

  if (L == R) {
    for (int i = 0; i < 20; i++) {
      for (int j = 0; j < 20; j++) {
        st[p][i][j] = 0;
      }
    }
    int d2 = num_times_div(A, 2);
    int d5 = num_times_div(A, 5);
    st[p][min(18, d2)][min(18, d5)] = 1;
    return;
  }

  int mid = (L + R) >> 1;
  update(left(p), L, mid, pos, A);
  update(right(p), mid + 1, R, pos, A);

  for (int i = 0; i < 20; i++) {
    for (int j = 0; j < 20; j++) {
      st[p][i][j] = st[left(p)][i][j] + st[right(p)][i][j];
    }
  }
}

void update(int pos, long long A) { update(1, 0, MAXN - 1, pos, A); }

void query(int p, int L, int R, int i, int j, int cnt[][20]) {
  if (L > j or R < i)
    return;

  if (L >= i and R <= j) {
    for (int k = 0; k < 20; k++) {
      for (int l = 0; l < 20; l++) {
        cnt[k][l] += st[p][k][l];
      }
    }
    return;
  }

  int mid = (L + R) >> 1;
  query(left(p), L, mid, i, j, cnt);
  query(right(p), mid + 1, R, i, j, cnt);
}

void query(int i, int j, int cnt[][20]) { query(1, 0, MAXN - 1, i, j, cnt); }

char s[100];

long long read_value() {
  scanf("%s", s);

  int i = 0;
  while (s[i] and s[i] != '.')
    i++;
  int x = 9;

  if (!s[i]) {
    s[i++] = '.';
    s[i] = 0;
  } else {
    i++;
  }

  while (s[i]) {
    i++;
    x--;
  }

  while (x--) {
    s[i++] = '0';
  }
  s[i] = 0;

  long long ret = 0;
  for (int i = 0; s[i]; i++) {
    if (s[i] != '.')
      ret = ret * 10 + s[i] - '0';
  }

  return ret;
}

int main() {
  int N;
  while (scanf("%d", &N) > 0) {
    long long ans = 0;
    int cnt[20][20];

    for (int i = 0; i < N; i++) {
      long long A = read_value();
      update(i, A);

      memset(cnt, 0, sizeof cnt);
      query(0, i - 1, cnt);

      int d2 = num_times_div(A, 2);
      int d5 = num_times_div(A, 5);

      for (int k = 0; k < 20; k++) {
        for (int l = 0; l < 20; l++) {
          if (min(k + d2, l + d5) >= 18) {
            ans += cnt[k][l];
          }
        }
      }
    }

    printf("%lld\\n", ans);
  }
}