Problem p02618 (C++) — buggy submission, verdict: Time Limit Exceeded

#include <bits/stdc++.h>
#define rep(i, n) for (int i = 0; i < (n); i++)
using namespace std;
typedef long long ll;
typedef pair<int, int> P;

const int D = 365;
int csum;
int c[26];
int s[D][26];
int last[26];

set<int> se[26];

int ans[D];

int cur_score;

int score() {
  memset(last, -1, sizeof(last));
  int sum = 0;
  int diff = 0;
  rep(i, D) {
    sum += s[i][ans[i]];
    diff += csum;
    diff -= (i - last[ans[i]]) * c[ans[i]];
    sum -= diff;
    last[ans[i]] = i;
  }
  cur_score = sum;
  return sum;
}

inline int SUM(int b, int n) { return (b * (n - 1)) * n / 2; }
int update(int pos, int d) {
  int x = ans[pos];
  auto it = se[x].find(pos);
  int diff = 0;
  diff -= s[pos][x];
  diff += s[pos][d];

  int prv = *prev(it), nx = *next(it);
  diff += SUM(c[x], pos - prv);
  diff += SUM(c[x], nx - pos);
  diff -= SUM(c[x], nx - prv);

  it = se[d].lower_bound(pos);
  prv = *prev(it), nx = *it;
  diff += SUM(c[d], nx - prv);
  diff -= SUM(c[d], pos - prv);
  diff -= SUM(c[d], nx - pos);

  cur_score += diff;
  return cur_score;
}

int main() {
  rep(i, 26) {
    se[i].insert(-1);
    se[i].insert(D);
  }
  scanf("%*d");
  rep(i, 26) scanf("%d", &c[i]), csum += c[i];
  rep(i, D) rep(j, 26) scanf("%d", &s[i][j]);
  rep(i, D) {
    ans[i] = max_element(s[i], s[i] + 26) - s[i];
    se[ans[i]].insert(i);
  }
  random_device rnd;
  mt19937 mt(rnd());
  uniform_real_distribution<double> Real(0, 1);
  int Max = score();
  double stmp = 10000, etmp = 0;
  int upd = 0;
  int LOOP = 8000000;
  rep(loop, LOOP) {
    int pos = mt() % D;
    int sum = 0;
    rep(i, 26) sum += s[pos][i];
    int ch, d = -1;
    do {
      ch = mt() % sum;
      rep(i, 26) {
        ch -= s[pos][i];
        if (ch < 0) {
          d = i;
          break;
        }
      }
    } while (d == ans[pos]);
    int old = ans[pos], old_score = cur_score;
    int nx = update(pos, d);
    double tmp = stmp + (etmp - stmp) / LOOP * loop;
    double p = exp(-double(abs(Max - nx)) / tmp);
    if (Max < nx || Real(mt) < p) {
      se[old].erase(pos);
      se[d].insert(pos);
      ans[pos] = d;
      Max = nx;
      upd++;
    } else {
      cur_score = old_score;
    }
  }
  cerr << upd << endl;
  rep(i, D) { cout << ans[i] + 1 << endl; }
  cerr << "score: " << Max << ' ' << score() << endl;
}

Error: TLE

Fixed submission:

#include <bits/stdc++.h>
#define rep(i, n) for (int i = 0; i < (n); i++)
using namespace std;
typedef long long ll;
typedef pair<int, int> P;

const int D = 365;
int csum;
int c[26];
int s[D][26];
int last[26];

set<int> se[26];

int ans[D];

int cur_score;

int score() {
  memset(last, -1, sizeof(last));
  int sum = 0;
  int diff = 0;
  rep(i, D) {
    sum += s[i][ans[i]];
    diff += csum;
    diff -= (i - last[ans[i]]) * c[ans[i]];
    sum -= diff;
    last[ans[i]] = i;
  }
  cur_score = sum;
  return sum;
}

inline int SUM(int b, int n) { return (b * (n - 1)) * n / 2; }
int update(int pos, int d) {
  int x = ans[pos];
  auto it = se[x].find(pos);
  int diff = 0;
  diff -= s[pos][x];
  diff += s[pos][d];

  int prv = *prev(it), nx = *next(it);
  diff += SUM(c[x], pos - prv);
  diff += SUM(c[x], nx - pos);
  diff -= SUM(c[x], nx - prv);

  it = se[d].lower_bound(pos);
  prv = *prev(it), nx = *it;
  diff += SUM(c[d], nx - prv);
  diff -= SUM(c[d], pos - prv);
  diff -= SUM(c[d], nx - pos);

  cur_score += diff;
  return cur_score;
}

int main() {
  rep(i, 26) {
    se[i].insert(-1);
    se[i].insert(D);
  }
  scanf("%*d");
  rep(i, 26) scanf("%d", &c[i]), csum += c[i];
  rep(i, D) rep(j, 26) scanf("%d", &s[i][j]);
  rep(i, D) {
    ans[i] = max_element(s[i], s[i] + 26) - s[i];
    se[ans[i]].insert(i);
  }
  random_device rnd;
  mt19937 mt(rnd());
  uniform_real_distribution<double> Real(0, 1);
  int Max = score();
  double stmp = 10000, etmp = 0;
  int upd = 0;
  int LOOP = 10000000;
  rep(loop, LOOP) {
    int pos = mt() % D;
    int sum = 0;
    rep(i, 26) sum += s[pos][i];
    int ch, d = -1;
    do {
      ch = mt() % sum;
      rep(i, 26) {
        ch -= s[pos][i];
        if (ch < 0) {
          d = i;
          break;
        }
      }
    } while (d == ans[pos]);
    int old = ans[pos], old_score = cur_score;
    int nx = update(pos, d);
    double tmp = stmp + (etmp - stmp) / LOOP * loop;
    double p = exp(-double(abs(Max - nx)) / tmp);
    if (Max < nx || Real(mt) < p) {
      se[old].erase(pos);
      se[d].insert(pos);
      ans[pos] = d;
      Max = nx;
      upd++;
    } else {
      cur_score = old_score;
    }
  }
  cerr << upd << endl;
  rep(i, D) { cout << ans[i] + 1 << endl; }
  cerr << "score: " << Max << ' ' << score() << endl;
}