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

#include <bits/stdc++.h>
#define rep(i, n) for (lli i = 0; i < (n); i++)
#define rrep(i, n) for (lli i = (n)-1; i >= 0; i--)
#define vall(x) (x).begin(), (x).end()
using namespace std;
using lli = long long int;
void YESNO(bool), YesNo(bool);
template <class T1, class T2> bool chmin(T1 &l, const T2 &r);
template <class T1, class T2> bool chmax(T1 &l, const T2 &r);
template <class T1, class T2> void vadd(vector<T1> &v, T2 x);

#define int long long int
struct ufind {
  struct node {
    int par, rank, size;
    void init(int i) {
      par = i;
      rank = 0;
      size = 1;
    }
  };
  vector<node> nodes;
  ufind(int n) {
    nodes.resize(n);
    rep(i, n) nodes[i].init(i);
  }
  int find(int x) {
    return nodes[x].par == x ? x : (nodes[x].par = find(nodes[x].par));
  }
  void unite(int x, int y) {
    x = find(x);
    y = find(y);
    if (x == y)
      return;
    if (nodes[x].rank < nodes[y].rank) {
      nodes[x].par = y;
      nodes[y].size += nodes[x].size;
    } else {
      nodes[y].par = x;
      if (nodes[x].rank == nodes[y].rank)
        nodes[x].rank++;
      nodes[x].size += nodes[y].size;
    }
  }
  bool same(int x, int y) { return find(x) == find(y); }
  int size(int x) { return nodes[find(x)].size; }
};
int f[505 * 505] = {};

int N;
void dump_grid() {
  return;
  // rep(i, N) rep(j, N) {
  //   cout << f[i * N + j] << " ";
  //   if (j == N - 1)
  //     cout << endl;
  // }
}
signed main() {
  cin >> N;
  auto get = [=](int x, int y) {
    if (x < 0 || x >= N || y >= N || y < 0)
      return N * N;
    return x * N + y;
  };
  ufind uf(N * N + 1);
  vector<int> P(N * N + 1);
  vector<int> used(N * N + 1);

  rep(i, N) rep(j, N) { f[get(i, j)] = min({i, j, N - i - 1, N - j - 1}); }
  int ret = 0;
  used[N * N] = true;
  int dx[4] = {-1, 0, 1, 0};
  int dy[4] = {0, 1, 0, -1};
  map<int, int> hoge;
  rep(i, N * N) {
    cin >> P[i];
    P[i]--;
    // hoge[P[i]] = i;
  }
  rep(i, N * N) {
    int X = P[i] / N;
    int Y = P[i] % N;
    queue<pair<int, int>> que;
    ret += f[get(X, Y)];
    used[P[i]] = true;
    rep(j, 4) {
      int nx = X + dx[j];
      int ny = Y + dy[j];
      que.push(make_pair(nx, ny));
    }
    while (!que.empty()) {
      auto [cX, cY] = que.front();
      que.pop();
      bool change = false;
      rep(j, 4) {
        int nx = cX + dx[j];
        int ny = cY + dy[j];
        change |=
            chmin(f[get(cX, cY)], f[get(nx, ny)] + (used[get(nx, ny)] ? 0 : 1));
      }
      if (change) {
        rep(j, 4) {
          int nx = cX + dx[j];
          int ny = cY + dy[j];
          que.push({nx, ny});
        }
      }
    }
    dump_grid();
  }
  cout << ret << endl;
}

// -- lib
void YESNO(bool b) { cout << (b ? "YES" : "NO") << endl; }
void YesNo(bool b) { cout << (b ? "Yes" : "No") << endl; }

template <class T1, class T2> bool chmin(T1 &l, const T2 &r) {
  return (l > r) ? (l = r, true) : false;
}

template <class T1, class T2> bool chmax(T1 &l, const T2 &r) {
  return (l < r) ? (l = r, true) : false;
}

template <class T1, class T2> void vadd(vector<T1> &v, T2 x) {
  for (auto &s : v)
    s += T2(x);
}

Error: TLE

Fixed submission:

#include <bits/stdc++.h>
#define rep(i, n) for (lli i = 0; i < (n); i++)
#define rrep(i, n) for (lli i = (n)-1; i >= 0; i--)
#define vall(x) (x).begin(), (x).end()
using namespace std;
using lli = long long int;
void YESNO(bool), YesNo(bool);
template <class T1, class T2> bool chmin(T1 &l, const T2 &r);
template <class T1, class T2> bool chmax(T1 &l, const T2 &r);
template <class T1, class T2> void vadd(vector<T1> &v, T2 x);

#define int long long int
struct ufind {
  struct node {
    int par, rank, size;
    void init(int i) {
      par = i;
      rank = 0;
      size = 1;
    }
  };
  vector<node> nodes;
  ufind(int n) {
    nodes.resize(n);
    rep(i, n) nodes[i].init(i);
  }
  int find(int x) {
    return nodes[x].par == x ? x : (nodes[x].par = find(nodes[x].par));
  }
  void unite(int x, int y) {
    x = find(x);
    y = find(y);
    if (x == y)
      return;
    if (nodes[x].rank < nodes[y].rank) {
      nodes[x].par = y;
      nodes[y].size += nodes[x].size;
    } else {
      nodes[y].par = x;
      if (nodes[x].rank == nodes[y].rank)
        nodes[x].rank++;
      nodes[x].size += nodes[y].size;
    }
  }
  bool same(int x, int y) { return find(x) == find(y); }
  int size(int x) { return nodes[find(x)].size; }
};
int f[505 * 505] = {};
set<int> adj[505 * 505];

