Problem p02618 (C++)

Buggy submission (status: Time Limit Exceeded):
#include <algorithm>
#include <assert.h>
#include <bitset>
#include <complex>
#include <deque>
#include <functional>
#include <iomanip>
#include <iostream>
#include <map>
#include <math.h>
#include <numeric>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <vector>
using namespace std;
#define REP(i, m, n) for (int i = (int)(m); i < (int)(n); ++i)
#define rep(i, n) REP(i, 0, n)
using ll = long long;
constexpr int inf = 1e9 + 7;
constexpr ll longinf = 1LL << 60;
constexpr ll mod = 1e9 + 7;

const int N = 365, M = 26;
int c[26], s[365][26];
int res[365];

set<int> st[26];

int calc() {
  int ret = 0;
  vector<int> last(26, -1);
  rep(i, N) {
    ret += s[i][res[i]];
    last[res[i]] = i;
    rep(j, 26) ret -= c[j] * (i - last[j]);
  }
  return ret;
}
inline int f(int n) { return n * (n - 1) / 2; }

int erase(int i, int j) {
  auto itr = st[i].lower_bound(j);
  int nxt = *(next(itr)), prv = *(prev(itr));
  return -s[j][i] + c[i] * (f(j - prv) + f(nxt - j) - f(nxt - prv));
}
int insert(int i, int j) {
  auto itr = st[i].lower_bound(j);
  int nxt = *itr, prv = *(prev(itr));
  return s[j][i] + c[i] * (-f(j - prv) - f(nxt - j) + f(nxt - prv));
}

int up(int i, int j) {
  auto itr = st[i].lower_bound(j);
  int nxt = *(next(itr)), prv = *(prev(itr));
  return s[j + 1][i] - s[j][i] +
         c[i] * (f(j - prv) + f(nxt - j) - f(j + 1 - prv) - f(nxt - j - 1));
}

int down(int i, int j) {
  auto itr = st[i].lower_bound(j);
  int nxt = *(next(itr)), prv = *(prev(itr));
  return s[j - 1][i] - s[j][i] +
         c[i] * (f(j - prv) + f(nxt - j) - f(j - 1 - prv) - f(nxt - j + 1));
}
struct Xor128 {
  unsigned x, y, z, w;

  Xor128(unsigned w_ = 88675123)
      : x(123456789), y(362436069), z(521288629), w(w_){};

  inline unsigned xor128() {
    unsigned t;
    t = x ^ (x << 11);
    x = y;
    y = z;
    z = w;
    return w = (w ^ (w >> 19)) ^ (t ^ (t >> 8));
  }

  int nextInt(int x, int y) {
    if (x > y)
      swap(x, y);
    return xor128() % (y - x) + x;
  }

  double nextDouble(double a, double b) {
    return (double)(xor128() & 0xffff) / 0xffff * (b - a) + a;
  }
};

const int T = 14000000;
const double startT = 20000, endT = 0;
const double startT2 = 1000, endT2 = 0;
int main() {
  int _;
  cin >> _;
  rep(i, M) cin >> c[i];
  rep(i, N) rep(j, M) cin >> s[i][j];
  rep(i, M) st[i].insert(-1);
  rep(i, M) st[i].insert(N);
  auto rnd = Xor128();
  int sum = 0;
  rep(j, M) sum += c[j];
  rep(i, N) {
    int t = rnd.nextInt(0, sum);
    int j = 0, cs = 0;
    while (cs + c[j] < t) {
      cs += c[j++];
    }
    res[i] = j;
    st[res[i]].insert(i);
  }
  int cur = calc();
  cerr << cur << endl;
  rep(loop, T) {
    if (loop % 2 == 0) {
      int day = rnd.nextInt(0, N), con = rnd.nextInt(0, M);
      if (res[day] == con)
        continue;
      int diff = insert(con, day) + erase(res[day], day);
      double temp = startT + (endT - startT) * loop / T;
      double prob = exp((double)diff / temp);
      if (prob > rnd.nextDouble(0, 1) || diff > 0) {
        cur += diff;
        st[res[day]].erase(day);
        st[con].insert(day);
        res[day] = con;
      }
    } else {
      int day = rnd.nextInt(0, N - 1);
      if (res[day] == res[day + 1])
        continue;
      int diff = up(res[day], day) + down(res[day + 1], day + 1);
      double temp = startT2 + (endT2 - startT2) * loop / T;
      double prob = exp((double)diff / temp);
      if (prob > rnd.nextDouble(0, 1) || diff > 0) {
        cur += diff;
        st[res[day]].erase(day);
        st[res[day + 1]].erase(day + 1);
        swap(res[day], res[day + 1]);
        st[res[day]].insert(day);
        st[res[day + 1]].insert(day + 1);
      }
    }
  }
  rep(i, N) cout << res[i] + 1 << endl;
  cerr << cur << endl;
  return 0;
}

