Problem p02618 (C++)

Buggy submission (status: Runtime Error):
#include <bits/stdc++.h>
using namespace std;
mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());

#define pb push_back

using VI = vector<int>;
using ll = long long;

const ll inf = 0x3f3f3f3f3f3f3f3f;
const int MXT = 26;
const int MXD = 365;

int D;
int C[MXT + 10], S[MXD + 10][MXT + 10];

VI best;
ll best_score;

namespace MyChecker {
int last[MXT + 10];
ll calc_score(VI ans = best) {
  fill_n(last + 1, MXT, 0);
  if (ans.size() != D) {
    puts("Wrong Answer");
    assert(0);
  }
  int d = 0;
  ll score = 0;
  for (auto x : ans) {
    ++d;
    score += S[d][x];
    last[x] = d;
    for (int i = 1; i <= MXT; i++)
      score -= 1ll * C[i] * (d - last[i]);
  }
  return max(0ll, score + 1000000);
}
} // namespace MyChecker

void update_ans(VI &current, ll new_score = -inf) {
  if (new_score == -inf)
    new_score = MyChecker::calc_score(current);
  if (best.empty() || best_score < new_score) {
    best_score = new_score;
    best = current;
  }
  return;
}

void input_and_init() {
  scanf("%d", &D);
  for (int i = 1; i <= MXT; i++)
    scanf("%d", &C[i]);
  for (int i = 1; i <= D; i++) {
    for (int j = 1; j <= MXT; j++)
      scanf("%d", &S[i][j]);
  }
  best.clear();
  return;
}
void output() {
  for (auto x : best)
    printf("%d\n", x);
}

namespace Greedy {
int last[MXT + 10];
ll greedy(double param) {
  fill_n(last, MXT + 1, 0);
  ll delta[MXT + 1] = {0};
  VI greedy_ans;
  ll score = 0;
  for (int i = 1; i <= D; i++) {
    for (int j = 1; j <= MXT; j++)
      delta[j] += C[j];
    ll sum = accumulate(delta + 1, delta + MXT + 1, 0ll);
    double mx = -2e18;
    int ansd = -1;
    for (int j = 1; j <= MXT; j++) {
      double val = param * delta[j] + S[i][j];
      if (mx < val)
        mx = val, ansd = j;
    }
    score += S[i][ansd] + delta[ansd] - sum;
    delta[ansd] = 0;
    last[ansd] = i;
    greedy_ans.pb(ansd);
  }
  update_ans(greedy_ans, max(score + 1000000, 0ll));
  return score;
}
void greedy_solve() {
  for (double x = 1; x <= 10; x += 1)
    greedy(x);
}
} // namespace Greedy
namespace Update1 {
VI days[MXT + 1];
VI plan;
ll score;

VI random_days, cur, best;
ll mx = -inf;
void erase(int d, int type) {
  auto it = lower_bound(days[type].begin(), days[type].end(), d);
  score -= (*it - *prev(it)) * (*next(it) - *it) * C[type];
  score -= S[d][type];
  days[type].erase(it);
  plan[d - 1] = 0;
}
void add(int d, int type) {
  auto it = lower_bound(days[type].begin(), days[type].end(), d);
  score += (d - *prev(it)) * (*it - d) * C[type];
  score += S[d][type];
  days[type].insert(it, d);
  plan[d - 1] = type;
}
void dfs(int x) {
  if (x == random_days.size()) {
    if (mx < score)
      mx = score, best = cur;
    return;
  }
  for (int i = 1; i <= MXT; i++) {
    cur[x] = i;
    add(random_days[x], i);
    dfs(x + 1);
    erase(random_days[x], i);
  }
  return;
}

void update1(VI &_plan) {
  int d = 0;
  plan = _plan;
  score = MyChecker::calc_score();
  for (int i = 1; i <= MXT; i++)
    days[i] = {0};
  for (auto x : plan)
    days[x].pb(++d);
  for (int i = 1; i <= MXT; i++)
    days[i].pb(D + 1);

  for (int step = 0; step < 10000; step++) {
    ll prv = score;
    random_days.clear();
    while (random_days.size() < 2) {
      int d = rng() % 365 + 1;
      random_days.pb(d);
    }

    sort(random_days.begin(), random_days.end());
    random_days.erase(unique(random_days.begin(), random_days.end()),
                      random_days.end());

    for (auto x : random_days)
      erase(x, plan[x - 1]);
    cur.resize(random_days.size());

    mx = -inf;
    dfs(0);
    for (int i = 0; i < random_days.size(); i++)
      add(random_days[i], best[i]);
    assert(score == mx);
  }

  update_ans(plan, score);
}
} // namespace Update1

