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

#include <bits/stdc++.h>
#include <math.h>
#include <time.h>
using namespace std;
typedef long long ll;
typedef long double ld;
#define rep(i, n) for (int i = 0; i < (int)(n); i++)
const ll mod = 1000000007;
const ll INF = 1001001001;
const ll LINF = 1001001001001001001;

void prvec(vector<bool> vec) {
  ll n = vec.size();
  rep(i, n) cout << i << " " << vec.at(i) << "\\n";
}

void pr2d(vector<vector<ll>> vvec) {
  ll h = vvec.size();
  ll w = vvec.at(0).size();
  rep(i, h) {
    rep(j, w) { cout << vvec.at(i).at(j) << " "; }
    cout << "\\n";
  }
}

ll cancel_and_add(vector<vector<ll>> &contlis, vector<ll> &cont_order,
                  vector<vector<ll>> &s, vector<ll> &c, ll date, ll add_con) {
  ll diff = 0; // 変更によってsatisがどれだけ変わるか

  ll cur_cont_d =
      cont_order.at(date); // 現在date日に開催されているコンテストの種類
  diff -=
      s.at(date).at(cur_cont_d); // cur_cont_dの開催をやめることによる直接の影響
  diff +=
      s.at(date).at(add_con); // add_conコンテストの分のsatisを増やす直接の影響

  // cur_cont_d開催中止による飽きの影響
  auto it = lower_bound(contlis.at(cur_cont_d).begin(),
                        contlis.at(cur_cont_d).end(), date + 1);
  ll x = it - contlis.at(cur_cont_d).begin();
  ll a = date + 1 - contlis.at(cur_cont_d).at(x - 1) - 1;
  ll b = contlis.at(cur_cont_d).at(x + 1) - (date + 1) - 1;
  ll z =
      contlis.at(cur_cont_d).at(x + 1) - contlis.at(cur_cont_d).at(x - 1) - 1;

  diff = diff - c.at(cur_cont_d) * z * (z + 1) / 2 +
         c.at(cur_cont_d) * a * (a + 1) / 2 +
         c.at(cur_cont_d) * b * (b + 1) / 2;

  // q追加による飽きへの影響
  auto it2 = lower_bound(contlis.at(add_con).begin(), contlis.at(add_con).end(),
                         date + 1);
  x = it2 - contlis.at(add_con).begin();
  a = (date + 1) - contlis.at(add_con).at(x - 1) - 1;
  b = contlis.at(add_con).at(x) - (date + 1) - 1;
  z = contlis.at(add_con).at(x) - contlis.at(add_con).at(x - 1) - 1;
  diff += c.at(add_con) * z * (z + 1) / 2 - c.at(add_con) * a * (a + 1) / 2 -
          c.at(add_con) * b * (b + 1) / 2;
  return diff;
}

