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

// -----------------------------------
// author   : MatsuTaku
// country  : Japan
// created  : 06/14/20 20:53:44
// -----------------------------------

#include <bits/stdc++.h>

using namespace std;
using ll = long long;

int main() {
  cin.tie(nullptr);
  ios::sync_with_stdio(false);

  int h, w, k;
  cin >> h >> w >> k;
  int a, b, c, d;
  cin >> a >> b >> c >> d;
  a--;
  b--;
  c--;
  d--;
  vector<string> grid(h);
  for (int i = 0; i < h; i++) {
    cin >> grid[i];
  }

  constexpr int INF = 1e9;
  struct Cost {
    int x, c, k;
    Cost operator+(const Cost &r) const {
      auto xx = x + r.x;
      auto cc = c + r.c;
      if (cc >= k) {
        xx++;
        cc -= k;
      }
      return {xx, cc, k};
    }
    bool operator<(const Cost &r) const { return x != r.x ? x < r.x : c < r.c; }
    bool operator==(const Cost &r) const { return x == r.x and c == r.c; }
    bool operator<=(const Cost &r) const { return *this < r or *this == r; }
    bool operator>(const Cost &r) const { return r < (*this); }
    Cost ceil() const { return {x + (c > 0), 0, k}; }
  };
  const Cost DC = {INF, 0, k};
  vector<vector<array<Cost, 4>>> dist(
      h, vector<array<Cost, 4>>(w, {DC, DC, DC, DC}));
  struct Pos {
    int x, y, d;
    Cost c;
    bool operator>(const Pos &rhs) const { return rhs.c < c; }
  };
  priority_queue<Pos, vector<Pos>, greater<>> qs;
  for (int i = 0; i < 4; i++) {
    dist[a][b][i] = {0, 0, k};
    qs.push({a, b, i, {0, 0, k}});
  }
  constexpr int dir[4][2] = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};
  const Cost mcost{0, 1, k};
  while (not qs.empty()) {
    const auto [x, y, d, c] = qs.top();
    qs.pop();
    if (dist[x][y][d] < c)
      continue;
    auto fx = x + dir[d][0];
    auto fy = y + dir[d][1];
    if (fx >= 0 and fx < h and fy >= 0 and fy < w and
        dist[fx][fy][d] > c + mcost and grid[fx][fy] == '.') {
      dist[fx][fy][d] = c + mcost;
      qs.push({fx, fy, d, c + mcost});
    }
    auto cc = c.ceil();
    for (int i = 0; i < 4; i++) {
      if (i == d)
        continue;
      if (dist[x][y][i] <= cc)
        continue;
      dist[x][y][i] = cc;
      qs.push({x, y, i, cc});
    }
  }
  auto ans = min_element(dist[c][d].begin(), dist[c][d].end())->ceil();
  cout << (ans == DC ? -1 : ans.x) << endl;

  return 0;
}


Error: TLE

Fixed submission:

// -----------------------------------
// author   : MatsuTaku
// country  : Japan
// created  : 06/14/20 20:53:44
// -----------------------------------

#include <bits/stdc++.h>

using namespace std;
using ll = long long;

int main() {
  cin.tie(nullptr);
  ios::sync_with_stdio(false);

  int h, w, k;
  cin >> h >> w >> k;
  int a, b, c, d;
  cin >> a >> b >> c >> d;
  a--;
  b--;
  c--;
  d--;
  vector<string> grid(h);
  for (int i = 0; i < h; i++) {
    cin >> grid[i];
  }
  vector<vector<int>> dh(h), dw(w);
  for (int i = 0; i < w; i++)
    dw[i].push_back(-1);
  for (int i = 0; i < h; i++) {
    dh[i].push_back(-1);
    for (int j = 0; j < w; j++) {
      if (grid[i][j] == '@') {
        dh[i].push_back(j);
        dw[j].push_back(i);
      }
    }
    dh[i].push_back(w);
  }
  for (int i = 0; i < w; i++)
    dw[i].push_back(h);

  vector<vector<int>> dist(h, vector<int>(w, 1e9));
  dist[a][b] = 0;
  struct Pos {
    int x, y;
  };
  queue<Pos> qs;
  qs.push({a, b});
  while (not qs.empty()) {
    auto [x, y] = qs.front();
    qs.pop();
    if (x == c and y == d) {
      break;
    }
    auto cd = dist[x][y];
    // up
    auto uu = *--lower_bound(dw[y].begin(), dw[y].end(), x);
    uu = max(uu, x - k - 1);
    auto ud = *upper_bound(dw[y].begin(), dw[y].end(), x);
    ud = min(ud, x + k + 1);
    for (int i = uu + 1; i < x; i++) {
      assert(grid[i][y] == '.');
      if (dist[i][y] <= cd + 1)
        continue;
      dist[i][y] = cd + 1;
      qs.push({i, y});
    }
    // down
    for (int i = ud - 1; i > x; i--) {
      assert(grid[i][y] == '.');
      if (dist[i][y] <= cd + 1)
        continue;
      dist[i][y] = cd + 1;
      qs.push({i, y});
    }
    auto rl = *--lower_bound(dh[x].begin(), dh[x].end(), y);
    rl = max(rl, y - k - 1);
    auto rr = *upper_bound(dh[x].begin(), dh[x].end(), y);
    rr = min(rr, y + k + 1);
    // left
    for (int i = rl + 1; i < y; i++) {
      assert(grid[x][i] == '.');
      if (dist[x][i] <= cd + 1)
        continue;
      dist[x][i] = cd + 1;
      qs.push({x, i});
    }
    // right
    for (int i = rr - 1; i > y; i--) {
      assert(grid[x][i] == '.');
      if (dist[x][i] <= cd + 1)
        continue;
      dist[x][i] = cd + 1;
      qs.push({x, i});
    }
  }
  cout << (dist[c][d] == 1e9 ? -1 : dist[c][d]) << endl;

  return 0;
}