namespace Update2 {
VI plan, days[MXT + 1];

ll dp[MXD + 10][MXD + 10];
int prv[MXD + 10][MXD + 10];
void update_solve(int x, int y) {
  VI dd;
  dd.pb(0);
  for (auto y : days[x])
    dd.pb(y);
  for (auto x : days[y])
    dd.pb(x);
  sort(dd.begin(), dd.end());

  ll pscore = 0;
  int prvp = 0;
  for (auto y : days[x])
    pscore += (y - max(prvp, 1)) * C[x] * prvp + S[y][x], prvp = y;
  pscore += (D + 1 - prvp) * C[x] * prvp;
  prvp = 0;
  for (auto x : days[y])
    pscore += (x - max(prvp, 1)) * C[y] * prvp + S[x][y], prvp = x;
  pscore += (D + 1 - prvp) * C[y] * prvp;

  int sz = dd.size() - 1;
  for (int i = 0; i <= sz; i++)
    fill(dp[i], dp[i] + sz + 1, -1);
  dp[0][0] = 0;
  for (int i = 1; i <= sz; i++) {
    ll tmp;
    for (int j = 0; j < i; j++) {
      if (dp[j][i - 1] >= 0) {
        tmp =
            dp[j][i - 1] + S[dd[i]][y] + C[y] * (dd[i] - dd[i - 1]) * dd[i - 1];
        if (dp[j][i] < tmp)
          dp[j][i] = tmp, prv[j][i] = (j << 10) | (i - 1);
        tmp = dp[j][i - 1] + S[dd[i]][x] + C[x] * (dd[i] - dd[j]) * dd[j];
        if (dp[i][i - 1] < tmp)
          dp[i][i - 1] = tmp, prv[i][i - 1] = (j << 10) | (i - 1);
      }
      if (dp[i - 1][j] >= 0) {
        tmp =
            dp[i - 1][j] + S[dd[i]][x] + C[x] * (dd[i] - dd[i - 1]) * dd[i - 1];
        if (dp[i][j] < tmp)
          dp[i][j] = tmp, prv[i][j] = (i - 1 << 10) | j;
        tmp = dp[i - 1][j] + S[dd[i]][y] + C[y] * (dd[i] - dd[j]) * dd[j];
        if (dp[i - 1][i] < tmp)
          dp[i - 1][i] = tmp, prv[i - 1][i] = (i - 1 << 10) | j;
      }
    }
  }
  ll mx = -1;
  int ex = -1, ey = -1;
  for (int i = 0; i < sz; i++) {
    ll tmp;
    tmp = dp[i][sz] + (D + 1 - dd[i]) * C[x] * dd[i] +
          (D + 1 - dd[sz]) * C[y] * dd[sz];
    if (mx < tmp)
      mx = tmp, ex = i, ey = sz;
    tmp = dp[sz][i] + (D + 1 - dd[sz]) * C[x] * dd[sz] +
          (D + 1 - dd[i]) * C[y] * dd[i];
    if (mx < tmp)
      mx = tmp, ex = sz, ey = i;
  }
  days[x].clear(), days[y].clear();
  if (ex)
    days[x].pb(dd[ex]);
  if (ey)
    days[y].pb(dd[ey]);
  while (ex > 0 || ey > 0) {
    int px = prv[ex][ey] >> 10, py = prv[ex][ey] & 1023;
    if (px != ex) {
      ex = px;
      if (ex)
        days[x].pb(dd[ex]);
    }
    if (py != ey) {
      ey = py;
      if (ey)
        days[y].pb(dd[ey]);
    }
  }

  reverse(days[x].begin(), days[x].end());
  reverse(days[y].begin(), days[y].end());
  assert(mx >= pscore);
  return;
}

void update2(VI &_plan) {
  plan = _plan;
  int d = 0;
  for (auto x : plan)
    days[x].pb(++d);
  for (int step = 0; step < 10000; step++) {
    int x = rng() % 26 + 1, y = rng() % 26 + 1;
    if (x == y) {
      step--;
      continue;
    }
    update_solve(x, y);
  }
  for (int i = 1; i <= MXT; i++) {
    for (auto x : days[i])
      plan[x - 1] = i;
  }
  ll score = MyChecker::calc_score(plan);
  update_ans(plan, score);
}
} // namespace Update2

int main() {
  input_and_init();
  Greedy::greedy_solve();
  Update1::update1(best);
  Update2::update2(best);
  output();
  return 0;
}


