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

#pragma GCC optimize("O3")
// #pragma GCC target ("avx")
#include <algorithm>
#include <ctime>
#include <iostream>
#include <random>
#include <set>
#include <stdio.h>
#include <string.h>
#include <string>
#include <vector>

#ifdef LOCAL
#define eprintf(...) fprintf(stderr, __VA_ARGS__)
#else
#define NDEBUG
#define eprintf(...)                                                           \\
  do {                                                                         \\
  } while (0)
#endif
#include <cassert>

using namespace std;

typedef long long LL;
typedef vector<int> VI;

#define REP(i, n) for (int i = 0, i##_len = (n); i < i##_len; ++i)
#define EACH(i, c)                                                             \\
  for (__typeof((c).begin()) i = (c).begin(), i##_end = (c).end();             \\
       i != i##_end; ++i)

template <class T> inline void amin(T &x, const T &y) {
  if (y < x)
    x = y;
}
template <class T> inline void amax(T &x, const T &y) {
  if (x < y)
    x = y;
}
template <class Iter> void rprintf(const char *fmt, Iter begin, Iter end) {
  for (bool sp = 0; begin != end; ++begin) {
    if (sp)
      putchar(' ');
    else
      sp = true;
    printf(fmt, *begin);
  }
  putchar('\\n');
}

mt19937_64 engine(20200628);

int D;
int C[26];
int S[365][26];

int last[26];

int initial_score(int *T, VI *se) {
  int cur = 0;

  REP(c, 26) {
    last[c] = -1;
    se[c].push_back(-1);
  }

  REP(i, D) {
    int t = T[i];
    last[t] = i;
    se[t].push_back(i);

    cur += S[i][t];
    REP(c, 26) cur -= C[c] * (i - last[c]);
  }

  REP(c, 26) { se[c].push_back(D); }
  return cur;
}

int tri(int n) { return n * (n - 1) / 2; }

int modify_diff(int *T, VI *se, int d, int q) {
  int p = T[d];
  if (p == q)
    return 0;
  T[d] = q;

  int ret = 0;

  int pos = lower_bound(se[p].begin(), se[p].end(), d) - se[p].begin();
  int left = se[p][pos - 1], right = se[p][pos + 1];
  ret -= C[p] * (tri(right - left) - tri(d - left) - tri(right - d));
  ret -= S[d][p];
  se[p].erase(se[p].begin() + pos);

  pos = lower_bound(se[q].begin(), se[q].end(), d) - se[q].begin();
  left = se[q][pos - 1];
  right = se[q][pos];
  ret += C[q] * (tri(right - left) - tri(d - left) - tri(right - d));
  ret += S[d][q];
  se[q].insert(se[q].begin() + pos, d);

  return ret;
}

// int solve() {
//     const int LOOP = 100000;
//     REP (i, D) T[i] = engine() % 26;
//     int cur = initial_score();
//     REP ($, LOOP) {
// 	int day = engine() % D, type = engine() % 26;
// 	int old = T[day];
// 	int diff = modify_diff(day, type);
// 	if (diff >= 0) {
// 	    cur += diff;
// 	} else {
// 	    modify_diff(day, old);
// 	}
//     }
//     // eprintf("%d\\n", cur);
// }

struct State {
  int score;
  int T[365];
  VI se[26];

  State() {}

  void random_initialize() {
    REP(i, D) T[i] = engine() % 26;
    score = initial_score(T, se);
  }

  void next(int day, int type) {
    int old = T[day];
    int diff = modify_diff(T, se, day, type);
    score += diff;
  }

  //    void random_next() {
  //	int day = engine() % D, type = engine() % 26;
  //	int old = T[day];
  //	int diff = modify_diff(T, se, day, type);
  //	score += diff;
  //	if (diff >= 0) {
  //	} else {
  //	    modify_diff(T, se, day, old);
  //	}
  //    }

  bool operator<(const State &o) const { return score > o.score; }
  bool operator==(const State &o) const {
    if (score != o.score)
      return false;
    REP(c, 26) if (se[c] != o.se[c]) return false;
    REP(i, D) if (T[i] != o.T[i]) return false;
    return true;
  }
};

void output(int *T) { REP(d, D) printf("%d\\n", T[d] + 1); }

void MAIN() {
  clock_t clock_start = clock();

  scanf("%d", &D);
  REP(c, 26) scanf("%d", C + c);
  REP(i, D) REP(c, 26) scanf("%d", S[i] + c);

#ifdef LOCAL
  D = 365;
  REP(c, 26) C[c] = engine() % 101;
  REP(i, D) REP(c, 26) S[i][c] = engine() % 20001;
#endif

  double delta = 1;
  const int PA = 8;
  const int BRANCH = 8;
  const int LOOP = 1000000;
  const int CUT = 5;
  vector<State> st;
  st.resize(PA * (BRANCH + 1));
  REP(i, PA) st[i].random_initialize();
  REP($, LOOP) {
    if ($ % 1000 == 0) {
      clock_t clock_end = clock();
      double sec = (double)(clock_end - clock_start) / CLOCKS_PER_SEC;
      if (sec > 1.90) {
        eprintf("%f %d\\n", sec, $);
        break;
      }
    }
    set<int> scores;
    REP(i, PA) scores.insert(st[i].score);
    int len = PA;
    REP(i, PA) {
      REP(j, BRANCH) {
        st[len] = st[i];
        int cnt = 0;
        while (1) {
          int day = engine() % D, type = engine() % 26;
          int old = st[len].T[day];
          st[len].next(day, type);
          if (scores.find(st[len].score) == scores.end()) {
            if (st[len].score <= 0 && st[len].score > st[i].score)
              break;
            if (st[len].score > 0 &&
                st[len].score * (1.0 + delta) > st[i].score)
              break;
          }
          cnt++;
          if (cnt == CUT)
            break;
          st[len].next(day, old);
        }
        if (cnt < CUT)
          len++;
        if (cnt == CUT)
          break;
      }
    }
    nth_element(st.begin(), st.begin() + PA, st.begin() + len);
    delta *= 0.99990;
#ifdef LOCAL
//	{
//	    int pos = max_element(st.begin(), st.begin()+PA) - st.begin();
//	    eprintf("score %d %f\\n", st[pos].score, delta);
//	}
#endif
  }

#ifdef LOCAL
  REP(i, PA) {
    REP(j, PA) eprintf("%d", st[i] == st[j]);
    eprintf("\\n");
  }
#endif

  int pos = max_element(st.begin(), st.begin() + PA) - st.begin();
  output(st[pos].T);
  eprintf("score %d\\n", st[pos].score);
  eprintf("score %d\\n", (st[pos].score + 1000000) * 50);
}

int main() {
  int TC = 1;
  //    scanf("%d", &TC);
  REP(tc, TC) MAIN();
  return 0;
}


Error: TLE

Fixed submission:

#pragma GCC optimize("O3")
// #pragma GCC target ("avx")
#include <algorithm>
#include <iostream>
#include <random>
#include <set>
#include <stdio.h>
#include <string.h>
#include <string>
#include <vector>

#ifdef LOCAL
#define eprintf(...) fprintf(stderr, __VA_ARGS__)
#else
#define NDEBUG
#define eprintf(...)                                                           \\
  do {                                                                         \\
  } while (0)
#endif
#include <cassert>

using namespace std;

typedef long long LL;
typedef vector<int> VI;

#define REP(i, n) for (int i = 0, i##_len = (n); i < i##_len; ++i)
#define EACH(i, c)                                                             \\
  for (__typeof((c).begin()) i = (c).begin(), i##_end = (c).end();             \\
       i != i##_end; ++i)

template <class T> inline void amin(T &x, const T &y) {
  if (y < x)
    x = y;
}
template <class T> inline void amax(T &x, const T &y) {
  if (x < y)
    x = y;
}
template <class Iter> void rprintf(const char *fmt, Iter begin, Iter end) {
  for (bool sp = 0; begin != end; ++begin) {
    if (sp)
      putchar(' ');
    else
      sp = true;
    printf(fmt, *begin);
  }
  putchar('\\n');
}

mt19937_64 engine(20200628);

int D;
int C[26];
int S[365][26];

int last[26];

int initial_score(int *T, VI *se) {
  int cur = 0;

  REP(c, 26) {
    last[c] = -1;
    se[c].push_back(-1);
  }

  REP(i, D) {
    int t = T[i];
    last[t] = i;
    se[t].push_back(i);

    cur += S[i][t];
    REP(c, 26) cur -= C[c] * (i - last[c]);
  }

  REP(c, 26) { se[c].push_back(D); }
  return cur;
}

int tri(int n) { return n * (n - 1) / 2; }

int modify_diff(int *T, VI *se, int d, int q) {
  int p = T[d];
  if (p == q)
    return 0;
  T[d] = q;

  int ret = 0;

  int pos = lower_bound(se[p].begin(), se[p].end(), d) - se[p].begin();
  int left = se[p][pos - 1], right = se[p][pos + 1];
  ret -= C[p] * (tri(right - left) - tri(d - left) - tri(right - d));
  ret -= S[d][p];
  se[p].erase(se[p].begin() + pos);

  pos = lower_bound(se[q].begin(), se[q].end(), d) - se[q].begin();
  left = se[q][pos - 1];
  right = se[q][pos];
  ret += C[q] * (tri(right - left) - tri(d - left) - tri(right - d));
  ret += S[d][q];
  se[q].insert(se[q].begin() + pos, d);

  return ret;
}

// int solve() {
//     const int LOOP = 100000;
//     REP (i, D) T[i] = engine() % 26;
//     int cur = initial_score();
//     REP ($, LOOP) {
// 	int day = engine() % D, type = engine() % 26;
// 	int old = T[day];
// 	int diff = modify_diff(day, type);
// 	if (diff >= 0) {
// 	    cur += diff;
// 	} else {
// 	    modify_diff(day, old);
// 	}
//     }
//     // eprintf("%d\\n", cur);
// }

struct State {
  int score;
  int T[365];
  VI se[26];

  State() {}

  void random_initialize() {
    REP(i, D) T[i] = engine() % 26;
    score = initial_score(T, se);
  }

  void next(int day, int type) {
    int old = T[day];
    int diff = modify_diff(T, se, day, type);
    score += diff;
  }

  //    void random_next() {
  //	int day = engine() % D, type = engine() % 26;
  //	int old = T[day];
  //	int diff = modify_diff(T, se, day, type);
  //	score += diff;
  //	if (diff >= 0) {
  //	} else {
  //	    modify_diff(T, se, day, old);
  //	}
  //    }

  bool operator<(const State &o) const { return score > o.score; }
  bool operator==(const State &o) const {
    if (score != o.score)
      return false;
    REP(c, 26) if (se[c] != o.se[c]) return false;
    REP(i, D) if (T[i] != o.T[i]) return false;
    return true;
  }
};

void output(int *T) { REP(d, D) printf("%d\\n", T[d] + 1); }

void MAIN() {
  scanf("%d", &D);
  REP(c, 26) scanf("%d", C + c);
  REP(i, D) REP(c, 26) scanf("%d", S[i] + c);

#ifdef MYTEST
  D = 365;
  REP(c, 26) C[c] = engine() % 101;
  REP(i, D) REP(c, 26) S[i][c] = engine() % 20001;
#endif

  double delta = 1;
  const int PA = 10;
  const int BRANCH = 8;
  const int LOOP = 100000;
  const int CUT = 7;
  vector<State> st;
  st.resize(PA * (BRANCH + 1));
  REP(i, PA) st[i].random_initialize();
  REP($, LOOP) {
    set<int> scores;
    REP(i, PA) scores.insert(st[i].score);
    int len = PA;
    REP(i, PA) {
      REP(j, BRANCH) {
        st[len] = st[i];
        int cnt = 0;
        while (1) {
          int day = engine() % D, type = engine() % 26;
          int old = st[len].T[day];
          st[len].next(day, type);
          if (scores.find(st[len].score) == scores.end()) {
            if (st[len].score <= 0 && st[len].score > st[i].score)
              break;
            if (st[len].score > 0 &&
                st[len].score * (1.0 + delta) > st[i].score)
              break;
          }
          cnt++;
          if (cnt == CUT)
            break;
          st[len].next(day, old);
        }
        if (cnt < CUT)
          len++;
        if (cnt == CUT)
          break;
      }
    }
    nth_element(st.begin(), st.begin() + PA, st.begin() + len);
    delta *= 0.99990;
#ifdef LOCAL
//	{
//	    int pos = max_element(st.begin(), st.begin()+PA) - st.begin();
//	    eprintf("score %d %f\\n", st[pos].score, delta);
//	}
#endif
  }

#ifdef LOCAL
  REP(i, PA) {
    REP(j, PA) eprintf("%d", st[i] == st[j]);
    eprintf("\\n");
  }
#endif

  int pos = max_element(st.begin(), st.begin() + PA) - st.begin();
  output(st[pos].T);
  eprintf("score %d\\n", st[pos].score);
  eprintf("score %d\\n", (st[pos].score + 1000000) * 50);
}

int main() {
  int TC = 1;
  //    scanf("%d", &TC);
  REP(tc, TC) MAIN();
  return 0;
}