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

#include <algorithm>
#include <iostream>
#include <math.h>
#include <queue>
#include <set>
#include <string.h>
#include <string>
#include <vector>

using namespace std;
struct UnionFind {
  vector<int> par; // par[i]:iの親の番号　(例) par[3] = 2 : 3の親が2

  UnionFind(int N) : par(N) { // 最初は全てが根であるとして初期化
    for (int i = 0; i < N; i++)
      par[i] = i;
  }

  int root(int x) { // データxが属する木の根を再帰で得る：root(x) = {xの木の根}
    if (par[x] == x)
      return x;
    return par[x] = root(par[x]);
  }

  void unite(int x, int y) { // xとyの木を併合
    int rx = root(x);        // xの根をrx
    int ry = root(y);        // yの根をry
    if (rx == ry)
      return; // xとyの根が同じ(=同じ木にある)時はそのまま
    par[rx] =
        ry; // xとyの根が同じでない(=同じ木にない)時：xの根rxをyの根ryにつける
  }

  bool same(int x, int y) { // 2つのデータx, yが属する木が同じならtrueを返す
    int rx = root(x);
    int ry = root(y);
    return rx == ry;
  }
};

template <class T> inline bool chmin(T &a, T b) {
  // aの方が大きければbに値を更新、そうでなければ何もしない
  if (a > b) {
    a = b;
    return true;
  }
  return false;
}
template <class T> inline bool chmax(T &a, T b) {
  if (a < b) {
    a = b;
    return true;
  }
  return false;
}
bool compare_a_big(pair<int, int> l, pair<int, int> r) {
  // firstが大きい方からソート、firstが同じならbが小さい方から
  if (l.first != r.first) {
    return l.first > r.first;
  } else {
    return l.second < r.second;
  }
}
bool compare_a_b_big(pair<int, int> l, pair<int, int> r) {
  // firstが大きい方からソート、firstが同じならbが大きい方から
  if (l.first != r.first) {
    return l.first > r.first;
  } else {
    return l.second > r.second;
  }
}
bool compare_b_small(pair<int, int> l, pair<int, int> r) {
  // secondが小さい方からソート、firstが同じならfirstが小さい方から
  if (l.second != r.second) {
    return l.second < r.second;
  } else {
    return l.first < r.first;
  }
}
const int INF = 1e9;
const int M = 1000000007;

typedef long long int ll;
vector<ll> fac(3001);  // n!(mod M)
vector<ll> ifac(3001); // k!^{M-2} (mod M)
// a,bの範囲的にこれだけ配列を用意していけば十分

ll mpow(ll x,
        ll n) { // x^n(mod M) ←普通にpow(x,n)では溢れてしまうため，随時mod計算
  ll ans = 1;
  while (n != 0) {
    if (n & 1)
      ans = ans * x % M;
    x = x * x % M;
    n = n >> 1;
  }
  return ans;
}

ll comb(ll a, ll b) { // aCbをmod計算、a,b<=300000でないと使えない
  fac[0] = 1;
  ifac[0] = 1;
  for (ll i = 0; i < 3000; i++) {
    fac[i + 1] = fac[i] * (i + 1) % M; // n!(mod M)
    ifac[i + 1] =
        ifac[i] * mpow(i + 1, M - 2) % M; // k!^{M-2} (mod M) ←累乗にmpowを採用
  }
  if (a == 0 && b == 0)
    return 1;
  if (a < b || a < 0)
    return 0;
  ll tmp = ifac[a - b] * ifac[b] % M;
  return tmp * fac[a] % M;
}

typedef long long int ll;

int pow(int a, int b) {
  if (b == 0)
    return 1;
  else {
    return a * pow(a, b - 1);
  }
}

typedef struct ListNode {
  int data;
  struct ListNode *next;
} ListNode;

int main() {
  int n, i;
  cin >> n;
  int x[n], y[n];
  for (i = 0; i < n; i++) {
    cin >> x[i] >> y[i];
  }
  int fx[n][4];
  for (i = 0; i < n; i++) {
    fx[i][0] = x[i] + y[i];
    fx[i][1] = x[i] - y[i];
    fx[i][2] = -x[i] + y[i];
    fx[i][3] = -x[i] - y[i];
  }

  int max[4] = {0, 0, 0, 0};
  int maxv = -INF;
  int minv = INF;
  for (i = 0; i < 4; i++) {
    for (int j = 0; j < n; j++) {
      if (fx[j][i] > maxv) {
        maxv = fx[j][i];
      }
      if (fx[j][i] < minv) {
        minv = fx[j][i];
      }
    }
    max[i] = abs(maxv - minv);
    maxv = -INF;
    minv = INF;
  }

  int ans = 0;
  for (int j = 0; j < 4; j++) {
    if (ans < max[j]) {
      ans = max[j];
    }
  }
  cout << ans << endl;
}