Fixed submission:
#include <bits/stdc++.h>
using namespace std;
mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());

#define pb push_back

using VI = vector<int>;
using ll = long long;

const ll inf = 0x3f3f3f3f3f3f3f3f;
const int MXT = 26;
const int MXD = 365;

int D;
int C[MXT + 10], S[MXD + 10][MXT + 10];

VI best;
ll best_score;

namespace MyChecker {
int last[MXT + 10];
ll calc_score(VI ans = best) {
  fill_n(last + 1, MXT, 0);
  if (ans.size() != D) {
    puts("Wrong Answer");
    assert(0);
  }
  int d = 0;
  ll score = 0;
  for (auto x : ans) {
    ++d;
    score += S[d][x];
    last[x] = d;
    for (int i = 1; i <= MXT; i++)
      score -= 1ll * C[i] * (d - last[i]);
  }
  return max(0ll, score + 1000000);
}
} // namespace MyChecker

void update_ans(VI &current, ll new_score = -inf) {
  if (new_score == -inf)
    new_score = MyChecker::calc_score(current);
  if (best.empty() || best_score < new_score) {
    best_score = new_score;
    best = current;
  }
  return;
}

void input_and_init() {
  scanf("%d", &D);
  for (int i = 1; i <= MXT; i++)
    scanf("%d", &C[i]);
  for (int i = 1; i <= D; i++) {
    for (int j = 1; j <= MXT; j++)
      scanf("%d", &S[i][j]);
  }
  best.clear();
  return;
}
void output() {
  for (auto x : best)
    printf("%d\n", x);
}

namespace Greedy {
int last[MXT + 10];
ll greedy(double param) {
  fill_n(last, MXT + 1, 0);
  ll delta[MXT + 1] = {0};
  VI greedy_ans;
  ll score = 0;
  for (int i = 1; i <= D; i++) {
    for (int j = 1; j <= MXT; j++)
      delta[j] += C[j];
    ll sum = accumulate(delta + 1, delta + MXT + 1, 0ll);
    double mx = -2e18;
    int ansd = -1;
    for (int j = 1; j <= MXT; j++) {
      double val = param * delta[j] + S[i][j];
      if (mx < val)
        mx = val, ansd = j;
    }
    score += S[i][ansd] + delta[ansd] - sum;
    delta[ansd] = 0;
    last[ansd] = i;
    greedy_ans.pb(ansd);
  }
  update_ans(greedy_ans, max(score + 1000000, 0ll));
  return score;
}
void greedy_solve() {
  for (double x = 1; x <= 10; x += 1)
    greedy(x);
}
} // namespace Greedy
namespace Update1 {
VI days[MXT + 1];
VI plan;
ll score;

VI random_days, cur, best;
ll mx = -inf;
void erase(int d, int type) {
  auto it = lower_bound(days[type].begin(), days[type].end(), d);
  score -= (*it - *prev(it)) * (*next(it) - *it) * C[type];
  score -= S[d][type];
  days[type].erase(it);
  plan[d - 1] = 0;
}
void add(int d, int type) {
  auto it = lower_bound(days[type].begin(), days[type].end(), d);
  score += (d - *prev(it)) * (*it - d) * C[type];
  score += S[d][type];
  days[type].insert(it, d);
  plan[d - 1] = type;
}
void dfs(int x) {
  if (x == random_days.size()) {
    if (mx < score)
      mx = score, best = cur;
    return;
  }
  for (int i = 1; i <= MXT; i++) {
    cur[x] = i;
    add(random_days[x], i);
    dfs(x + 1);
    erase(random_days[x], i);
  }
  return;
}

void update1(VI &_plan) {
  int d = 0;
  plan = _plan;
  score = MyChecker::calc_score();
  for (int i = 1; i <= MXT; i++)
    days[i] = {0};
  for (auto x : plan)
    days[x].pb(++d);
  for (int i = 1; i <= MXT; i++)
    days[i].pb(D + 1);

  for (int step = 0; step < 10000; step++) {
    ll prv = score;
    random_days.clear();
    while (random_days.size() < 2) {
      int d = rng() % 365 + 1;
      random_days.pb(d);
    }

    sort(random_days.begin(), random_days.end());
    random_days.erase(unique(random_days.begin(), random_days.end()),
                      random_days.end());

    for (auto x : random_days)
      erase(x, plan[x - 1]);
    cur.resize(random_days.size());

    mx = -inf;
    dfs(0);
    for (int i = 0; i < random_days.size(); i++)
      add(random_days[i], best[i]);
    assert(score == mx);
  }

  update_ans(plan, score);
}
} // namespace Update1

