Problem p02618 (C++)

Buggy submission (status: Runtime Error):
#include <algorithm>
#include <chrono>
#include <iostream>
#include <set>
#include <vector>
using namespace std;
typedef long long Int;

#define KIND 26
// #define KIND 2
Int D;
Int c[KIND];
Int s[400][KIND];
Int last[KIND];

vector<Int> best_t;

std::chrono::time_point<std::chrono::steady_clock> start;

double dice() { return double(rand()) / RAND_MAX; }

double prob(double rest) { return rest * 1e-4; }

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

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 ContestInfo {
  set<Int> held[KIND];
  vector<Int> t;
  int D;
  Int score = 0;
  ContestInfo(int D) : D(D) {
    t.resize(D, -1);
    for (int i = 0; i < KIND; i++) {
      held[i].insert(-1);
      held[i].insert(D);
      score += c[i] * range(-1, D);
    }
  }

  void add(int d, int q) {
    if (t[d] != -1) {
      cout << "Add failed" << endl;
      exit(1);
    }
    t[d] = q;
    score += s[d][q];
    held[q].insert(d);
    auto it = held[q].find(d);
    auto rit = next(it);
    auto lit = prev(it);
    score -= c[q] * range(*lit, *rit);
    score += c[q] * range(*it, *rit);
    score += c[q] * range(*lit, *it);
  }

  void erase(int d) {
    if (t[d] == -1) {
      cout << "erase failed" << endl;
      exit(1);
    }
    int q = t[d];
    t[d] = -1;
    score -= s[d][q];
    auto it = held[q].find(d);
    auto rit = next(it);
    auto lit = prev(it);
    score += c[q] * range(*lit, *rit);
    score -= c[q] * range(*it, *rit);
    score -= c[q] * range(*lit, *it);
    held[q].erase(it);
  }

  void change(int d, int q) {
    erase(d);
    add(d, q);
  }

  void output() {
    for (int i = 0; i < D; i++) {
      cout << t[i] + 1 << endl;
    }
  }

  void save() { best_t = t; }
};

int main() {
  cin >> D;
  for (Int i = 0; i < KIND; i++) {
    cin >> c[i];
  }
  for (Int d = 0; d < D; d++) {
    for (Int i = 0; i < KIND; i++) {
      cin >> s[d][i];
    }
  }

  ContestInfo ci(D);
  tic();

  for (int _d = 0; _d < D; _d++) {
    int new_d;
    int new_q;
    Int best_score = -1;
    for (int d = 0; d < D; d++) {
      if (ci.t[d] != -1)
        continue;
      ci.add(d, 0);
      for (int i = 0; i < KIND; i++) {
        if (ci.t[d] != i)
          ci.change(d, i);
        if (ci.score > best_score) {
          best_score = ci.score;
          new_q = i;
          new_d = d;
        }
      }
      ci.erase(d);
    }
    ci.add(new_d, new_q);
  }

  Int current_score = ci.score;
  ci.save();
  Int best_score = current_score;
  while (toc() < 1.9) {
    Int d, q;
    d = rand() % D;
    int TRIAL = 1;
    int old = ci.t[d];
    vector<int> score(TRIAL);
    vector<int> contest_type(TRIAL);
    int best_contest_type_ind = 0;
    for (int i = 0; i < TRIAL; i++) {
      contest_type[i] = rand() % KIND;
      ci.change(d, contest_type[i]);
      score[i] = ci.score;
      if (score[best_contest_type_ind] < score[i]) {
        best_contest_type_ind = i;
      }
    }
    Int new_score = score[best_contest_type_ind];
    if (new_score > current_score || dice() < prob(1.9 - toc())) {
      // よかったら登る
      current_score = new_score;
      ci.change(d, contest_type[best_contest_type_ind]);
    } else {
      // 悪かったらそっちいかない
      ci.change(d, old);
    }
    if (current_score > best_score) {
      best_score = current_score;
      ci.save();
    }
  }

  for (int i = 0; i < D; i++)
    cout << best_t[i] + 1 << endl;
  return 0;
}

