Problem p02618 (C++) — buggy submission, verdict: Runtime Error

#pragma GCC optimize("Ofast", "unroll-loops")

// #define PRINT_PROGRESS
// #define TEST_WITH_RANDOMCASE

#include <bits/stdc++.h>

using namespace std;

#define K (26) // コンテストの種類

int D;
vector<int> c(K);
vector<vector<int>> s;

// コンテストのタイプおよび日付は0-indexedで数える

void input(void) {
  cin >> D;
  for (auto &ci : c)
    cin >> ci;
  s.resize(D, vector<int>(K));
  for (int i = 0; i < D; ++i)
    for (auto &sij : s[i])
      cin >> sij;
}

void random_input(void) {
  D = 365;
  for (auto &ci : c)
    ci = rand() % 101;
  s.resize(D, vector<int>(K));
  for (int i = 0; i < D; ++i)
    for (auto &sij : s[i])
      sij = rand() % 200001;
}

vector<int> t;             // 暫定解
vector<set<int>> c_day(K); // c_day[i] : コンテストiが開催される日程
int score;                 // 暫定解のスコア

int calc_score(void) {
  vector<int> lst_held(K, -1);
  int score = 0;
  for (int i = 0; i < D; ++i) {
    score += s[i][t[i]];
    lst_held[t[i]] = i;
    for (int c_id = 0; c_id < K; ++c_id) {
      score -= c[c_id] * (i - lst_held[c_id]);
    }
  }
  return score;
}

void init_t(void) {
  t.resize(D);

#ifdef PRINT_PROGRESS
  cout << "    MAKING INITIAL SOLUTION..." << endl;
#endif
  // edit from here
  for (int i = 0; i < D; ++i) {
    int mx = -1, mx_c = -1;
    for (int c_id = 0; c_id < K; ++c_id)
      if (mx < s[i][c_id])
        mx = s[i][c_id], mx_c = c_id;
      else if (mx == s[i][c_id] && c[mx_c] > c[c_id])
        mx = s[i][c_id], mx_c = c_id;
    t[i] = mx_c;
  }
  // edit end
#ifdef PRINT_PROGRESS
  cout << "    INITIAL SOLUTION : DONE." << endl;
#endif

  for (int c_id = 0; c_id < K; ++c_id)
    c_day[c_id].insert(-1);
  for (int i = 0; i < D; ++i)
    c_day[t[i]].insert(i);
  for (int c_id = 0; c_id < K; ++c_id)
    c_day[c_id].insert(D);

#ifdef PRINT_PROGRESS
  cout << "    INITIALIZE c_day : DONE." << endl;
#endif

  score = calc_score();
}

void print_t(void) {
  for (auto ti : t)
    cout << (ti + 1) << endl;
}

// d日目をc_idに変更する
void update_t(int d, int c_id) {
  // 消す処理
  int del_c = t[d];
  auto iter = c_day[del_c].lower_bound(d);
  int prv = *(--iter);
  ++iter;
  int nx = *(++iter);
  --iter;
  c_day[del_c].erase(iter);
  score -= s[d][del_c];
  score -= c[del_c] * (d - prv) * (nx - d);
  // 増やす処理
  iter = c_day[c_id].lower_bound(d);
  nx = *iter;
  --iter;
  prv = *iter;
  score += c[c_id] * (d - prv) * (nx - d);
  score += s[d][c_id];
  c_day[c_id].insert(d);
  // tの変更
  t[d] = c_id;
}

// そのupdateによるgain(実際にupdateはしない)
int gain_update(int d, int c_id) {
  int res = 0;
  // 消す処理
  int del_c = t[d];
  auto iter = c_day[del_c].lower_bound(d);
  int prv = *(--iter);
  ++iter;
  int nx = *(++iter);
  --iter;
  res -= s[d][del_c];
  res -= c[del_c] * (d - prv) * (nx - d);
  // 増やす処理
  iter = c_day[c_id].lower_bound(d);
  nx = *iter;
  --iter;
  prv = *iter;
  res += c[c_id] * (d - prv) * (nx - d);
  res += s[d][c_id];
  return res;
}

void random_update(void) {
  int change_dat = rand() % D;
  int change_to = rand() % K;
  if (gain_update(change_dat, change_to) > 0)
    update_t(change_dat, change_to);
}