int main() {
  clock_t start = clock();

  ll days;
  cin >> days;
  vector<ll> c(26);
  rep(i, 26) cin >> c.at(i);
  vector<vector<ll>> s(days, vector<ll>(26));
  rep(i, days) rep(j, 26) cin >> s.at(i).at(j);
  vector<ll> last(26, 0);

  ll sat = 0;

  ll initial_satis = 0;
  rep(i, 26) { initial_satis -= c.at(i) * days * (days + 1) / 2; }
  // initial_satis =　何もコンテストを開催していない状態の満足度

  ll satis = initial_satis;
  vector<vector<ll>> contlis(26, {0, days + 1});
  vector<ll> cont_order(days);

  while (true) { // ある程度ランダムに生成してたまたま得点が良い組み合わせを探す
    clock_t now = clock();
    const double x = static_cast<double>(now - start) / CLOCKS_PER_SEC;
    if (x > 0.5)
      break;

    ll satis_candidate = initial_satis;

    // ランダムに生成して得点の良い解を探す
    srand(time(NULL));
    vector<ll> rand_init(days);
    rep(i, days) rand_init.at(i) = (rand() % 26);

    // 与えられたtだけコンテストを開催することを考える
    vector<vector<ll>> contlis_candidate(26, {0, days + 1});
    for (int i = 1; i <= days; i++) {
      ll t = rand_init.at(i - 1);
      auto it = lower_bound(contlis_candidate.at(t).begin(),
                            contlis_candidate.at(t).end(), i);
      ll x = it - contlis_candidate.at(t).begin();
      ll a = i - contlis_candidate.at(t).at(x - 1) - 1;
      ll b = contlis_candidate.at(t).at(x) - i - 1;
      ll z =
          contlis_candidate.at(t).at(x) - contlis_candidate.at(t).at(x - 1) - 1;
      satis_candidate += c.at(t) * z * (z + 1) / 2 - c.at(t) * a * (a + 1) / 2 -
                         c.at(t) * b * (b + 1) / 2;
      satis_candidate += s.at(i - 1).at(t);
      contlis_candidate.at(t).insert(it, i);
    }
    if (satis_candidate > satis) {
      satis = satis_candidate;
      cont_order = rand_init;
      contlis = contlis_candidate;
    }
  }

  while (true) {
    clock_t now = clock();
    const double time = static_cast<double>(now - start) / CLOCKS_PER_SEC;
    if (time > 1.950)
      break;

    ll type = rand() % 2;

    if (type == 0) {

      ll d = rand() % days,
         q = rand() %
             26; // 最適化その1:ランダムにdとqを選び、d日目の開催コンテストをq番目のものにする

      if (cancel_and_add(contlis, cont_order, s, c, d, q) >
          0) { // 採用する場合、様々変える
        satis += cancel_and_add(contlis, cont_order, s, c, d, q) > 0;

        { // d日目の開催コンテストをqに変更する
          ll cur_cont_d = cont_order.at(d);
          cont_order.at(d) = q;
          auto erasecon = lower_bound(contlis.at(cur_cont_d).begin(),
                                      contlis.at(cur_cont_d).end(), d + 1);
          contlis.at(cur_cont_d).erase(erasecon);
          auto addcon =
              lower_bound(contlis.at(q).begin(), contlis.at(q).end(), d + 1);
          contlis.at(q).insert(addcon, d + 1);
        }
      }
    } else {

      // 最適化その2:a日目のコンテストとb日目のコンテストを入れ替える
      ll a = rand() % days,
         b = (a + ((rand() % 33) - 16)) % days; // 入れ替える日にちの選択

      if (b < 0)
        b += days;

      // 現状a,b日目に開催されているコンテストは？
      ll cur_cont_a = cont_order.at(a), cur_cont_b = cont_order.at(b);
      ll exchange_diff =
          cancel_and_add(contlis, cont_order, s, c, a, cur_cont_b) +
          cancel_and_add(contlis, cont_order, s, c, b, cur_cont_a);

      if (exchange_diff > 0) { // 変化が0以上なら採用
        cont_order.at(a) = cur_cont_b;
        cont_order.at(b) = cur_cont_a;

        auto erasecon = lower_bound(contlis.at(cur_cont_a).begin(),
                                    contlis.at(cur_cont_a).end(), a + 1);
        contlis.at(cur_cont_a).erase(erasecon);
        auto addcon = lower_bound(contlis.at(cur_cont_b).begin(),
                                  contlis.at(cur_cont_b).end(), a + 1);
        contlis.at(cur_cont_b).insert(addcon, a + 1);

        erasecon = lower_bound(contlis.at(cur_cont_b).begin(),
                               contlis.at(cur_cont_b).end(), b + 1);
        contlis.at(cur_cont_b).erase(erasecon);
        addcon = lower_bound(contlis.at(cur_cont_a).begin(),
                             contlis.at(cur_cont_a).end(), b + 1);
        contlis.at(cur_cont_a).insert(addcon, b + 1);
      }
    }
  }

  rep(i, days) {
    cout << cont_order.at(i) + 1;
    if (i != (days - 1))
      cout << "\\n";
  }

  return 0;
}