int N;
void dump_grid() {
  return;
  // rep(i, N) rep(j, N) {
  //   cout << f[i * N + j] << " ";
  //   if (j == N - 1)
  //     cout << endl;
  // }
}
signed main() {
  cin >> N;
  auto get = [=](int x, int y) {
    if (x < 0 || x >= N || y >= N || y < 0)
      return N * N;
    return x * N + y;
  };
  ufind uf(N * N + 1);
  vector<int> P(N * N + 1);
  vector<int> used(N * N + 1);

  rep(i, N) rep(j, N) { f[get(i, j)] = min({i, j, N - i - 1, N - j - 1}); }
  int ret = 0;
  used[N * N] = true;
  int dx[4] = {-1, 0, 1, 0};
  int dy[4] = {0, 1, 0, -1};
  map<int, int> hoge;
  rep(i, N * N) {
    cin >> P[i];
    P[i]--;
    // hoge[P[i]] = i;
  }
  rep(i, N * N) {
    int X = i / N;
    int Y = i % N;
    rep(j, 4) {
      int nx1 = dx[j] + X;
      int ny1 = dy[j] + Y;
      adj[i].insert(get(nx1, ny1));
    }
  }
  int out = N * N;
  rep(i, N * N) {
    int X = P[i] / N;
    int Y = P[i] % N;
    int score = f[uf.find(get(X, Y))];
    // ret += f[uf.find(get(X, Y))];

    deque<pair<int, int>> que;
    map<int, bool> visited;
    que.push_front({uf.find(get(X, Y)), 0});
    while (!que.empty()) {
      auto [cur, dep] = que.front();
      que.pop_front();
      if (visited[cur])
        continue;
      if (uf.same(cur, out)) {
        ret += dep;
        break;
      }
      visited[cur] = true;
      for (auto s : adj[cur]) {
        int t = uf.find(s);
        if (visited[t])
          continue;
        if (used[t]) {
          que.push_front({t, dep});
        } else {
          que.push_back({t, dep + 1});
        }
      }
    }
    rep(j, 4) {
      int id = uf.find(get(X, Y));
      int nx1 = dx[j] + X;
      int ny1 = dy[j] + Y;
      int id1 = uf.find(get(nx1, ny1));
      int score1 = f[id1];
      if (used[id1]) {
        if (adj[id].size() > adj[id1].size()) {
          for (auto s : adj[id1])
            adj[id].insert(s);
        } else {
          for (auto s : adj[id])
            adj[id1].insert(s);
          swap(adj[id], adj[id1]);
        }
        uf.unite(id, id1);
        if (id != uf.find(id)) {
          swap(adj[id], adj[id1]);
        }
      }
    }
    // cerr << P[i] + 1 << " " << X << " " << Y << " " << score << endl;

    // rep(j, 4) {
    //   int nx1 = dx[j] + X;
    //   int ny1 = dy[j] + Y;
    //   int id1 = uf.find(get(nx1, ny1));
    //   int score1 = f[id1];
    //   bool used1 = used[get(nx1, ny1)];
    //   chmin(f[id1], score);
    //   rep(k, 4) {
    //     int nx2 = dx[k] + X;
    //     int ny2 = dy[k] + Y;
    //     int id2 = uf.find(get(nx2, ny2));
    //     int score2 = f[id2];
    //     bool used2 = used[get(nx2, ny2)];
    //     if (used1 && used2) {
    //       chmin(f[id1], score);
    //       chmin(f[id2], score);
    //       // = min({score1, score2, score});
    //       // f[id2] = min(score1, score2);
    //       uf.unite(id1, id2);
    //       continue;
    //     }
    //     // if (used2) {
    //     //   f[id2] = min(score1 + 1, score2);
    //     //   f[id1] = min(score1, score2);
    //     // }
    //     // if (used1) {
    //     //   f[id1] = min(score1, score2 + 1);
    //     //   f[id2] = min(score1, score2);
    //     // }
    //   }
    // }
    used[uf.find(P[i])] = true;

    dump_grid();
  }
  cout << ret << endl;
}

// -- lib
void YESNO(bool b) { cout << (b ? "YES" : "NO") << endl; }
void YesNo(bool b) { cout << (b ? "Yes" : "No") << endl; }

template <class T1, class T2> bool chmin(T1 &l, const T2 &r) {
  return (l > r) ? (l = r, true) : false;
}

template <class T1, class T2> bool chmax(T1 &l, const T2 &r) {
  return (l < r) ? (l = r, true) : false;
}

template <class T1, class T2> void vadd(vector<T1> &v, T2 x) {
  for (auto &s : v)
    s += T2(x);
}