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

/*
　　　∫ ∫ ∫
　　　ノヽ
　　（＿　 ）
　（＿　　　 ）
（＿＿＿＿＿＿ ）
　ヽ(´･ω･)ﾉ　
　　 |　 /
　　 UU
*/
#pragma region macro
#include <bits/stdc++.h>
typedef long long int64;
using namespace std;
typedef vector<int> vi;
const int MOD = (int)1e9 + 7;
const int64 INF = 1LL << 62;
const int inf = 1 << 30;
const char bn = '\\n';
template <class T> bool chmax(T &a, const T &b) {
  if (a < b) {
    a = b;
    return 1;
  }
  return 0;
}
template <class T> bool chmin(T &a, const T &b) {
  if (b < a) {
    a = b;
    return 1;
  }
  return 0;
}
#define REP(i, n) for (int i = 0; i < (n); i++)
#define FOR(i, s, n) for (int i = s; i < (n); i++)
#define ALL(obj) (obj).begin(), (obj).end() // コンテナじゃないと使えない!!
#define debug(x) cerr << #x << ": " << x << "\\n";
#define mp make_pair
template <typename T> ostream &operator<<(ostream &os, const vector<T> &V) {
  int N = V.size();
  REP(i, N) {
    os << V[i];
    if (i != N - 1)
      os << " ";
  }
  os << "\\n";
  return os;
}
template <typename T, typename S>
ostream &operator<<(ostream &os, pair<T, S> const &P) {
  os << "(";
  os << P.first;
  os << " , ";
  os << P.second;
  os << ")";
  return os;
}
template <typename T, typename S, typename U>
ostream &operator<<(ostream &os, tuple<T, S, U> const &P) {
  os << "(";
  os << get<0>(P);
  os << ", ";
  os << get<1>(P);
  os << ", ";
  os << get<2>(P);
  os << ")";
  return os;
}
template <typename T> ostream &operator<<(ostream &os, set<T> const &S) {
  auto it = S.begin();
  while (it != S.end()) {
    os << *it;
    os << " ";
    it++;
  }
  os << "\\n";
  return os;
}
template <typename T> ostream &operator<<(ostream &os, deque<T> &q) {
  for (auto it = q.begin(); it < q.end(); it++) {
    os << *it;
    os << " ";
  }
  os << endl;
  return os;
}
template <typename T, typename S>
ostream &operator<<(ostream &os, map<T, S> const &M) {
  for (auto e : M) {
    os << e;
  }
  os << endl;
  return os;
}
vector<pair<int, int>> dxdy = {mp(0, 1), mp(1, 0), mp(-1, 0), mp(0, -1)};
#pragma endregion
// fixed<<setprecision(10)<<ans<<endl;

#pragma region LS
int64 calc_score(int D, vector<int64> const &C, vector<vector<int64>> const &S,
                 vector<int> T) {
  int64 score = 0;
  vector<int> last(26, -1);
  vector<int64> res(D);
  REP(i, D) {
    last[T[i]] = i;
    score += S[i][T[i]];
    REP(j, 26) { score -= C[j] * (i - last[j]); }
    res[i] = score;
  }
  return score;
  // return res;
}

vector<set<int>> init_set(int D, vector<int> const &T) {
  vector<set<int>> res(26);
  REP(i, 26) {
    res[i].insert(-1);
    res[i].insert(D);
  }
  REP(date, D) { res[T[date]].insert(date); }
  return move(res);
}

int prev_contest(int date, int contest,
                 vector<set<int>> const &contest_schedule) {
  return *--contest_schedule[contest].lower_bound(date);
}

int next_contest(int date, int contest,
                 vector<set<int>> const &contest_schedule) {
  return *contest_schedule[contest].upper_bound(date);
}