namespace Update2 {
VI plan, days[MXT + 1];

ll dp[MXD + 10][MXD + 10];
int prv[MXD + 10][MXD + 10];
void update_solve(int x, int y) {
  if (days[x].empty() && days[y].empty())
    return;
  VI dd;
  dd.pb(0);
  for (auto y : days[x])
    dd.pb(y);
  for (auto x : days[y])
    dd.pb(x);
  sort(dd.begin(), dd.end());

  ll pscore = 0;
  int prvp = 0;
  for (auto y : days[x])
    pscore += (y - max(prvp, 1)) * C[x] * prvp + S[y][x], prvp = y;
  pscore += (D + 1 - prvp) * C[x] * prvp;
  prvp = 0;
  for (auto x : days[y])
    pscore += (x - max(prvp, 1)) * C[y] * prvp + S[x][y], prvp = x;
  pscore += (D + 1 - prvp) * C[y] * prvp;

  int sz = dd.size() - 1;
  for (int i = 0; i <= sz; i++)
    fill(dp[i], dp[i] + sz + 1, -1);
  dp[0][0] = 0;
  for (int i = 1; i <= sz; i++) {
    ll tmp;
    for (int j = 0; j < i; j++) {
      if (dp[j][i - 1] >= 0) {
        tmp =
            dp[j][i - 1] + S[dd[i]][y] + C[y] * (dd[i] - dd[i - 1]) * dd[i - 1];
        if (dp[j][i] < tmp)
          dp[j][i] = tmp, prv[j][i] = (j << 10) | (i - 1);
        tmp = dp[j][i - 1] + S[dd[i]][x] + C[x] * (dd[i] - dd[j]) * dd[j];
        if (dp[i][i - 1] < tmp)
          dp[i][i - 1] = tmp, prv[i][i - 1] = (j << 10) | (i - 1);
      }
      if (dp[i - 1][j] >= 0) {
        tmp =
            dp[i - 1][j] + S[dd[i]][x] + C[x] * (dd[i] - dd[i - 1]) * dd[i - 1];
        if (dp[i][j] < tmp)
          dp[i][j] = tmp, prv[i][j] = (i - 1 << 10) | j;
        tmp = dp[i - 1][j] + S[dd[i]][y] + C[y] * (dd[i] - dd[j]) * dd[j];
        if (dp[i - 1][i] < tmp)
          dp[i - 1][i] = tmp, prv[i - 1][i] = (i - 1 << 10) | j;
      }
    }
  }
  ll mx = -1;
  int ex = -1, ey = -1;
  for (int i = 0; i < sz; i++) {
    ll tmp;
    tmp = dp[i][sz] + (D + 1 - dd[i]) * C[x] * dd[i] +
          (D + 1 - dd[sz]) * C[y] * dd[sz];
    if (mx < tmp)
      mx = tmp, ex = i, ey = sz;
    tmp = dp[sz][i] + (D + 1 - dd[sz]) * C[x] * dd[sz] +
          (D + 1 - dd[i]) * C[y] * dd[i];
    if (mx < tmp)
      mx = tmp, ex = sz, ey = i;
  }
  days[x].clear(), days[y].clear();
  if (ex)
    days[x].pb(dd[ex]);
  if (ey)
    days[y].pb(dd[ey]);
  while (ex > 0 || ey > 0) {
    int px = prv[ex][ey] >> 10, py = prv[ex][ey] & 1023;
    if (px != ex) {
      ex = px;
      if (ex)
        days[x].pb(dd[ex]);
    }
    if (py != ey) {
      ey = py;
      if (ey)
        days[y].pb(dd[ey]);
    }
  }

  reverse(days[x].begin(), days[x].end());
  reverse(days[y].begin(), days[y].end());
  assert(mx >= pscore);
  return;
}

void update2(VI &_plan) {
  plan = _plan;
  int d = 0;
  for (auto x : plan)
    days[x].pb(++d);
  for (int step = 0; step < 10000; step++) {
    int x = rng() % 26 + 1, y = rng() % 26 + 1;
    if (x == y) {
      step--;
      continue;
    }
    update_solve(x, y);
  }
  for (int i = 1; i <= MXT; i++) {
    for (auto x : days[i])
      plan[x - 1] = i;
  }
  ll score = MyChecker::calc_score(plan);
  update_ans(plan, score);
}
} // namespace Update2

int main() {
  input_and_init();
  Greedy::greedy_solve();
  Update1::update1(best);
  Update2::update2(best);
  output();
  return 0;
}