Problem p02618 (C++)

Buggy submission (status: Runtime Error):
#include <bits/stdc++.h>
using namespace std;

typedef long long ll;
typedef pair<int, int> P;
typedef pair<int, P> P1;
typedef pair<P, P> P2;
typedef vector<int> vi;
typedef pair<int, int> pi;
typedef vector<pi> vpi;
typedef vector<vi> vvi;
#define pu push
#define pb push_back
#define mp make_pair
#define eps 1e-7
#define INF 1000000000
#define fi first
#define sc second
#define rep(i, x) for (long long i = 0; i < x; i++)
#define repn(i, x) for (long long i = 1; i <= x; i++)
#define SORT(x) sort(x.begin(), x.end())
#define ERASE(x) x.erase(unique(x.begin(), x.end()), x.end())
#define POSL(x, v) (lower_bound(x.begin(), x.end(), v) - x.begin())
#define POSU(x, v) (upper_bound(x.begin(), x.end(), v) - x.begin())
#define rrep(i, n) for (int i = ((int)(n)-1); i >= 0; --i)
#define rrepn(i, n) for (int i = ((int)(n)); i > 0; --i)
#define SZ(x) ((int)(x).size())
template <class T> bool chmax(T &a, const T &b) {
  if (a < b) {
    a = b;
    return 1;
  }
  return 0;
}
template <class T> bool chmin(T &a, const T &b) {
  if (b < a) {
    a = b;
    return 1;
  }
  return 0;
}
vector<pair<string, P>> vec;
// vector<vector<int>> data(3, vector<int>(4));

inline unsigned long long rdtsc() {
#ifdef __amd64
  unsigned long long a, d;
  __asm__ volatile("rdtsc" : "=a"(a), "=d"(d));
  return (d << 32) | a;
#else
  unsigned long long x;
  __asm__ volatile("rdtsc" : "=A"(x));
  return x;
#endif
}

inline double gettime() { return rdtsc() / 2993344000.0; }
inline double elapsed(double st) { return gettime() - st; }
class Xorshift128 {
private:
  static constexpr unsigned MASK = 0x7FFFFFFF;
  unsigned x = 123456789, y = 987654321, z = 1000000007, w;

public:
  unsigned rnd() {
    unsigned t = x ^ (x << 11);
    x = y;
    y = z;
    z = w;
    w = (w ^ (w >> 19)) ^ (t ^ (t >> 8));
    return w & MASK;
  }
  inline double rnd_d() { return (double)rnd() / INT32_MAX; }

  Xorshift128(const unsigned seed = 0) : w(seed) {}
};
Xorshift128 prng(21);

int D;
vi c(26);
vvi s(365, vi(26));

int compute_score(const vi &out) {
  vector<int> last(26);
  int score = 0;
  rep(i, out.size()) {
    score += s[i][out[i]];
    last[out[i]] = i + 1;
    int m = 0;
    rep(j, 26) { m += c[j] * (i + 1 - last[j]); }
    score -= m;
    // cout << score << endl;
  }
  return score;
}

int evaluate(const vi &out, int k) {
  vector<int> last(26);
  int score = 0;
  rep(i, out.size()) {
    score += s[i][out[i]];
    last[out[i]] = i + 1;
    int m = 0;
    rep(j, 26) { m += c[j] * (i + 1 - last[j]); }
    score -= m;
    // cout << score << endl;
  }

  int n = min(k, D - (int)out.size());
  rep(i, 26) {
    int a = (int)out.size() + 1 - last[i];
    score -= (a + (a + n - 1)) * n / 2 * c[i];
  }

  return score;
}

int cost(int a, int b) {
  int d = b - a;
  return d * (d - 1) / 2;
}

struct State {
  vi out;
  int score;
  vvi ds;

  State(const vector<int> t) : out(t) {
    score = compute_score(out);

    vvi dsn(26, vi());
    rep(d, D) dsn[out[d]].push_back(d + 1);
    ds = dsn;
  }

  void change(int d, int i) {
    int old_i = out[d];

    int p = lower_bound(ds[old_i].begin(), ds[old_i].end(), d + 1) -
            ds[old_i].begin();
    int prev, next;
    if (p - 1 >= 0)
      prev = ds[old_i][p - 1];
    else
      prev = 0;
    if (p + 1 < ds[old_i].size())
      next = ds[old_i][p + 1];
    else
      next = D + 1;
    ds[old_i].erase(ds[old_i].begin() + p);
    score +=
        (cost(prev, d + 1) + cost(d + 1, next) - cost(prev, next)) * c[old_i];

    p = lower_bound(ds[i].begin(), ds[i].end(), d + 2) - ds[i].begin();
    if (p - 1 >= 0)
      prev = ds[i][p - 1];
    else
      prev = 0;
    if (p < ds[i].size())
      next = ds[i][p];
    else
      next = D + 1;
    ds[i].insert(ds[i].begin() + p, d + 1);
    score -= (cost(prev, d + 1) + cost(d + 1, next) - cost(prev, next)) * c[i];

    score += s[d][i] - s[d][old_i];

    out[d] = i;
  }
};

