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

#include <bits/stdc++.h>
using namespace std;
#define rep(i, n) for (int i = 0; i < (int)(n); ++i)
#define rrep(i, n) for (int i = (int)(n)-1; i >= 0; --i)
#define For(i, a, b) for (auto i = (a); i <= (b); ++i)
#define rFor(i, a, b) for (auto i = (b); i >= (a); --i)
#define call(var) cerr << #var << "=" << var << "\\n";
#define dup(x, y) (((x) + (y)-1) / (y))
#define all(x) (x).begin(), (x).end()
using ll = long long;
using vi = vector<int>;
using vl = vector<ll>;
using vb = vector<bool>;
using Graph = vector<vi>;
using P = pair<int, int>;
const int MOD = (int)1e9 + 7;
const int INF = (int)1e9;
const ll LINF = (ll)1e18;
const double pi = acos(-1);
template <class t, class u> inline bool chmax(t &a, u b) {
  if (a < b) {
    a = b;
    return true;
  }
  return false;
}
template <class t, class u> inline bool chmin(t &a, u b) {
  if (b < a) {
    a = b;
    return true;
  }
  return false;
}
template <class T> istream &operator>>(istream &is, vector<T> &a) {
  rep(i, a.size()) is >> a[i];
  return is;
}
template <class T> ostream &operator<<(ostream &os, vector<T> &a) {
  rep(i, a.size()) os << a[i] << " ";
  return os;
}
template <class T, class U> istream &operator>>(istream &is, pair<T, U> &p) {
  is >> p.first >> p.second;
  return is;
}
template <class T, class U>
ostream &operator<<(ostream &os, const pair<T, U> &p) {
  os << "(" << p.first << "," << p.second << ")";
  return os;
}
template <class T, class U>
ostream &operator<<(ostream &os, const map<T, U> &mp) {
  for (auto &t : mp)
    os << t.first << " " << t.second << "\\n";
  return os;
}
template <class T> ostream &operator<<(ostream &os, const set<T> &se) {
  for (auto &t : se)
    os << t << " ";
  return os;
}

int D, score;
vi c(26 + 1);
// D+1 * 26+1 vec
vector<vi> s;
// 1 ~ 26 のコンテストnumber
vi output;
// 1 ~ 26 のコンテストについて最後に開催した日
vector<set<int>> last_day(26 + 1);

void init() {
  cin >> D;
  rep(i, 26) cin >> c[i + 1];
  s.resize(D + 1, vi(26 + 1));
  rep(i, D) rep(j, 26) cin >> s[i + 1][j + 1];
  output.resize(D + 1);
  for (int i = 1; i <= 26; ++i)
    last_day[i].insert(0), last_day[i].insert(D + 1);
  srand(time(nullptr));
}

int last(int d, int i) {
  // d日目より前にタイプiのコンテストを開催した日
  auto it = last_day[i].end();
  it = prev(it, 1);
  while (*it != 0 && *it > d) {
    it = prev(it, 1);
    // cout << *it << "\\n";
  }
  return *it;
}

int loss_calc(int a, int b, int i) { return (b - a - 1) * (b - a) / 2 * c[i]; }

ll calScore() {
  ll ret = 0;
  // vi b_ret(D+1);
  // for(int i=1;i<=D;++i){
  //     b_ret[i] = b_ret[i-1];

  //     // コンテスト開催による加算
  //     // ret += s[i][output[i]];
  //     b_ret[i] += s[i][output[i]];

  //     // コンテスト非開催による減算
  //     for(int j=1;j<=26;++j){
  //         if(j == output[i]) continue;
  //         // ret -= c[j] * (i - last(i, j));
  //         b_ret[i] -= c[j] * (i - last(i, j));
  //     }
  // }

  for (int i = 1; i <= 26; ++i) {
    // cerr << " ---- i : " << i << " ----\\n";
    for (auto it = last_day[i].begin(); *it != D + 1; ++it) {
      if (*it != 0)
        ret += s[*it][i];
      // cerr << "s[*it][i] = " << s[*it][i] << "\\n";
      // cerr << "*it=" << *it << " *next(it,1)=" << *next(it, 1) << " loss_calc
      // = " << loss_calc(*it, *next(it, 1), i) << "\\n";
      ret -= loss_calc(*it, *next(it, 1), i);
    }
    // cerr << "ret = " << ret << "\\n";
  }

  // B_ret
  // cerr << "----B_ret----\\n";
  // for(int i=1;i<=D;++i){
  //     cout << b_ret[i] << "\\n";
  // }
  return ret;
}