Fixed submission:
#include <algorithm>
#include <chrono>
#include <iostream>
#include <set>
#include <vector>
using namespace std;
typedef long long Int;

#define KIND 26
// #define KIND 2
Int D;
Int c[KIND];
Int s[400][KIND];
Int last[KIND];

vector<Int> best_t;

std::chrono::time_point<std::chrono::steady_clock> start;

double dice() { return double(rand()) / RAND_MAX; }

double prob(double rest) { return rest * 1e-4; }

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

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 ContestInfo {
  set<Int> held[KIND];
  vector<Int> t;
  int D;
  Int score = 0;
  ContestInfo(int D) : D(D) {
    t.resize(D, -1);
    for (int i = 0; i < KIND; i++) {
      held[i].insert(-1);
      held[i].insert(D);
      score += c[i] * range(-1, D);
    }
  }

  void add(int d, int q) {
    if (t[d] != -1) {
      cout << "Add failed" << endl;
      exit(1);
    }
    t[d] = q;
    score += s[d][q];
    held[q].insert(d);
    auto it = held[q].find(d);
    auto rit = next(it);
    auto lit = prev(it);
    score -= c[q] * range(*lit, *rit);
    score += c[q] * range(*it, *rit);
    score += c[q] * range(*lit, *it);
  }

  void erase(int d) {
    if (t[d] == -1) {
      cout << "erase failed" << endl;
      exit(1);
    }
    int q = t[d];
    t[d] = -1;
    score -= s[d][q];
    auto it = held[q].find(d);
    auto rit = next(it);
    auto lit = prev(it);
    score += c[q] * range(*lit, *rit);
    score -= c[q] * range(*it, *rit);
    score -= c[q] * range(*lit, *it);
    held[q].erase(it);
  }

  void change(int d, int q) {
    erase(d);
    add(d, q);
  }

  void output() {
    for (int i = 0; i < D; i++) {
      cout << t[i] + 1 << endl;
    }
  }

  void save() { best_t = t; }
};

int main() {
  cin >> D;
  for (Int i = 0; i < KIND; i++) {
    cin >> c[i];
  }
  for (Int d = 0; d < D; d++) {
    for (Int i = 0; i < KIND; i++) {
      cin >> s[d][i];
    }
  }

  ContestInfo ci(D);
  tic();

  for (int _d = 0; _d < D; _d++) {
    int new_d;
    int new_q;
    Int best_score = -1e10;
    for (int d = 0; d < D; d++) {
      if (ci.t[d] != -1)
        continue;
      ci.add(d, 0);
      for (int i = 0; i < KIND; i++) {
        if (ci.t[d] != i)
          ci.change(d, i);
        if (ci.score > best_score) {
          best_score = ci.score;
          new_q = i;
          new_d = d;
        }
      }
      ci.erase(d);
    }
    ci.add(new_d, new_q);
  }

  Int current_score = ci.score;
  ci.save();
  Int best_score = current_score;
  while (toc() < 1.9) {
    Int d, q;
    d = rand() % D;
    int TRIAL = 1;
    int old = ci.t[d];
    vector<int> score(TRIAL);
    vector<int> contest_type(TRIAL);
    int best_contest_type_ind = 0;
    for (int i = 0; i < TRIAL; i++) {
      contest_type[i] = rand() % KIND;
      ci.change(d, contest_type[i]);
      score[i] = ci.score;
      if (score[best_contest_type_ind] < score[i]) {
        best_contest_type_ind = i;
      }
    }
    Int new_score = score[best_contest_type_ind];
    if (new_score > current_score || dice() < prob(1.9 - toc())) {
      // よかったら登る
      current_score = new_score;
      ci.change(d, contest_type[best_contest_type_ind]);
    } else {
      // 悪かったらそっちいかない
      ci.change(d, old);
    }
    if (current_score > best_score) {
      best_score = current_score;
      ci.save();
    }
  }

  for (int i = 0; i < D; i++)
    cout << best_t[i] + 1 << endl;
  return 0;
}