Error: TLE

Fixed submission:

#include <algorithm>
#include <iostream>
#include <math.h>
#include <queue>
#include <set>
#include <string.h>
#include <string>
#include <vector>

using namespace std;
struct UnionFind {
  vector<int> par; // par[i]:iの親の番号　(例) par[3] = 2 : 3の親が2

  UnionFind(int N) : par(N) { // 最初は全てが根であるとして初期化
    for (int i = 0; i < N; i++)
      par[i] = i;
  }

  int root(int x) { // データxが属する木の根を再帰で得る：root(x) = {xの木の根}
    if (par[x] == x)
      return x;
    return par[x] = root(par[x]);
  }

  void unite(int x, int y) { // xとyの木を併合
    int rx = root(x);        // xの根をrx
    int ry = root(y);        // yの根をry
    if (rx == ry)
      return; // xとyの根が同じ(=同じ木にある)時はそのまま
    par[rx] =
        ry; // xとyの根が同じでない(=同じ木にない)時：xの根rxをyの根ryにつける
  }

  bool same(int x, int y) { // 2つのデータx, yが属する木が同じならtrueを返す
    int rx = root(x);
    int ry = root(y);
    return rx == ry;
  }
};

template <class T> inline bool chmin(T &a, T b) {
  // aの方が大きければbに値を更新、そうでなければ何もしない
  if (a > b) {
    a = b;
    return true;
  }
  return false;
}
template <class T> inline bool chmax(T &a, T b) {
  if (a < b) {
    a = b;
    return true;
  }
  return false;
}
bool compare_a_big(pair<int, int> l, pair<int, int> r) {
  // firstが大きい方からソート、firstが同じならbが小さい方から
  if (l.first != r.first) {
    return l.first > r.first;
  } else {
    return l.second < r.second;
  }
}
bool compare_a_b_big(pair<int, int> l, pair<int, int> r) {
  // firstが大きい方からソート、firstが同じならbが大きい方から
  if (l.first != r.first) {
    return l.first > r.first;
  } else {
    return l.second > r.second;
  }
}
bool compare_b_small(pair<int, int> l, pair<int, int> r) {
  // secondが小さい方からソート、firstが同じならfirstが小さい方から
  if (l.second != r.second) {
    return l.second < r.second;
  } else {
    return l.first < r.first;
  }
}
const int INF = 1e9;
const int M = 1000000007;

typedef long long int ll;
vector<ll> fac(3001);  // n!(mod M)
vector<ll> ifac(3001); // k!^{M-2} (mod M)
// a,bの範囲的にこれだけ配列を用意していけば十分

ll mpow(ll x,
        ll n) { // x^n(mod M) ←普通にpow(x,n)では溢れてしまうため，随時mod計算
  ll ans = 1;
  while (n != 0) {
    if (n & 1)
      ans = ans * x % M;
    x = x * x % M;
    n = n >> 1;
  }
  return ans;
}

ll comb(ll a, ll b) { // aCbをmod計算、a,b<=300000でないと使えない
  fac[0] = 1;
  ifac[0] = 1;
  for (ll i = 0; i < 3000; i++) {
    fac[i + 1] = fac[i] * (i + 1) % M; // n!(mod M)
    ifac[i + 1] =
        ifac[i] * mpow(i + 1, M - 2) % M; // k!^{M-2} (mod M) ←累乗にmpowを採用
  }
  if (a == 0 && b == 0)
    return 1;
  if (a < b || a < 0)
    return 0;
  ll tmp = ifac[a - b] * ifac[b] % M;
  return tmp * fac[a] % M;
}

typedef long long int ll;

int pow(int a, int b) {
  if (b == 0)
    return 1;
  else {
    return a * pow(a, b - 1);
  }
}

typedef struct ListNode {
  int data;
  struct ListNode *next;
} ListNode;

int main() {
  int n, i;
  cin >> n;
  int x[n], y[n];
  for (i = 0; i < n; i++) {
    cin >> x[i] >> y[i];
  }
  int fx[n][4];
  for (i = 0; i < n; i++) {
    fx[i][0] = x[i] + y[i];
    fx[i][1] = x[i] - y[i];
    fx[i][2] = -x[i] + y[i];
    fx[i][3] = -x[i] - y[i];
  }

  int ans = 0;
  for (int j = 0; j < 4; j++) {
    for (i = 0; i < n - 1; i++) {
      for (int k = i + 1; k < n; k++) {
        if (ans < abs(fx[i][j] - fx[k][j])) {
          ans = abs(fx[i][j] - fx[k][j]);
        }
      }
    }
  }
  cout << ans << endl;
}