int delete_ld(int i, int d) {
  // コンテストiからdを消す
  auto itr_d = last_day[i].find(d);
  auto pre_d = prev(itr_d, 1);
  auto aft_d = next(itr_d, 1);

  // int ret = loss_calc(*itr_d, *pre_d, i) - s[d][i] - loss_calc(*aft_d,
  // *pre_d, i);
  int ret = -loss_calc(*pre_d, *aft_d, i) + loss_calc(*pre_d, *itr_d, i) +
            loss_calc(*itr_d, *aft_d, i) - s[d][i];
  // last_day[i].erase(d);
  // cerr << "delete_ld return : " << ret << "\\n";
  return ret;
}

int add_ld(int i, int d) {
  // コンテストiにdを追加する
  auto pre_d = prev(lower_bound(all(last_day[i]), d), 1);
  auto aft_d = next(pre_d, 1);

  // int ret = loss_calc(*pre_d, *aft_d, i) - loss_calc(*pre_d, d, i) -
  // loss_calc(*aft_d, d, i) + s[d][i];
  int ret = -loss_calc(*pre_d, d, i) - loss_calc(d, *aft_d, i) +
            loss_calc(*pre_d, *aft_d, i) + s[d][i];
  // last_day[i].insert(d);
  // cerr << "add_ld return : " << ret << "\\n";
  return ret;
}

int change_last_day(int d, int to) {
  int from = output[d];
  int ret = delete_ld(from, d) + add_ld(to, d);
  // output[d] = to;
  return ret;
}

// unsigned int randInt(){
//     static unsigned int tx=123456789, ty=362436069, tz=521288629,
//     tw=88675123; unsigned int tt = (tx^(tx<<11)); tx = ty; ty = tz; tz = tw;
//     return ( tw=(tw^(tw>>19))^(tt^(tt>>8)) );
// }

void change_random_one_point() {
  int old_day = rand() % D + 1;
  int old_contest = output[old_day];

  int new_contest = rand() % 26 + 1;
  int delta = change_last_day(old_day, new_contest);
  if (delta >= 0) {
    output[old_day] = new_contest;
    last_day[old_contest].erase(old_day);
    last_day[new_contest].insert(old_day);
    score += delta;
  } else {
    output[old_day] = old_contest;
  }
}

void random_init() {

  for (int i = 1; i <= D; ++i) {
    output[i] = rand() % 26 + 1;
    last_day[output[i]].insert(i);
  }
}

void gready_init() {
  // その日のうち最も高い満足度を得られるものを初期値とする
  for (int i = 1; i <= D; ++i) {
    // cerr << "i = " << i << " : " << max_element(s[i].begin(), s[i].end()) -
    // s[i].begin() + 1 << "\\n";
    output[i] = max_element(s[i].begin(), s[i].end()) - s[i].begin() + 1;
    last_day[output[i]].insert(i);
  }
  // cerr << "output : " << output << "\\n";
}

int main() {
  // 時間計測
  chrono::system_clock::time_point start_time, end_time;
  start_time = chrono::system_clock::now();

  // cin.tie(0);
  // ios::sync_with_stdio(false);

  init();

  // ランダム初期化
  // init_random();
  random_init();

  // cerr << output << "\\n";
  // 初期化したときのscoreを計算
  score = calScore();
  cerr << "score = " << score << "\\n";

  // while(time < 1900){ ランダムに値を変える}
  int time_limit = 1900;
  ll exe_num = 0;
  while (true) {

    auto elapsed = chrono::duration_cast<chrono::milliseconds>(
        chrono::system_clock::now() - start_time);
    // cerr << "time elapsed = " << elapsed.count() << "\\n";
    if (elapsed.count() >= time_limit) {
      break;
    }
    ++exe_num;

    change_random_one_point();
  }
  // 答えを出力
  // cerr << "+++++ output +++++\\n";
  for (int i = 1; i <= D; ++i) {
    cout << output[i] << "\\n";
  }
  // for(int i=1;i<=26;++i){
  //     cerr << "contest " << i << " : " << last_day[i] << "\\n";
  // }
  cerr << "exe_num = " << exe_num << "\\n";
  cerr << "score = " << score << "\\n";
}

Error: WA