int64 replace_contest(int D, vector<int64> const &C,
                      vector<vector<int64>> const &S, vector<int> &T,
                      int64 pre_val, int date, int q,
                      vector<set<int>> &contest_schedule, int &p) {
  int64 new_val = pre_val;
  p = T[date];

  // 1. date日目のコンテストpに関して,lastなんたらでの満足度低下が増える
  new_val -= C[p] * (date - prev_contest(date, p, contest_schedule)) *
             (next_contest(date, p, contest_schedule) - date);
  // 2.          コンテストqに関して,lastなんたらでの満足度低下が減る
  new_val += C[q] * (date - prev_contest(date, q, contest_schedule)) *
             (next_contest(date, q, contest_schedule) - date);
  // 3. p,qに関して満足度が増える
  new_val += S[date][q] - S[date][p];

  contest_schedule[q].insert(date);
  contest_schedule[p].erase(date);
  T[date] = q;

  return new_val;
}

int64 f(int date, int contest, vector<int> const &last, vector<int64> const &C,
        vector<vector<int64>> const &S) {
  int64 res = S[date][contest];
  REP(j, 26) if (j != contest) res -= C[j] * (date - last[j]);
  return res;
}

vector<int> greedy(int D, vector<int64> const &C,
                   vector<vector<int64>> const &S) {
  vector<int> last(26, -1);
  vector<int> T(D, -1);

  int64 tmp = 0;
  REP(date, D) {
    int best_contest;
    int64 best_val = -INF;
    REP(j, 26) {
      auto val = f(date, j, last, C, S);
      if (best_val < val) {
        best_contest = j;
        best_val = val;
      }
    }
    last[best_contest] = date;
    T[date] = best_contest;
    tmp += best_val;
  }
  return T;
}
#pragma endregion

double get_temp(clock_t now, clock_t start_time, clock_t end_time,
                double start_temp, double end_temp) {
  return start_temp + (end_temp - start_temp) * now / 2.0;
  // return double(start_temp * (end_time - now) + end_temp * (now -
  // start_time)) / (end_time - start_time);
}

// inline uint32_t xor128() {
//     static uint32_t y = 2463534242;
//     y = y ^ (y << 13);
//     y = y ^ (y >> 17);
//     return y = y ^ (y << 5);
// }

inline double exp1(double x) {
  x = 1.0 + x / 256.0;
  x *= x;
  x *= x;
  x *= x;
  x *= x;
  x *= x;
  x *= x;
  x *= x;
  x *= x;
  return x;
}

int64 get_max_modify(vector<vector<int>> dist_matrix) {
  int64 res = 0;
  for (auto &row : dist_matrix) {
    sort(row.begin(), row.end(), greater<int>());
    res = max(
        res,
        accumulate(
            row.begin(), row.begin() + 1,
            0LL)); // とりあえずすべての和の最大値を目的関数値更新の最大とする
  }
  return res;
}

int main() {
  cin.tie(nullptr);
  ios::sync_with_stdio(false);
  clock_t start = clock();
  clock_t stop = start + 38 * CLOCKS_PER_SEC / 20;

  int D;
  cin >> D;

  vector<int64> C(26);
  REP(i, 26) cin >> C[i];

  vector<vector<int64>> S(D, vector<int64>(26));
  REP(i, D) REP(j, 26) cin >> S[i][j];

  vector<int> T = greedy(D, C, S);

  auto score = calc_score(D, C, S, T);

  auto contest_schedule = init_set(D, T);

  double start_temp = 3000.0;
  double end_temp = 10.0;

  vector<int> best_sol = T;
  int64 best_score = score;

  while (true) {
    clock_t now = clock();
    if (now >= stop) {
      break;
    }
    double temp = get_temp(now, start, stop, start_temp, end_temp);
    REP(_, 100) {
      int date = rand() % D;
      int contest = rand() % 26;
      int ori;
      int64 new_val = replace_contest(D, C, S, T, score, date, contest,
                                      contest_schedule, ori);
      double prob = exp((new_val - score) / temp);
      if (prob > rand() / (double)RAND_MAX) {
        // 解を更新
        score = new_val;
      } else {
        // 解を更新しないので戻す
        T[date] = ori;
        contest_schedule[contest].erase(date);
        contest_schedule[ori].insert(date);
      }

      if (chmax(best_score, score))
        best_sol = T;
    }
  }

  for (auto t : best_sol)
    cout << t + 1 << bn;
}