Fixed submission:
#include <algorithm>
#include <assert.h>
#include <bitset>
#include <complex>
#include <deque>
#include <functional>
#include <iomanip>
#include <iostream>
#include <map>
#include <math.h>
#include <numeric>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <vector>
using namespace std;
#define REP(i, m, n) for (int i = (int)(m); i < (int)(n); ++i)
#define rep(i, n) REP(i, 0, n)
using ll = long long;
constexpr int inf = 1e9 + 7;
constexpr ll longinf = 1LL << 60;
constexpr ll mod = 1e9 + 7;

const int N = 365, M = 26;
int c[26], s[365][26];
int res[365];

set<int> st[26];

int calc() {
  int ret = 0;
  vector<int> last(26, -1);
  rep(i, N) {
    ret += s[i][res[i]];
    last[res[i]] = i;
    rep(j, 26) ret -= c[j] * (i - last[j]);
  }
  return ret;
}
inline int f(int n) { return n * (n - 1) / 2; }

int erase(int i, int j) {
  auto itr = st[i].lower_bound(j);
  int nxt = *(next(itr)), prv = *(prev(itr));
  return -s[j][i] + c[i] * (f(j - prv) + f(nxt - j) - f(nxt - prv));
}
int insert(int i, int j) {
  auto itr = st[i].lower_bound(j);
  int nxt = *itr, prv = *(prev(itr));
  return s[j][i] + c[i] * (-f(j - prv) - f(nxt - j) + f(nxt - prv));
}

int up(int i, int j) {
  auto itr = st[i].lower_bound(j);
  int nxt = *(next(itr)), prv = *(prev(itr));
  return s[j + 1][i] - s[j][i] +
         c[i] * (f(j - prv) + f(nxt - j) - f(j + 1 - prv) - f(nxt - j - 1));
}

int down(int i, int j) {
  auto itr = st[i].lower_bound(j);
  int nxt = *(next(itr)), prv = *(prev(itr));
  return s[j - 1][i] - s[j][i] +
         c[i] * (f(j - prv) + f(nxt - j) - f(j - 1 - prv) - f(nxt - j + 1));
}
struct Xor128 {
  unsigned x, y, z, w;

  Xor128(unsigned w_ = 88675123)
      : x(123456789), y(362436069), z(521288629), w(w_){};

  inline unsigned xor128() {
    unsigned t;
    t = x ^ (x << 11);
    x = y;
    y = z;
    z = w;
    return w = (w ^ (w >> 19)) ^ (t ^ (t >> 8));
  }

  int nextInt(int x, int y) {
    if (x > y)
      swap(x, y);
    return xor128() % (y - x) + x;
  }

  double nextDouble(double a, double b) {
    return (double)(xor128() & 0xffff) / 0xffff * (b - a) + a;
  }
};

const int T = 10000000;
const double startT = 5000, endT = 100;
const double startT2 = 1000, endT2 = 20;
int main() {
  int _;
  cin >> _;
  rep(i, M) cin >> c[i];
  rep(i, N) rep(j, M) cin >> s[i][j];
  rep(i, M) st[i].insert(-1);
  rep(i, M) st[i].insert(N);
  auto rnd = Xor128();
  int sum = 0;
  rep(j, M) sum += c[j];
  rep(i, N) {
    int t = rnd.nextInt(0, sum);
    int j = 0, cs = 0;
    while (cs + c[j] < t) {
      cs += c[j++];
    }
    res[i] = j;
    st[res[i]].insert(i);
  }
  int cur = calc();
  cerr << cur << endl;
  rep(loop, T) {
    if (loop % 2 == 0) {
      int day = rnd.nextInt(0, N), con = rnd.nextInt(0, M);
      if (res[day] == con)
        continue;
      int diff = insert(con, day) + erase(res[day], day);
      double temp = startT + (endT - startT) * loop / T;
      double prob = exp((double)diff / temp);
      if (prob > rnd.nextDouble(0, 1) || diff > 0) {
        cur += diff;
        st[res[day]].erase(day);
        st[con].insert(day);
        res[day] = con;
      }
    } else {
      int day = rnd.nextInt(0, N - 1);
      if (res[day] == res[day + 1])
        continue;
      int diff = up(res[day], day) + down(res[day + 1], day + 1);
      double temp = startT2 + (endT2 - startT2) * loop / T;
      double prob = exp((double)diff / temp);
      if (prob > rnd.nextDouble(0, 1) || diff > 0) {
        cur += diff;
        st[res[day]].erase(day);
        st[res[day + 1]].erase(day + 1);
        swap(res[day], res[day + 1]);
        st[res[day]].insert(day);
        st[res[day + 1]].insert(day + 1);
      }
    }
  }
  rep(i, N) cout << res[i] + 1 << endl;
  cerr << cur << endl;
  return 0;
}