Fixed submission:

#include <bits/stdc++.h>
using namespace std;
#define rep(i, n) for (int i = 0; i < (int)(n); ++i)
#define rrep(i, n) for (int i = (int)(n)-1; i >= 0; --i)
#define For(i, a, b) for (auto i = (a); i <= (b); ++i)
#define rFor(i, a, b) for (auto i = (b); i >= (a); --i)
#define call(var) cerr << #var << "=" << var << "\\n";
#define dup(x, y) (((x) + (y)-1) / (y))
#define all(x) (x).begin(), (x).end()
using ll = long long;
using vi = vector<int>;
using vl = vector<ll>;
using vb = vector<bool>;
using Graph = vector<vi>;
using P = pair<int, int>;
const int MOD = (int)1e9 + 7;
const int INF = (int)1e9;
const ll LINF = (ll)1e18;
const double pi = acos(-1);
template <class t, class u> inline bool chmax(t &a, u b) {
  if (a < b) {
    a = b;
    return true;
  }
  return false;
}
template <class t, class u> inline bool chmin(t &a, u b) {
  if (b < a) {
    a = b;
    return true;
  }
  return false;
}
template <class T> istream &operator>>(istream &is, vector<T> &a) {
  rep(i, a.size()) is >> a[i];
  return is;
}
template <class T> ostream &operator<<(ostream &os, vector<T> &a) {
  rep(i, a.size()) os << a[i] << " ";
  return os;
}
template <class T, class U> istream &operator>>(istream &is, pair<T, U> &p) {
  is >> p.first >> p.second;
  return is;
}
template <class T, class U>
ostream &operator<<(ostream &os, const pair<T, U> &p) {
  os << "(" << p.first << "," << p.second << ")";
  return os;
}
template <class T, class U>
ostream &operator<<(ostream &os, const map<T, U> &mp) {
  for (auto &t : mp)
    os << t.first << " " << t.second << "\\n";
  return os;
}
template <class T> ostream &operator<<(ostream &os, const set<T> &se) {
  for (auto &t : se)
    os << t << " ";
  return os;
}

int D, score;
vi c(26 + 1);
// D+1 * 26+1 vec
vector<vi> s;
// 1 ~ 26 のコンテストnumber
vi output;
// 1 ~ 26 のコンテストについて最後に開催した日
vector<set<int>> last_day(26 + 1);

void init() {
  cin >> D;
  rep(i, 26) cin >> c[i + 1];
  s.resize(D + 1, vi(26 + 1));
  rep(i, D) rep(j, 26) cin >> s[i + 1][j + 1];
  output.resize(D + 1);
  for (int i = 1; i <= 26; ++i)
    last_day[i].insert(0), last_day[i].insert(D + 1);
  srand(time(nullptr));
}

int last(int d, int i) {
  // d日目より前にタイプiのコンテストを開催した日
  auto it = last_day[i].end();
  it = prev(it, 1);
  while (*it != 0 && *it > d) {
    it = prev(it, 1);
    // cout << *it << "\\n";
  }
  return *it;
}

int loss_calc(int a, int b, int i) { return (b - a - 1) * (b - a) / 2 * c[i]; }

ll calScore() {
  ll ret = 0;
  // vi b_ret(D+1);
  // for(int i=1;i<=D;++i){
  //     b_ret[i] = b_ret[i-1];

  //     // コンテスト開催による加算
  //     // ret += s[i][output[i]];
  //     b_ret[i] += s[i][output[i]];

  //     // コンテスト非開催による減算
  //     for(int j=1;j<=26;++j){
  //         if(j == output[i]) continue;
  //         // ret -= c[j] * (i - last(i, j));
  //         b_ret[i] -= c[j] * (i - last(i, j));
  //     }
  // }

  for (int i = 1; i <= 26; ++i) {
    // cerr << " ---- i : " << i << " ----\\n";
    for (auto it = last_day[i].begin(); *it != D + 1; ++it) {
      if (*it != 0)
        ret += s[*it][i];
      // cerr << "s[*it][i] = " << s[*it][i] << "\\n";
      // cerr << "*it=" << *it << " *next(it,1)=" << *next(it, 1) << " loss_calc
      // = " << loss_calc(*it, *next(it, 1), i) << "\\n";
      ret -= loss_calc(*it, *next(it, 1), i);
    }
    // cerr << "ret = " << ret << "\\n";
  }

  // B_ret
  // cerr << "----B_ret----\\n";
  // for(int i=1;i<=D;++i){
  //     cout << b_ret[i] << "\\n";
  // }
  return ret;
}

