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

#include <bits/stdc++.h>
#define debug(x) cerr << #x << ": " << x << endl
#define debugArray(x, n)                                                       \\
  for (long long hoge = 0; (hoge) < (n); ++(hoge))                             \\
  cerr << #x << "[" << hoge << "]: " << x[hoge] << endl
using namespace std;

signed main() {
  cin.tie(0);
  ios::sync_with_stdio(false);
  const long long INF = LLONG_MAX / 10;
  int H, W, K;
  cin >> H >> W >> K;
  int dx[4] = {-1, 0, 0, 1};
  int dy[4] = {0, -1, 1, 0};
  int x1, y1, x2, y2;
  cin >> x1 >> y1 >> x2 >> y2;
  x1--, y1--, x2--, y2--;
  string ike[H];
  for (int i = 0; i < H; i++) {
    cin >> ike[i];
  }
  using P = pair<int, int>;
  queue<pair<long long, P>> que;
  que.emplace(0, P(x1 * W + y1, -1));
  long long dist[H * W];
  fill(dist, dist + H * W, INF);
  dist[x1 * W + y1] = 0;
  while (!que.empty()) {
    long long cost;
    P p;
    tie(cost, p) = que.front();
    que.pop();
    int x = p.first / W, y = p.first % W;
    if (dist[p.first] < cost)
      continue;
    if (x == x2 && y == y2)
      break;
    for (int d = 0; d < 4; d++) {
      if (d == p.second)
        continue;
      int cx = x, cy = y;
      for (int i = 1; i <= K; i++) {
        cx += dx[d];
        cy += dy[d];
        if (cx < 0 || H <= cx || cy < 0 || W <= cy)
          break;
        if (ike[cx][cy] == '@')
          break;
        if (dist[cx * W + cy] <= dist[x * W + y])
          break;
        if (dist[cx * W + cy] > cost + 1) {
          dist[cx * W + cy] = cost + 1;
          que.emplace(dist[cx * W + cy], P(cx * W + cy, 3 - d));
        }
      }
    }
  }
  cout << (dist[x2 * W + y2] == INF ? -1 : dist[x2 * W + y2]) << endl;
  return 0;
}


Error: TLE

Fixed submission:

#include <bits/stdc++.h>
#define debug(x) cerr << #x << ": " << x << endl
#define debugArray(x, n)                                                       \\
  for (long long hoge = 0; (hoge) < (n); ++(hoge))                             \\
  cerr << #x << "[" << hoge << "]: " << x[hoge] << endl
using namespace std;

namespace internal {
template <bool Is64bit> class find_bucket_impl;
template <> class find_bucket_impl<false> {
public:
  static inline constexpr size_t find_bucket(uint32_t x, uint32_t last) {
    return x == last ? 0 : 32 - __builtin_clz(x ^ last);
  }
};
template <> class find_bucket_impl<true> {
public:
  static inline constexpr size_t find_bucket(uint64_t x, uint64_t last) {
    return x == last ? 0 : 64 - __builtin_clzll(x ^ last);
  }
};
template <typename T> inline constexpr size_t find_bucket(T x, T last) {
  return find_bucket_impl<sizeof(T) == 8>::find_bucket(x, last);
}
template <typename key_t, bool IsSigned> class encoder_impl_integer;
template <typename key_t> class encoder_impl_integer<key_t, false> {
public:
  using ukey_t = key_t;
  inline static constexpr ukey_t encode(key_t x) { return x; }
  inline static constexpr key_t decode(ukey_t x) { return x; }
};
template <typename key_t> class encoder_impl_integer<key_t, true> {
public:
  typedef typename make_unsigned<key_t>::type ukey_t;
  inline static constexpr ukey_t encode(key_t x) {
    return static_cast<ukey_t>(x) ^
           (ukey_t(1) << ukey_t(numeric_limits<ukey_t>::digits - 1));
  }
  inline static constexpr key_t decode(ukey_t x) {
    return static_cast<key_t>(
        x ^ (ukey_t(1) << (numeric_limits<ukey_t>::digits - 1)));
  }
};
template <typename key_t, typename ukey_t> class encoder_impl_decimal {
public:
  inline static constexpr ukey_t encode(key_t x) {
    return raw_cast<key_t, ukey_t>(x) ^
           ((-(raw_cast<key_t, ukey_t>(x) >>
               (numeric_limits<ukey_t>::digits - 1))) |
            (ukey_t(1) << (numeric_limits<ukey_t>::digits - 1)));
  }
  inline static constexpr key_t decode(ukey_t x) {
    return raw_cast<ukey_t, key_t>(
        x ^ (((x >> (numeric_limits<ukey_t>::digits - 1)) - 1) |
             (ukey_t(1) << (numeric_limits<ukey_t>::digits - 1))));
  }

private:
  template <typename T, typename U> union raw_cast {
  public:
    constexpr raw_cast(T t) : t_(t) {}
    operator U() const { return u_; }

  private:
    T t_;
    U u_;
  };
};
template <typename key_t>
class encoder : public encoder_impl_integer<key_t, is_signed<key_t>::value> {};
template <>
class encoder<float> : public encoder_impl_decimal<float, uint32_t> {};
template <>
class encoder<double> : public encoder_impl_decimal<double, uint64_t> {};
} // namespace internal

template <typename key_t, typename val_t,
          typename encoder_t = internal::encoder<key_t>>
