Problem p02618 (C++)

Buggy submission (status: Runtime Error):
#include <bits/stdc++.h>
#include <chrono>
using namespace std;
#define rep(i, n) for (int i = 0; i < (int)(n); i++)
#define rep1(i, n) for (int i = 1; i <= (int)(n); i++)
typedef int64_t Int;
typedef pair<Int, Int> P;

const Int Q = 26;

Int D;
vector<Int> C(Q);
vector<vector<Int>> S(400, vector<Int>(Q));

Int range(Int l, Int r) {
  Int len = r - l - 1;
  return -len * (len + 1) / 2;
}

//-------------------- 時間計測用 --------------------------
std::chrono::time_point<std::chrono::steady_clock> start;

void tic() { start = std::chrono::steady_clock::now(); }

double toc() {
  auto now = std::chrono::steady_clock::now();
  std::chrono::duration<double> duration = now - start;
  return duration.count();
}
//-----------------------------------------------------------

struct ContestInformation {
  vector<set<Int>> held; // held[q] : コンテストqを行った日程の集合
  vector<Int> schedule; // schedule[d]: d日目に実施するコンテストの番号
  Int score;            // 最終日の満足度
  Int cnt;

  ContestInformation(Int D) {
    schedule.resize(D, 0);
    score = 0;
    cnt = 0;

    held.resize(Q);
    rep(q, Q) {
      held[q].insert(-1);
      held[q].insert(D);
    }
  }

  // scheduleの表示
  void OutputSchedule() { rep(d, D) cout << schedule[d] + 1 << endl; }

  // scheduleの貪欲法による初期化
  void InitSchedule() {
    rep(d, D) {
      Int score_max = -10000000;
      Int opt_q = -1;

      rep(q_now, Q) {
        Int score_next = 0;

        rep(q, Q) {
          if (q == q_now) {
            score_next += S[d][q];
          } else {
            auto itr_last_day = lower_bound(held[q].begin(), held[q].end(), d);
            score_next -= C[q] * (d - *prev(itr_last_day));
          }
        }

        if (score_next > score_max) {
          score_max = score_next;
          opt_q = q_now;
        }
      }

      schedule[d] = opt_q;
      score += score_max;
      held[opt_q].insert(d);
    }
  }

  // d日目のコンテストを一旦なくす
  void close(Int d) {
    Int q_old = schedule[d]; // 変更前のコンテスト
    score -= S[d][q_old];

    auto itr_old = held[q_old].find(d);
    auto r_old = next(itr_old);
    auto l_old = prev(itr_old);
    score += C[q_old] * range(*l_old, *r_old);
    score -= C[q_old] * range(*l_old, *itr_old);
    score -= C[q_old] * range(*itr_old, *r_old);

    held[q_old].erase(d);
    schedule[d] = -1;
  }

  // d日目にコンテストqを開催
  void open(Int d, Int q_new) {
    score += S[d][q_new];
    held[q_new].insert(d);
    schedule[d] = q_new;

    auto itr_new = held[q_new].find(d);
    auto r_new = next(itr_new);
    auto l_new = prev(itr_new);
    score -= C[q_new] * range(*l_new, *r_new);
    score += C[q_new] * range(*l_new, *itr_new);
    score += C[q_new] * range(*itr_new, *r_new);
  }

  // 日程・コンテストをランダムに決めて改善したら変更
  void modify() {
    Int old_score = score;

    Int d = rand() % D;
    Int q_old = schedule[d];
    Int q_new = rand() % 26;

    close(d);
    open(d, q_new);

    if (score < old_score) {
      close(d);
      open(d, q_old);
      cnt++;
    }
  }

  // modifyを2つの日程に対して強制的に実行
  void modify2() {
    Int d1 = rand() % D, d2 = rand() % D;
    Int q1 = rand() % 26, q2 = rand() % 26;

    close(d1);
    open(d1, q1);
    close(d2);
    open(d1, q2);
  }
  // 2つの日程をランダムに決めて改善したらコンテストを入れ替え
  void swap() {
    Int old_score = score;

    Int d1 = rand() % (D - 13), d2 = d1 + 1 + rand() % 13;
    Int q_d1 = schedule[d1], q_d2 = schedule[d2];

    close(d1);
    open(d1, q_d2);
    close(d2);
    open(d2, q_d1);

    if (score < old_score) {
      close(d1);
      open(d1, q_d1);
      close(d2);
      open(d2, q_d2);
      cnt++;
    }
  }
};

int main() {
  cin >> D;
  rep(i, Q) cin >> C[i];
  rep(i, D) rep(j, Q) cin >> S[i][j];

  ContestInformation CI(D);
  tic();

  CI.InitSchedule();
  // CI.OutputSchedule();
  // cout << CI.score << endl;

  while (toc() < 1.9) {
    Int modify_or_swap = rand() % 2;

    if (CI.cnt > 500) {
      CI.modify2();
      CI.cnt = 0;
    } else if (modify_or_swap) {
      CI.modify();
    } else {
      CI.swap();
    }
  }

  CI.OutputSchedule();
}

