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

#include <algorithm>
#include <cfloat>
#include <cmath>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <stdio.h>
#include <string>
#include <time.h>
#include <vector>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;

ll *min_data, *max_data, *add_data;
ll first_table[500000];
int N = 1;

void init(ll first_N) {
  while (N < first_N)
    N *= 2;
}

void add(int left, int right, ll value, int node_id, int node_left,
         int node_right) {

  if (right < node_left || left > node_right) {
    return;
  } else if (left <= node_left && right >= node_right) {

    add_data[node_id] += value;

    while (node_id != 0) {

      node_id = (node_id - 1) / 2;
      min_data[node_id] =
          min(min_data[2 * node_id + 1] + add_data[2 * node_id + 1],
              min_data[2 * node_id + 2] + add_data[2 * node_id + 2]);
      max_data[node_id] =
          max(max_data[2 * node_id + 1] + add_data[2 * node_id + 1],
              max_data[2 * node_id + 2] + add_data[2 * node_id + 2]);
    }
  } else {

    add(left, right, value, 2 * node_id + 1, node_left,
        (node_left + node_right) / 2);
    add(left, right, value, 2 * node_id + 2, (node_left + node_right) / 2 + 1,
        node_right);
  }
}

ll getMin(int left, int right, int node_id, int node_left, int node_right) {
  if (right < node_left || left > node_right)
    return BIG_NUM;
  else if (left <= node_left && right >= node_right) {
    return min_data[node_id] + add_data[node_id];

  } else {

    ll left_min = getMin(left, right, 2 * node_id + 1, node_left,
                         (node_left + node_right) / 2);
    ll right_min = getMin(left, right, 2 * node_id + 2,
                          (node_left + node_right) / 2 + 1, node_right);
    return min(left_min, right_min) + add_data[node_id];
  }
}

ll getMax(int left, int right, int node_id, int node_left, int node_right) {
  if (right < node_left || left > node_right)
    return -BIG_NUM;
  else if (left <= node_left && right >= node_right) {
    return max_data[node_id] + add_data[node_id];

  } else {

    ll left_max = getMax(left, right, 2 * node_id + 1, node_left,
                         (node_left + node_right) / 2);
    ll right_max = getMax(left, right, 2 * node_id + 2,
                          (node_left + node_right) / 2 + 1, node_right);
    return max(left_max, right_max) + add_data[node_id];
  }
}

int main() {

  int first_N;
  scanf("%d", &first_N);

  for (int i = 0; i < first_N; i++)
    scanf("%lld", &first_table[i]);

  for (int i = 0; i < first_N / 2; i++) {
    first_table[i] -= first_table[(first_N - 1) - i];
  }

  first_N /= 2;
  init(first_N);

  min_data = new ll[2 * N - 1];
  max_data = new ll[2 * N - 1];
  add_data = new ll[2 * N - 1];

  for (ll i = 0; i <= 2 * N - 2; i++) {
    min_data[i] = 0;
    max_data[i] = 0;
    add_data[i] = 0;
  }

  for (int i = 0; i < first_N; i++) {
    add(i, i, first_table[i], 0, 0, N - 1);
  }

  int Q;
  scanf("%d", &Q);

  int left, right, tmp, calc_left;
  ll add_value;

  for (int i = 0; i < Q; i++) {
    scanf("%d %d %lld", &left, &right, &add_value);
    left--;
    right--;

    if (left >= first_N) {

      tmp = right;
      right = (2 * first_N - 1) - left;
      left = (2 * first_N - 1) - tmp;

      add(left, right, -add_value, 0, 0, N - 1);

    } else { // left < first_N

      if (right < first_N) {
        add(left, right, add_value, 0, 0, N - 1);

      } else { // right > first_N

        if (left + right == 2 * first_N - 1) {
          // Do nothing
        } else {

          calc_left = (2 * first_N - 1) - right;

          if (calc_left < left) {

            right = left - 1;
            left = calc_left;
            add(left, right, -add_value, 0, 0, N - 1);

          } else {

            right = calc_left - 1;
            add(left, right, add_value, 0, 0, N - 1);
          }
        }
      }
    }

    if (getMin(0, first_N - 1, 0, 0, N - 1) == 0 &&
        getMax(0, first_N - 1, 0, 0, N - 1) == 0) {
      printf("1\\n");
    } else {
      printf("0\\n");
    }
  }

  return 0;
}


Error: TLE

Fixed submission:

#include <algorithm>
#include <cfloat>
#include <cmath>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <stdio.h>
#include <string>
#include <time.h>
#include <vector>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;