int delete_ld(int i, int d) {
  // コンテストiからdを消す
  auto itr_d = last_day[i].find(d);
  auto pre_d = prev(itr_d, 1);
  auto aft_d = next(itr_d, 1);

  // int ret = loss_calc(*itr_d, *pre_d, i) - s[d][i] - loss_calc(*aft_d,
  // *pre_d, i);
  int ret = -loss_calc(*pre_d, *aft_d, i) + loss_calc(*pre_d, *itr_d, i) +
            loss_calc(*itr_d, *aft_d, i) - s[d][i];
  // last_day[i].erase(d);
  // cerr << "delete_ld return : " << ret << "\\n";
  return ret;
}

int add_ld(int i, int d) {
  // コンテストiにdを追加する
  auto pre_d = prev(lower_bound(all(last_day[i]), d), 1);
  auto aft_d = next(pre_d, 1);

  // int ret = loss_calc(*pre_d, *aft_d, i) - loss_calc(*pre_d, d, i) -
  // loss_calc(*aft_d, d, i) + s[d][i];
  int ret = -loss_calc(*pre_d, d, i) - loss_calc(d, *aft_d, i) +
            loss_calc(*pre_d, *aft_d, i) + s[d][i];
  // last_day[i].insert(d);
  // cerr << "add_ld return : " << ret << "\\n";
  return ret;
}

int change_last_day(int d, int to) {
  int from = output[d];
  int ret = delete_ld(from, d) + add_ld(to, d);
  // output[d] = to;
  return ret;
}

// unsigned int randInt(){
//     static unsigned int tx=123456789, ty=362436069, tz=521288629,
//     tw=88675123; unsigned int tt = (tx^(tx<<11)); tx = ty; ty = tz; tz = tw;
//     return ( tw=(tw^(tw>>19))^(tt^(tt>>8)) );
// }

void change_random_one_point() {
  int old_day = rand() % D + 1;
  int old_contest = output[old_day];

  int new_contest = rand() % 26 + 1;
  int delta = change_last_day(old_day, new_contest);
  if (delta >= 0) {
    output[old_day] = new_contest;
    last_day[old_contest].erase(old_day);
    last_day[new_contest].insert(old_day);
    score += delta;
  } else {
    output[old_day] = old_contest;
  }
}

void init_random() {

  for (int i = 1; i <= D; ++i) {
    output[i] = rand() % 26 + 1;
    last_day[output[i]].insert(i);
  }
}

void gready_init() {
  // その日のうち最も高い満足度を得られるものを初期値とする
  for (int i = 1; i <= D; ++i) {
    // cerr << "i = " << i << " : " << max_element(s[i].begin(), s[i].end()) -
    // s[i].begin() + 1 << "\\n";
    output[i] = max_element(s[i].begin(), s[i].end()) - s[i].begin() + 1;
    last_day[output[i]].insert(i);
  }
  // cerr << "output : " << output << "\\n";
}

int main() {
  // 時間計測
  chrono::system_clock::time_point start_time, end_time;
  start_time = chrono::system_clock::now();

  // cin.tie(0);
  // ios::sync_with_stdio(false);

  init();

  // ランダム初期化
  // init_random();
  gready_init();

  // cerr << output << "\\n";
  // 初期化したときのscoreを計算
  score = calScore();
  cerr << "score = " << score << "\\n";

  // while(time < 1900){ ランダムに値を変える}
  int time_limit = 1900;
  ll exe_num = 0;
  while (true) {

    auto elapsed = chrono::duration_cast<chrono::milliseconds>(
        chrono::system_clock::now() - start_time);
    // cerr << "time elapsed = " << elapsed.count() << "\\n";
    if (elapsed.count() >= time_limit) {
      break;
    }
    ++exe_num;

    change_random_one_point();
  }
  // 答えを出力
  // cerr << "+++++ output +++++\\n";
  for (int i = 1; i <= D; ++i) {
    cout << output[i] << "\\n";
  }
  // for(int i=1;i<=26;++i){
  //     cerr << "contest " << i << " : " << last_day[i] << "\\n";
  // }
  cerr << "exe_num = " << exe_num << "\\n";
  cerr << "score = " << score << "\\n";
}