Error: TLE

Fixed submission:

/*
　　　∫ ∫ ∫
　　　ノヽ
　　（＿　 ）
　（＿　　　 ）
（＿＿＿＿＿＿ ）
　ヽ(´･ω･)ﾉ　
　　 |　 /
　　 UU
*/
#pragma region macro
#include <bits/stdc++.h>
typedef long long int64;
using namespace std;
typedef vector<int> vi;
const int MOD = (int)1e9 + 7;
const int64 INF = 1LL << 62;
const int inf = 1 << 30;
const char bn = '\\n';
template <class T> bool chmax(T &a, const T &b) {
  if (a < b) {
    a = b;
    return 1;
  }
  return 0;
}
template <class T> bool chmin(T &a, const T &b) {
  if (b < a) {
    a = b;
    return 1;
  }
  return 0;
}
#define REP(i, n) for (int i = 0; i < (n); i++)
#define FOR(i, s, n) for (int i = s; i < (n); i++)
#define ALL(obj) (obj).begin(), (obj).end() // コンテナじゃないと使えない!!
#define debug(x) cerr << #x << ": " << x << "\\n";
#define mp make_pair
template <typename T> ostream &operator<<(ostream &os, const vector<T> &V) {
  int N = V.size();
  REP(i, N) {
    os << V[i];
    if (i != N - 1)
      os << " ";
  }
  os << "\\n";
  return os;
}
template <typename T, typename S>
ostream &operator<<(ostream &os, pair<T, S> const &P) {
  os << "(";
  os << P.first;
  os << " , ";
  os << P.second;
  os << ")";
  return os;
}
template <typename T, typename S, typename U>
ostream &operator<<(ostream &os, tuple<T, S, U> const &P) {
  os << "(";
  os << get<0>(P);
  os << ", ";
  os << get<1>(P);
  os << ", ";
  os << get<2>(P);
  os << ")";
  return os;
}
template <typename T> ostream &operator<<(ostream &os, set<T> const &S) {
  auto it = S.begin();
  while (it != S.end()) {
    os << *it;
    os << " ";
    it++;
  }
  os << "\\n";
  return os;
}
template <typename T> ostream &operator<<(ostream &os, deque<T> &q) {
  for (auto it = q.begin(); it < q.end(); it++) {
    os << *it;
    os << " ";
  }
  os << endl;
  return os;
}
template <typename T, typename S>
ostream &operator<<(ostream &os, map<T, S> const &M) {
  for (auto e : M) {
    os << e;
  }
  os << endl;
  return os;
}
vector<pair<int, int>> dxdy = {mp(0, 1), mp(1, 0), mp(-1, 0), mp(0, -1)};
#pragma endregion
// fixed<<setprecision(10)<<ans<<endl;

#pragma region LS
int64 calc_score(int D, vector<int64> const &C, vector<vector<int64>> const &S,
                 vector<int> T) {
  int64 score = 0;
  vector<int> last(26, -1);
  vector<int64> res(D);
  REP(i, D) {
    last[T[i]] = i;
    score += S[i][T[i]];
    REP(j, 26) { score -= C[j] * (i - last[j]); }
    res[i] = score;
  }
  return score;
  // return res;
}

vector<set<int>> init_set(int D, vector<int> const &T) {
  vector<set<int>> res(26);
  REP(i, 26) {
    res[i].insert(-1);
    res[i].insert(D);
  }
  REP(date, D) { res[T[date]].insert(date); }
  return move(res);
}

int prev_contest(int date, int contest,
                 vector<set<int>> const &contest_schedule) {
  return *--contest_schedule[contest].lower_bound(date);
}

int next_contest(int date, int contest,
                 vector<set<int>> const &contest_schedule) {
  return *contest_schedule[contest].upper_bound(date);
}