vi solve(int k) {
  vi t;
  rep(i, D) {
    int max_score = INT_MIN;
    int best_j = 0;
    rep(j, 26) {
      t.push_back(j);
      // TODO:
      // Stateで末尾追加できるようにして、最初から計算しなおさないようにする
      int score = evaluate(t, k);
      if (max_score < score) {
        max_score = score;
        best_j = j;
      }
      t.pop_back();
    }
    t.push_back(best_j);
  }
  return t;
}

int main() {
  const double TL = 2;
  double st = gettime();

  cin >> D;
  rep(i, 26) cin >> c[i];
  rep(i, D) rep(j, 26) cin >> s[i][j];

  int max_score = INT_MIN;
  vi t;
  rep(k, 26) {
    vi now_t = solve(k);
    // TODO: stateを利用して、計算しなくてもいいようにする
    int score = compute_score(now_t);
    if (max_score < score) {
      max_score = score;
      t = now_t;
    }
  }
  State state = State(t);

  while (true) {
    double time = elapsed(st) / TL;
    if (time > 0.99)
      break;

    if (prng.rnd() % 2 == 0) {
      int d = prng.rnd() % D, q = prng.rnd() % 26;
      int old_contest = state.out[d];
      int old_score = state.score;
      state.change(d, q);
      if (old_score > state.score)
        state.change(d, old_contest);
    } else {
      int d1 = prng.rnd() % (D - 1);
      int d2 = min(D, d1 + (int)(prng.rnd() % 16) + 1);
      int old_score = state.score;
      // TODO: stateにswapを用意する
      int tmp = state.out[d1];
      state.change(d1, state.out[d2]);
      state.change(d2, tmp);
      if (old_score > state.score) {
        state.change(d2, state.out[d1]);
        state.change(d1, tmp);
      }
    }
  }

  rep(i, D) printf("%d\n", state.out[i] + 1);

  return 0;
}


Fixed submission:
#include <bits/stdc++.h>
using namespace std;

typedef long long ll;
typedef pair<int, int> P;
typedef pair<int, P> P1;
typedef pair<P, P> P2;
typedef vector<int> vi;
typedef pair<int, int> pi;
typedef vector<pi> vpi;
typedef vector<vi> vvi;
#define pu push
#define pb push_back
#define mp make_pair
#define eps 1e-7
#define INF 1000000000
#define fi first
#define sc second
#define rep(i, x) for (long long i = 0; i < x; i++)
#define repn(i, x) for (long long i = 1; i <= x; i++)
#define SORT(x) sort(x.begin(), x.end())
#define ERASE(x) x.erase(unique(x.begin(), x.end()), x.end())
#define POSL(x, v) (lower_bound(x.begin(), x.end(), v) - x.begin())
#define POSU(x, v) (upper_bound(x.begin(), x.end(), v) - x.begin())
#define rrep(i, n) for (int i = ((int)(n)-1); i >= 0; --i)
#define rrepn(i, n) for (int i = ((int)(n)); i > 0; --i)
#define SZ(x) ((int)(x).size())
template <class T> bool chmax(T &a, const T &b) {
  if (a < b) {
    a = b;
    return 1;
  }
  return 0;
}
template <class T> bool chmin(T &a, const T &b) {
  if (b < a) {
    a = b;
    return 1;
  }
  return 0;
}
vector<pair<string, P>> vec;
// vector<vector<int>> data(3, vector<int>(4));

inline unsigned long long rdtsc() {
#ifdef __amd64
  unsigned long long a, d;
  __asm__ volatile("rdtsc" : "=a"(a), "=d"(d));
  return (d << 32) | a;
#else
  unsigned long long x;
  __asm__ volatile("rdtsc" : "=A"(x));
  return x;
#endif
}

inline double gettime() { return rdtsc() / 2993344000.0; }
inline double elapsed(double st) { return gettime() - st; }
class Xorshift128 {
private:
  static constexpr unsigned MASK = 0x7FFFFFFF;
  unsigned x = 123456789, y = 987654321, z = 1000000007, w;

public:
  unsigned rnd() {
    unsigned t = x ^ (x << 11);
    x = y;
    y = z;
    z = w;
    w = (w ^ (w >> 19)) ^ (t ^ (t >> 8));
    return w & MASK;
  }
  inline double rnd_d() { return (double)rnd() / INT32_MAX; }

