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

#include <bits/stdc++.h>
using namespace std;
#define ll long long

// ライブラリ始まり (簡潔ver)

// 定数
// 円周率
const double pi = 3.1415926535897932384;
// 天井
const int INF = 1000000000;       // = 10^9
const ll LINF = 1000000000000000; // = 10^15
// ABC文字列
const string ABC = "ABCDEFGHIJKLMNOPQRSTUVWXYZABC";
const string abc = "abcdefghijklmnopqrstuvwxyzabc";
// よくあるmodくん
const ll MOD = 1000000007; // = 10^9 + 7

// データ構造
// Union_Find木
struct UnionFind {
  vector<int> UF;   // UF.at(i) : iの親の番号
  vector<int> SIZE; // SIZE.at(root(i)) : iと連結されてる要素の数
  UnionFind(int N) : UF(N), SIZE(N, 1) { // 最初は全てが根であるとして初期化
    for (int i = 0; i < N; i++) {
      UF.at(i) = i;
    }
  }
  int root(int x) { // データxが属する木の根を再帰で得る：root(x) = {xの木の根}
    if (UF.at(x) == x) {
      return x;
    }
    return UF.at(x) = root(UF.at(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の根が同じ(=同じ木にある)時はそのまま
    }
    // xとyの根が同じでない(=同じ木にない)時：小さい方の根を大きい方の根につける
    if (SIZE.at(rx) < SIZE.at(ry)) {
      UF.at(rx) = ry;
      SIZE.at(ry) += SIZE.at(rx);
      SIZE.at(rx) = 0;
    } else {
      UF.at(ry) = rx;
      SIZE.at(rx) += SIZE.at(ry);
      SIZE.at(ry) = 0;
    }
  }
  bool same(int x, int y) { // 2つのデータx, yが属する木が同じならtrueを返す
    int rx = root(x);
    int ry = root(y);
    return rx == ry;
  }
  int size(int x) { // xと連結されてる要素の数を返す
    return SIZE.at(root(x));
  }
};

// ライブラリ終わり

// メイン処理
int main() {
  ll X, K, D;
  cin >> X >> K >> D;
  X = abs(X);
  if (X / D > K) {
    cout << X - D * K << endl;
  } else {
    if ((X / D) % 2 == K % 2) {
      cout << X % D << endl;
    } else {
      cout << D - X % D << endl;
    }
  }
}


Error: TLE

Fixed submission:

#include <bits/stdc++.h>
using namespace std;
#define ll long long

// ライブラリ始まり (簡潔ver)

// 定数
// 円周率
const double pi = 3.1415926535897932384;
// 天井
const int INF = 1000000000;       // = 10^9
const ll LINF = 1000000000000000; // = 10^15
// ABC文字列
const string ABC = "ABCDEFGHIJKLMNOPQRSTUVWXYZABC";
const string abc = "abcdefghijklmnopqrstuvwxyzabc";
// よくあるmodくん
const ll MOD = 1000000007; // = 10^9 + 7

// データ構造
// Union_Find木
struct UnionFind {
  vector<int> UF;   // UF.at(i) : iの親の番号
  vector<int> SIZE; // SIZE.at(root(i)) : iと連結されてる要素の数
  UnionFind(int N) : UF(N), SIZE(N, 1) { // 最初は全てが根であるとして初期化
    for (int i = 0; i < N; i++) {
      UF.at(i) = i;
    }
  }
  int root(int x) { // データxが属する木の根を再帰で得る：root(x) = {xの木の根}
    if (UF.at(x) == x) {
      return x;
    }
    return UF.at(x) = root(UF.at(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の根が同じ(=同じ木にある)時はそのまま
    }
    // xとyの根が同じでない(=同じ木にない)時：小さい方の根を大きい方の根につける
    if (SIZE.at(rx) < SIZE.at(ry)) {
      UF.at(rx) = ry;
      SIZE.at(ry) += SIZE.at(rx);
      SIZE.at(rx) = 0;
    } else {
      UF.at(ry) = rx;
      SIZE.at(rx) += SIZE.at(ry);
      SIZE.at(ry) = 0;
    }
  }
  bool same(int x, int y) { // 2つのデータx, yが属する木が同じならtrueを返す
    int rx = root(x);
    int ry = root(y);
    return rx == ry;
  }
  int size(int x) { // xと連結されてる要素の数を返す
    return SIZE.at(root(x));
  }
};

// ライブラリ終わり

// メイン処理
int main() {
  ll X, K, D;
  cin >> X >> K >> D;
  X = abs(X);
  ll M = X, N = 0, M2 = LINF, N2;
  bool ok = false;
  for (int i = 0; i < K; i++) {
    X -= D;
    if (abs(X) < M) {
      M2 = M;
      N2 = N;
      M = abs(X);
      N = i + 1;
    } else if (M2 > abs(X)) {
      M2 = abs(X);
      N2 = i + 1;
    }
    if (X < 0) {
      ok = true;
      break;
    }
  }
  if (ok) {
    if (K % 2 == N % 2) {
      cout << M << endl;
    } else {
      cout << M2 << endl;
    }
  } else {
    cout << M << endl;
  }
}