int64 replace_contest(int D, vector<int64> const &C,
                      vector<vector<int64>> const &S, vector<int> &T,
                      int64 pre_val, int date, int q,
                      vector<set<int>> &contest_schedule, int &p) {
  int64 new_val = pre_val;
  p = T[date];

  // 1. date日目のコンテストpに関して,lastなんたらでの満足度低下が増える
  new_val -= C[p] * (date - prev_contest(date, p, contest_schedule)) *
             (next_contest(date, p, contest_schedule) - date);
  // 2.          コンテストqに関して,lastなんたらでの満足度低下が減る
  new_val += C[q] * (date - prev_contest(date, q, contest_schedule)) *
             (next_contest(date, q, contest_schedule) - date);
  // 3. p,qに関して満足度が増える
  new_val += S[date][q] - S[date][p];

  contest_schedule[q].insert(date);
  contest_schedule[p].erase(date);
  T[date] = q;

  return new_val;
}

int64 f(int date, int contest, vector<int> const &last, vector<int64> const &C,
        vector<vector<int64>> const &S) {
  int64 res = S[date][contest];
  REP(j, 26) if (j != contest) res -= C[j] * (date - last[j]);
  return res;
}

vector<int> greedy(int D, vector<int64> const &C,
                   vector<vector<int64>> const &S) {
  vector<int> last(26, -1);
  vector<int> T(D, -1);

  int64 tmp = 0;
  REP(date, D) {
    int best_contest;
    int64 best_val = -INF;
    REP(j, 26) {
      auto val = f(date, j, last, C, S);
      if (best_val < val) {
        best_contest = j;
        best_val = val;
      }
    }
    last[best_contest] = date;
    T[date] = best_contest;
    tmp += best_val;
  }
  return T;
}
#pragma endregion

double get_temp(clock_t now, clock_t start_time, clock_t end_time,
                double start_temp, double end_temp) {
  return start_temp + (end_temp - start_temp) * now / 2.0;
  // return double(start_temp * (end_time - now) + end_temp * (now -
  // start_time)) / (end_time - start_time);
}

int64 get_max_modify(vector<vector<int>> dist_matrix) {
  int64 res = 0;
  for (auto &row : dist_matrix) {
    sort(row.begin(), row.end(), greater<int>());
    res = max(
        res,
        accumulate(
            row.begin(), row.begin() + 1,
            0LL)); // とりあえずすべての和の最大値を目的関数値更新の最大とする
  }
  return res;
}

int main() {
  cin.tie(nullptr);
  ios::sync_with_stdio(false);
  clock_t start = clock();
  clock_t stop = start + 38 * CLOCKS_PER_SEC / 20;

  int D;
  cin >> D;

  vector<int64> C(26);
  REP(i, 26) cin >> C[i];

  vector<vector<int64>> S(D, vector<int64>(26));
  REP(i, D) REP(j, 26) cin >> S[i][j];

  vector<int> T = greedy(D, C, S);

  auto score = calc_score(D, C, S, T);

  auto contest_schedule = init_set(D, T);

  double start_temp = 3000.0;
  double end_temp = 10.0;

  while (true) {
    clock_t now = clock();
    if (now >= stop) {
      break;
    }
    double temp = get_temp(now, start, stop, start_temp, end_temp);
    REP(_, 5) {
      REP(date, D) {
        REP(contest, 26) {
          int ori;
          int64 new_val = replace_contest(D, C, S, T, score, date, contest,
                                          contest_schedule, ori);
          double prob = exp((new_val - score) / temp);
          debug((new_val >= score))
              debug(prob) if (prob > rand() / (double)RAND_MAX) {
            // 解を更新
            score = new_val;
          }
          else {
            // 解を更新しないので戻す
            T[date] = ori;
            contest_schedule[contest].erase(date);
            contest_schedule[ori].insert(date);
          }
        }
      }
    }
  }

  for (auto t : T)
    cout << t + 1 << bn;
}