  Xorshift128(const unsigned seed = 0) : w(seed) {}
};
Xorshift128 prng(21);

int D;
vi c(26);
vvi s(365, vi(26));

int compute_score(const vi &out) {
  vector<int> last(26);
  int score = 0;
  rep(i, out.size()) {
    score += s[i][out[i]];
    last[out[i]] = i + 1;
    int m = 0;
    rep(j, 26) { m += c[j] * (i + 1 - last[j]); }
    score -= m;
    // cout << score << endl;
  }
  return score;
}

int evaluate(const vi &out, int k) {
  vector<int> last(26);
  int score = 0;
  rep(i, out.size()) {
    score += s[i][out[i]];
    last[out[i]] = i + 1;
    int m = 0;
    rep(j, 26) { m += c[j] * (i + 1 - last[j]); }
    score -= m;
    // cout << score << endl;
  }

  int n = min(k, D - (int)out.size());
  rep(i, 26) {
    int a = (int)out.size() + 1 - last[i];
    score -= (a + (a + n - 1)) * n / 2 * c[i];
  }

  return score;
}

int cost(int a, int b) {
  int d = b - a;
  return d * (d - 1) / 2;
}

struct State {
  vi out;
  int score;
  vvi ds;

  State(const vector<int> t) : out(t) {
    score = compute_score(out);

    vvi dsn(26, vi());
    rep(d, D) dsn[out[d]].push_back(d + 1);
    ds = dsn;
  }

  void change(int d, int i) {
    int old_i = out[d];

    int p = lower_bound(ds[old_i].begin(), ds[old_i].end(), d + 1) -
            ds[old_i].begin();
    int prev, next;
    if (p - 1 >= 0)
      prev = ds[old_i][p - 1];
    else
      prev = 0;
    if (p + 1 < ds[old_i].size())
      next = ds[old_i][p + 1];
    else
      next = D + 1;
    ds[old_i].erase(ds[old_i].begin() + p);
    score +=
        (cost(prev, d + 1) + cost(d + 1, next) - cost(prev, next)) * c[old_i];

    p = lower_bound(ds[i].begin(), ds[i].end(), d + 2) - ds[i].begin();
    if (p - 1 >= 0)
      prev = ds[i][p - 1];
    else
      prev = 0;
    if (p < ds[i].size())
      next = ds[i][p];
    else
      next = D + 1;
    ds[i].insert(ds[i].begin() + p, d + 1);
    score -= (cost(prev, d + 1) + cost(d + 1, next) - cost(prev, next)) * c[i];

    score += s[d][i] - s[d][old_i];

    out[d] = i;
  }
};

vi solve(int k) {
  vi t;
  rep(i, D) {
    int max_score = INT_MIN;
    int best_j = 0;
    rep(j, 26) {
      t.push_back(j);
      // TODO:
      // Stateで末尾追加できるようにして、最初から計算しなおさないようにする
      int score = evaluate(t, k);
      if (max_score < score) {
        max_score = score;
        best_j = j;
      }
      t.pop_back();
    }
    t.push_back(best_j);
  }
  return t;
}

int main() {
  const double TL = 2;
  double st = gettime();

  cin >> D;
  rep(i, 26) cin >> c[i];
  rep(i, D) rep(j, 26) cin >> s[i][j];

  int max_score = INT_MIN;
  vi t;
  rep(k, 26) {
    vi now_t = solve(k);
    // TODO: stateを利用して、計算しなくてもいいようにする
    int score = compute_score(now_t);
    if (max_score < score) {
      max_score = score;
      t = now_t;
    }
  }
  State state = State(t);

  while (true) {
    double time = elapsed(st) / TL;
    if (time > 0.99)
      break;

    if (prng.rnd() % 2 == 0) {
      int d = prng.rnd() % D, q = prng.rnd() % 26;
      int old_contest = state.out[d];
      int old_score = state.score;
      state.change(d, q);
      if (old_score > state.score)
        state.change(d, old_contest);
    } else {
      int d1 = prng.rnd() % (D - 1);
      int d2 = min(D - 1, d1 + (int)(prng.rnd() % 16) + 1);
      int old_score = state.score;
      // TODO: stateにswapを用意する
      int tmp = state.out[d1];
      state.change(d1, state.out[d2]);
      state.change(d2, tmp);
      if (old_score > state.score) {
        state.change(d2, state.out[d1]);
        state.change(d1, tmp);
      }
    }
  }

  rep(i, D) printf("%d\n", state.out[i] + 1);

  return 0;
}