Fixed submission:
#include <bits/stdc++.h>
#include <chrono>
using namespace std;
#define rep(i, n) for (int i = 0; i < (int)(n); i++)
#define rep1(i, n) for (int i = 1; i <= (int)(n); i++)
typedef int64_t Int;
typedef pair<Int, Int> P;

const Int Q = 26;

Int D;
vector<Int> C(Q);
vector<vector<Int>> S(400, vector<Int>(Q));

Int range(Int l, Int r) {
  Int len = r - l - 1;
  return -len * (len + 1) / 2;
}

//-------------------- 時間計測用 --------------------------
std::chrono::time_point<std::chrono::steady_clock> start;

void tic() { start = std::chrono::steady_clock::now(); }

double toc() {
  auto now = std::chrono::steady_clock::now();
  std::chrono::duration<double> duration = now - start;
  return duration.count();
}
//-----------------------------------------------------------

struct ContestInformation {
  vector<set<Int>> held; // held[q] : コンテストqを行った日程の集合
  vector<Int> schedule; // schedule[d]: d日目に実施するコンテストの番号
  Int score;            // 最終日の満足度
  Int cnt;

  ContestInformation(Int D) {
    schedule.resize(D, 0);
    score = 0;
    cnt = 0;

    held.resize(Q);
    rep(q, Q) {
      held[q].insert(-1);
      held[q].insert(D);
    }
  }

  // scheduleの表示
  void OutputSchedule() { rep(d, D) cout << schedule[d] + 1 << endl; }

  // scheduleの貪欲法による初期化
  void InitSchedule() {
    rep(d, D) {
      Int score_max = -10000000;
      Int opt_q = -1;

      rep(q_now, Q) {
        Int score_next = 0;

        rep(q, Q) {
          if (q == q_now) {
            score_next += S[d][q];
          } else {
            auto itr_last_day = lower_bound(held[q].begin(), held[q].end(), d);
            score_next -= C[q] * (d - *prev(itr_last_day));
          }
        }

        if (score_next > score_max) {
          score_max = score_next;
          opt_q = q_now;
        }
      }

      schedule[d] = opt_q;
      score += score_max;
      held[opt_q].insert(d);
    }
  }

  // d日目のコンテストを一旦なくす
  void close(Int d) {
    Int q_old = schedule[d]; // 変更前のコンテスト
    score -= S[d][q_old];

    auto itr_old = held[q_old].find(d);
    auto r_old = next(itr_old);
    auto l_old = prev(itr_old);
    score += C[q_old] * range(*l_old, *r_old);
    score -= C[q_old] * range(*l_old, *itr_old);
    score -= C[q_old] * range(*itr_old, *r_old);

    held[q_old].erase(d);
    schedule[d] = -1;
  }

  // d日目にコンテストqを開催
  void open(Int d, Int q_new) {
    score += S[d][q_new];
    held[q_new].insert(d);
    schedule[d] = q_new;

    auto itr_new = held[q_new].find(d);
    auto r_new = next(itr_new);
    auto l_new = prev(itr_new);
    score -= C[q_new] * range(*l_new, *r_new);
    score += C[q_new] * range(*l_new, *itr_new);
    score += C[q_new] * range(*itr_new, *r_new);
  }

  // 日程・コンテストをランダムに決めて改善したら変更
  void modify() {
    Int old_score = score;

    Int d = rand() % D;
    Int q_old = schedule[d];
    Int q_new = rand() % 26;

    close(d);
    open(d, q_new);

    if (score < old_score) {
      close(d);
      open(d, q_old);
      cnt++;
    }
  }

  // modifyを2つの日程に対して強制的に実行
  void modify2() {
    Int d1 = rand() % D, d2 = rand() % D;
    Int q1 = rand() % 26, q2 = rand() % 26;

    close(d1);
    open(d1, q1);
    close(d2);
    open(d2, q2);
  }
  // 2つの日程をランダムに決めて改善したらコンテストを入れ替え
  void swap() {
    Int old_score = score;

    Int d1 = rand() % (D - 13), d2 = d1 + 1 + rand() % 13;
    Int q_d1 = schedule[d1], q_d2 = schedule[d2];

    close(d1);
    open(d1, q_d2);
    close(d2);
    open(d2, q_d1);

    if (score < old_score) {
      close(d1);
      open(d1, q_d1);
      close(d2);
      open(d2, q_d2);
      cnt++;
    }
  }
};

int main() {
  cin >> D;
  rep(i, Q) cin >> C[i];
  rep(i, D) rep(j, Q) cin >> S[i][j];

  ContestInformation CI(D);
  tic();

  CI.InitSchedule();
  // CI.OutputSchedule();
  // cout << CI.score << endl;

  while (toc() < 1.9) {
    Int modify_or_swap = rand() % 2;

    if (CI.cnt > 500) {
      CI.modify2();
      CI.cnt = 0;
    } else if (modify_or_swap) {
      CI.modify();
    } else {
      CI.swap();
    }
  }

  CI.OutputSchedule();
}