Error: -6
terminate called after throwing an instance of 'std::out_of_range'
  what():  vector::_M_range_check: __n (which is 8) >= this->size() (which is 5)


Fixed submission:

#include <bits/stdc++.h>
#include <math.h>
#include <time.h>
using namespace std;
typedef long long ll;
typedef long double ld;
#define rep(i, n) for (int i = 0; i < (int)(n); i++)
const ll mod = 1000000007;
const ll INF = 1001001001;
const ll LINF = 1001001001001001001;

void prvec(vector<bool> vec) {
  ll n = vec.size();
  rep(i, n) cout << i << " " << vec.at(i) << "\\n";
}

void pr2d(vector<vector<ll>> vvec) {
  ll h = vvec.size();
  ll w = vvec.at(0).size();
  rep(i, h) {
    rep(j, w) { cout << vvec.at(i).at(j) << " "; }
    cout << "\\n";
  }
}

ll cancel_and_add(vector<vector<ll>> &contlis, vector<ll> &cont_order,
                  vector<vector<ll>> &s, vector<ll> &c, ll date, ll add_con) {
  ll diff = 0; // 変更によってsatisがどれだけ変わるか

  ll cur_cont_d =
      cont_order.at(date); // 現在date日に開催されているコンテストの種類
  diff -=
      s.at(date).at(cur_cont_d); // cur_cont_dの開催をやめることによる直接の影響
  diff +=
      s.at(date).at(add_con); // add_conコンテストの分のsatisを増やす直接の影響

  // cur_cont_d開催中止による飽きの影響
  auto it = lower_bound(contlis.at(cur_cont_d).begin(),
                        contlis.at(cur_cont_d).end(), date + 1);
  ll x = it - contlis.at(cur_cont_d).begin();
  ll a = date + 1 - contlis.at(cur_cont_d).at(x - 1) - 1;
  ll b = contlis.at(cur_cont_d).at(x + 1) - (date + 1) - 1;
  ll z =
      contlis.at(cur_cont_d).at(x + 1) - contlis.at(cur_cont_d).at(x - 1) - 1;

  diff = diff - c.at(cur_cont_d) * z * (z + 1) / 2 +
         c.at(cur_cont_d) * a * (a + 1) / 2 +
         c.at(cur_cont_d) * b * (b + 1) / 2;

  // q追加による飽きへの影響
  auto it2 = lower_bound(contlis.at(add_con).begin(), contlis.at(add_con).end(),
                         date + 1);
  x = it2 - contlis.at(add_con).begin();
  a = (date + 1) - contlis.at(add_con).at(x - 1) - 1;
  b = contlis.at(add_con).at(x) - (date + 1) - 1;
  z = contlis.at(add_con).at(x) - contlis.at(add_con).at(x - 1) - 1;
  diff += c.at(add_con) * z * (z + 1) / 2 - c.at(add_con) * a * (a + 1) / 2 -
          c.at(add_con) * b * (b + 1) / 2;
  return diff;
}