class RadixHeap {
public:
  typedef typename encoder_t::ukey_t ukey_t;

  RadixHeap() : size_(0), last_(), buckets_() {
    buckets_min_.fill(numeric_limits<ukey_t>::max());
  }

  void push(key_t key, val_t value) {
    const ukey_t x = encoder_t::encode(key);
    assert(last_ <= x);
    ++size_;
    const size_t k = internal::find_bucket(x, last_);
    buckets_[k].emplace_back(x, value);
    buckets_min_[k] = min(buckets_min_[k], x);
  }
  void emplace(key_t key, val_t value) { push(key, value); }
  pair<key_t, val_t> top() {
    pull();
    return make_pair(encoder_t::decode(last_), buckets_[0].back().second);
  }
  pair<key_t, val_t> pop() {
    pull();
    --size_;
    auto ret = make_pair(encoder_t::decode(last_), buckets_[0].back().second);
    buckets_[0].pop_back();
    return ret;
  }
  size_t size() const { return size_; }
  bool empty() const { return size_ == 0; }

private:
  size_t size_;
  ukey_t last_;
  array<vector<pair<ukey_t, val_t>>, numeric_limits<ukey_t>::digits + 1>
      buckets_;
  array<ukey_t, numeric_limits<ukey_t>::digits + 1> buckets_min_;

  void pull() {
    assert(size_ > 0);
    if (!buckets_[0].empty())
      return;
    size_t i = 1;
    while (buckets_[i].empty())
      ++i;
    last_ = buckets_min_[i];
    for (size_t j = 0; j < buckets_[i].size(); ++j) {
      const ukey_t x = buckets_[i][j].first;
      const size_t k = internal::find_bucket(x, last_);
      buckets_[k].emplace_back(move(buckets_[i][j]));
      buckets_min_[k] = min(buckets_min_[k], x);
    }
    buckets_[i].clear();
    buckets_min_[i] = numeric_limits<ukey_t>::max();
  }
};

signed main() {
  cin.tie(0);
  ios::sync_with_stdio(false);
  const long long INF = LLONG_MAX / 10;
  int H, W, K;
  cin >> H >> W >> K;
  int dx[4] = {-1, 0, 0, 1};
  int dy[4] = {0, -1, 1, 0};
  int x1, y1, x2, y2;
  cin >> x1 >> y1 >> x2 >> y2;
  x1--, y1--, x2--, y2--;
  string ike[H];
  for (int i = 0; i < H; i++) {
    cin >> ike[i];
  }
  using P = pair<int, int>;
  RadixHeap<long long, P> que1, que2;
  que1.emplace(0, P(x1 * W + y1, -1));
  que2.emplace(0, P(x2 * W + y2, -1));
  long long dist1[H * W], dist2[H * W];
  fill(dist1, dist1 + H * W, INF);
  fill(dist2, dist2 + H * W, INF);
  dist1[x1 * W + y1] = 0;
  dist2[x2 * W + y2] = 0;
  long long ans = INF;
  while (!que1.empty() && !que2.empty()) {
    if (ans != INF && ans <= que1.top().first + que2.top().first)
      break;
    if (que1.top().first < que2.top().first) {
      long long cost;
      P p;
      tie(cost, p) = que1.top();
      que1.pop();
      int x = p.first / W, y = p.first % W;
      if (dist1[p.first] < cost)
        continue;
      for (int d = 0; d < 4; d++) {
        if (d == p.second)
          continue;
        int cx = x, cy = y;
        for (int i = 1; i <= K; i++) {
          cx += dx[d];
          cy += dy[d];
          if (cx < 0 || H <= cx || cy < 0 || W <= cy)
            break;
          if (ike[cx][cy] == '@')
            break;
          int ccost = cost + 1 + (i - 1) / K;
          if (dist1[cx * W + cy] > ccost) {
            dist1[cx * W + cy] = ccost;
            que1.emplace(dist1[cx * W + cy], P(cx * W + cy, 3 - d));
            if (dist2[cx * W + cy] != INF) {
              if (ans > dist1[cx * W + cy] + dist2[cx * W + cy])
                ans = dist1[cx * W + cy] + dist2[cx * W + cy];
            }
          }
        }
      }
    } else {
      long long cost;
      P p;
      tie(cost, p) = que2.top();
      que2.pop();
      int x = p.first / W, y = p.first % W;
      if (dist2[p.first] < cost)
        continue;
      for (int d = 0; d < 4; d++) {
        if (d == p.second)
          continue;
        int cx = x, cy = y;
        for (int i = 1;; i++) {
          cx += dx[d];
          cy += dy[d];
          if (cx < 0 || H <= cx || cy < 0 || W <= cy)
            break;
          if (ike[cx][cy] == '@')
            break;
          int ccost = cost + 1 + (i - 1) / K;
          if (dist2[cx * W + cy] > ccost) {
            dist2[cx * W + cy] = ccost;
            que2.emplace(dist2[cx * W + cy], P(cx * W + cy, 3 - d));
            if (dist1[cx * W + cy] != INF) {
              if (ans > dist1[cx * W + cy] + dist2[cx * W + cy])
                ans = dist1[cx * W + cy] + dist2[cx * W + cy];
            }
          }
        }
      }
    }
  }
  cout << (ans == INF ? -1 : ans) << endl;
  return 0;
}