ll *uniformity, *partial;
ll first_table[500000];
ll N = 1;

void init(ll first_N) {
  while (N < first_N)
    N *= 2;
}

void add_and_updateNodes(ll left, ll right, ll value, ll node_id, ll node_left,
                         ll node_right) {

  if (right < node_left || left > node_right)
    return;
  else if (left <= node_left && right >= node_right) {
    uniformity[node_id] += value;
  } else {
    partial[node_id] +=
        (min(right, node_right) - max(left, node_left) + 1) * value;
    add_and_updateNodes(left, right, value, 2 * node_id + 1, node_left,
                        (node_left + node_right) / 2);
    add_and_updateNodes(left, right, value, 2 * node_id + 2,
                        (node_left + node_right) / 2 + 1, node_right);
  }
}

ll getSum(ll left, ll right, ll node_id, ll node_left, ll node_right) {
  if (right < node_left || left > node_right)
    return 0;
  else if (left <= node_left && right >= node_right) {

    return (node_right - node_left + 1) * uniformity[node_id] +
           partial[node_id];

  } else {
    ll sum = (min(right, node_right) - max(left, node_left) + 1) *
             uniformity[node_id];

    sum += getSum(left, right, 2 * node_id + 1, node_left,
                  (node_left + node_right) / 2);
    sum += getSum(left, right, 2 * node_id + 2,
                  (node_left + node_right) / 2 + 1, node_right);
    return sum;
  }
}

int main() {

  int first_N;
  scanf("%d", &first_N);

  for (int i = 0; i < first_N; i++)
    scanf("%lld", &first_table[i]);

  for (int i = 0; i < first_N / 2; i++) {
    first_table[i] -= first_table[(first_N - 1) - i];
  }

  first_N /= 2;
  init(first_N);

  uniformity = new ll[2 * N - 1];
  partial = new ll[2 * N - 1];

  for (ll i = 0; i <= 2 * N - 2; i++) {
    uniformity[i] = 0;
    partial[i] = 0;
  }

  // 右半分との差分を登録<データを半分にする>
  for (int i = 0; i < first_N; i++) {
    add_and_updateNodes(i, i, first_table[i], 0, 0, N - 1);
  }

  int Q;
  scanf("%d", &Q);

  int left, right, tmp, calc_left, pre;
  ll add_value;
  bool FLG;

  for (int i = 0; i < Q; i++) {
    scanf("%d %d %lld", &left, &right, &add_value);
    left--;
    right--;

    if (left >= first_N) { // 幻の右半分にだけデータを加算する場合

      tmp = right;
      right = (2 * first_N - 1) - left;
      left = (2 * first_N - 1) - tmp;

      add_and_updateNodes(left, right, -add_value, 0, 0,
                          N - 1); // 対応する左半分の区間に反転した値を加算

      if (pre == 1) {
        printf("0\\n");
        pre = 0;
        continue;
      }

    } else { // left < first_N

      if (right < first_N) {
        add_and_updateNodes(left, right, add_value, 0, 0, N - 1);

        if (pre == 1) {
          printf("0\\n");
          pre = 0;
          continue;
        }

      } else { // right > first_N:区間を跨ぐ場合

        if (left + right == 2 * first_N - 1) { // ちょうど左右対称
          printf("%d\\n", pre);
          continue;
          // Do nothing
        } else {

          calc_left = (2 * first_N - 1) - right; // 折り返した左端

          if (calc_left < left) { // 右半分の方が多く塗る場合

            // 右半分ではみ出す区間分のみ、反転した値で塗る
            right = left - 1;
            left = calc_left;
            add_and_updateNodes(left, right, -add_value, 0, 0, N - 1);

          } else { // 左半分の方が多く塗る場合

            right = calc_left - 1;
            add_and_updateNodes(left, right, add_value, 0, 0, N - 1);
          }

          if (pre == 1) {
            printf("0\\n");
            pre = 0;
            continue;
          }
        }
      }
    }

    if (getSum(0, first_N - 1, 0, 0, N - 1) == 0) {

      FLG = true;
      for (int i = 0; i < first_N; i++) {
        if (getSum(i, i, 0, 0, N - 1) != 0) {
          FLG = false;
          break;
        }
      }

      if (FLG) {
        printf("1\\n");
        pre = 1;
      } else {
        printf("0\\n");
        pre = 0;
      }
    } else {
      printf("0\\n");
      pre = 0;
    }
  }

  return 0;
}