int main() {
  clock_t start = clock();

  ll days;
  cin >> days;
  vector<ll> c(26);
  rep(i, 26) cin >> c.at(i);
  vector<vector<ll>> s(days, vector<ll>(26));
  rep(i, days) rep(j, 26) cin >> s.at(i).at(j);
  vector<ll> last(26, 0);

  ll sat = 0;

  ll initial_satis = 0;
  rep(i, 26) { initial_satis -= c.at(i) * days * (days + 1) / 2; }
  // initial_satis =　何もコンテストを開催していない状態の満足度

  ll satis = initial_satis;
  vector<vector<ll>> contlis(26, {0, days + 1});
  vector<ll> cont_order(days);

  while (true) { // ある程度ランダムに生成してたまたま得点が良い組み合わせを探す
    clock_t now = clock();
    const double x = static_cast<double>(now - start) / CLOCKS_PER_SEC;
    if (x > 0.5)
      break;

    ll satis_candidate = initial_satis;

    // ランダムに生成して得点の良い解を探す
    srand(time(NULL));
    vector<ll> rand_init(days);
    rep(i, days) rand_init.at(i) = (rand() % 26);

    // 与えられたtだけコンテストを開催することを考える
    vector<vector<ll>> contlis_candidate(26, {0, days + 1});
    for (int i = 1; i <= days; i++) {
      ll t = rand_init.at(i - 1);
      auto it = lower_bound(contlis_candidate.at(t).begin(),
                            contlis_candidate.at(t).end(), i);
      ll x = it - contlis_candidate.at(t).begin();
      ll a = i - contlis_candidate.at(t).at(x - 1) - 1;
      ll b = contlis_candidate.at(t).at(x) - i - 1;
      ll z =
          contlis_candidate.at(t).at(x) - contlis_candidate.at(t).at(x - 1) - 1;
      satis_candidate += c.at(t) * z * (z + 1) / 2 - c.at(t) * a * (a + 1) / 2 -
                         c.at(t) * b * (b + 1) / 2;
      satis_candidate += s.at(i - 1).at(t);
      contlis_candidate.at(t).insert(it, i);
    }
    if (satis_candidate > satis) {
      satis = satis_candidate;
      cont_order = rand_init;
      contlis = contlis_candidate;
    }
  }

  while (true) {
    clock_t now = clock();
    const double time = static_cast<double>(now - start) / CLOCKS_PER_SEC;
    if (time > 1.950)
      break;

    ll d = rand() % days,
       q = rand() %
           26; // 最適化その1:ランダムにdとqを選び、d日目の開催コンテストをq番目のものにする

    if (cancel_and_add(contlis, cont_order, s, c, d, q) >
        0) { // 採用する場合、様々変える
      satis += cancel_and_add(contlis, cont_order, s, c, d, q) > 0;

      { // d日目の開催コンテストをqに変更する
        ll cur_cont_d = cont_order.at(d);
        cont_order.at(d) = q;
        auto erasecon = lower_bound(contlis.at(cur_cont_d).begin(),
                                    contlis.at(cur_cont_d).end(), d + 1);
        contlis.at(cur_cont_d).erase(erasecon);
        auto addcon =
            lower_bound(contlis.at(q).begin(), contlis.at(q).end(), d + 1);
        contlis.at(q).insert(addcon, d + 1);
      }
    }

    // 最適化その2:a日目のコンテストとb日目のコンテストを入れ替える
    ll a = rand() % days, b = a + ((rand() % 33) - 16); // 入れ替える日にちの選択

    // 現状a,b日目に開催されているコンテストは？
    ll cur_cont_a = cont_order.at(a), cur_cont_b = cont_order.at(b);
    ll exchange_diff =
        cancel_and_add(contlis, cont_order, s, c, a, cur_cont_b) +
        cancel_and_add(contlis, cont_order, s, c, b, cur_cont_a);

    if (exchange_diff > 0) { // 変化が0以上なら採用
      cont_order.at(a) = cur_cont_b;
      cont_order.at(b) = cur_cont_a;

      auto erasecon = lower_bound(contlis.at(cur_cont_a).begin(),
                                  contlis.at(cur_cont_a).end(), a + 1);
      contlis.at(cur_cont_a).erase(erasecon);
      auto addcon = lower_bound(contlis.at(cur_cont_b).begin(),
                                contlis.at(cur_cont_b).end(), a + 1);
      contlis.at(cur_cont_b).insert(addcon, a + 1);

      erasecon = lower_bound(contlis.at(cur_cont_b).begin(),
                             contlis.at(cur_cont_b).end(), b + 1);
      contlis.at(cur_cont_b).erase(erasecon);
      addcon = lower_bound(contlis.at(cur_cont_a).begin(),
                           contlis.at(cur_cont_a).end(), b + 1);
      contlis.at(cur_cont_a).insert(addcon, b + 1);
    }
  }

  rep(i, days) {
    cout << cont_order.at(i) + 1;
    if (i != (days - 1))
      cout << "\\n";
  }

  return 0;
}