int main(void) {
  chrono::system_clock::time_point start, now;
  start = chrono::system_clock::now();

#ifdef PRINT_PROGRESS
  cout << "INPUT : START." << endl;
#endif
#ifdef TEST_WITH_RANDOMCASE
  random_input();
#else
  input();
#endif
#ifdef PRINT_PROGRESS
  cout << "INPUT : DONE." << endl;
  cout << "INITIALIZE : START." << endl;
#endif
  init_t();
#ifdef PRINT_PROGRESS
  cout << "INITIALIZE : DONE." << endl;
#endif

  int loop = 0;

  while (1) {
    random_update();
    ++loop;
    now = chrono::system_clock::now();
    double time = static_cast<double>(
        chrono::duration_cast<chrono::microseconds>(now - start).count() /
        1000.0);
    if (time > 1900)
      break;
  }

#ifdef PRINT_PROGRESS
  cout << "UPDATED " << loop << " TIMES." << endl;
#endif

  print_t();

  return 0;
}

Error: WA

Fixed submission:

#pragma GCC optimize("Ofast", "unroll-loops")

#include <bits/stdc++.h>

using namespace std;

#define K (26) // コンテストの種類

int D;
vector<int> c(K);
vector<vector<int>> s;

// コンテストのタイプおよび日付は0-indexedで数える
void input(void) {
  cin >> D;
  for (auto &ci : c)
    cin >> ci;
  s.resize(D, vector<int>(K));
  for (int i = 0; i < D; ++i)
    for (auto &sij : s[i])
      cin >> sij;
}

vector<int> t;             // 暫定解
vector<set<int>> c_day(K); // c_day[i] : コンテストiが開催される日程
int score;                 // 暫定解のスコア

int calc_score(void) {
  vector<int> lst_held(K, -1);
  int score = 0;
  for (int i = 0; i < D; ++i) {
    score += s[i][t[i]];
    lst_held[t[i]] = i;
    for (int c_id = 0; c_id < K; ++c_id) {
      score -= c[c_id] * (i - lst_held[c_id]);
    }
  }
  return score;
}

void init_t(void) {
  t.resize(D);

  // edit from here
  for (int i = 0; i < D; ++i) {
    int mx = -1, mx_c = -1;
    for (int c_id = 0; c_id < K; ++c_id)
      if (mx < s[i][c_id])
        mx = s[i][c_id], mx_c = i;
      else if (mx == s[i][c_id] && c[mx_c] > c[c_id])
        mx = s[i][c_id], mx_c = i;
    t[i] = mx_c;
  }
  // edit end

  for (int c_id = 0; c_id < K; ++c_id)
    c_day[c_id].insert(-1);
  for (int i = 0; i < D; ++i)
    c_day[t[i]].insert(i);
  for (int c_id = 0; c_id < K; ++c_id)
    c_day[c_id].insert(D);
  score = calc_score();
}

void print_t(void) {
  for (auto ti : t)
    cout << (ti + 1) << endl;
}

// d日目をc_idに変更する
void update_t(int d, int c_id) {
  // 消す処理
  int del_c = t[d];
  auto iter = c_day[del_c].lower_bound(d);
  int prv = *(--iter);
  ++iter;
  int nx = *(++iter);
  --iter;
  c_day[del_c].erase(iter);
  score -= s[d][del_c];
  score -= c[del_c] * (d - prv) * (nx - d);
  // 増やす処理
  iter = c_day[c_id].lower_bound(d);
  nx = *iter;
  --iter;
  prv = *iter;
  score += c[c_id] * (d - prv) * (nx - d);
  score += s[d][c_id];
  c_day[c_id].insert(d);
  // tの変更
  t[d] = c_id;
}

// そのupdateによるgain(実際にupdateはしない)
int gain_update(int d, int c_id) {
  int res = 0;
  // 消す処理
  int del_c = t[d];
  auto iter = c_day[del_c].lower_bound(d);
  int prv = *(--iter);
  ++iter;
  int nx = *(++iter);
  --iter;
  res -= s[d][del_c];
  res -= c[del_c] * (d - prv) * (nx - d);
  // 増やす処理
  iter = c_day[c_id].lower_bound(d);
  nx = *iter;
  --iter;
  prv = *iter;
  res += c[c_id] * (d - prv) * (nx - d);
  res += s[d][c_id];
  return res;
}

void random_update(void) {
  int change_dat = rand() % D;
  int change_to = rand() % K;
  if (gain_update(change_dat, change_to) > 0)
    update_t(change_dat, change_to);
}

int main(void) {
  chrono::system_clock::time_point start, now;
  start = chrono::system_clock::now();

  input();
  init_t();

  while (1) {
    random_update();
    now = chrono::system_clock::now();
    double time = static_cast<double>(
        chrono::duration_cast<chrono::microseconds>(now - start).count() /
        1000.0);
    if (time > 1900)
      break;
  }

  print_t();

  return 0;
}