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

#ifndef TIMER_H
#define TIMER_H

#include <cstdint>

#ifdef ONLY_MY_ENVIR

#include <chrono>
class Timer {
  const std::chrono::time_point<std::chrono::system_clock> start;
  int64_t limit_microsec = 0;

public:
  Timer();
  void set(int64_t time_microsec);
  bool elapsed() const;
  int64_t getMicrosec() const;
};

#else

class Timer {
  static const uint64_t ClocksPerMicrosec;
  const uint64_t start_clocks;
  uint64_t limit_clocks;

  uint64_t getClocks() const;

public:
  Timer();
  void set(int64_t time_microsec);
  bool elapsed() const;
  int64_t getMicrosec() const;
};

#endif

#endif

#ifdef ONLY_MY_ENVIR
#include "Timer.h"
#endif

#ifdef ONLY_MY_ENVIR

using namespace std::chrono;

Timer::Timer() : start(system_clock::now()) {}

void Timer::set(int64_t time_microsec) { limit_microsec += time_microsec; }

bool Timer::elapsed() const { return getMicrosec() >= limit_microsec; }

int64_t Timer::getMicrosec() const {
  return duration_cast<microseconds>(system_clock::now() - start).count();
}

#else

const uint64_t Timer::ClocksPerMicrosec = 2987;

uint64_t Timer::getClocks() const {
  unsigned int lo, hi;
  __asm__ volatile("rdtsc" : "=a"(lo), "=d"(hi));
  return ((uint64_t)hi << 32) | lo;
}

Timer::Timer() : start_clocks(getClocks()), limit_clocks(start_clocks) {}

void Timer::set(int64_t time_microsec) {
  limit_clocks += time_microsec * ClocksPerMicrosec;
}

bool Timer::elapsed() const { return getClocks() >= limit_clocks; }

int64_t Timer::getMicrosec() const {
  return (getClocks() - start_clocks) / ClocksPerMicrosec;
}

#endif

#ifndef RANDOM_H
#define RANDOM_H

#include <cstdint>
#include <utility>

uint32_t rnd();
uint32_t rnd(uint32_t max);

template <class T> void shuffle(T &arr);

template <class T> void shuffle(T &arr) {
  for (int i = arr.size(); i > 1; --i) {
    std::swap(arr[i - 1], arr[rnd(i)]);
  }
}

#endif

#ifdef ONLY_MY_ENVIR
#include "Random.h"
#endif

#include <vector>

uint32_t rnd() {
  static uint32_t val = 3141592653ul;
  val ^= val << 13;
  val ^= val >> 17;
  val ^= val << 15;
  return val;
}

uint32_t rnd(uint32_t max) { return rnd() % max; }
#define _CRT_SECURE_NO_WARNINGS
#define _SCL_SECURE_NO_WARNINGS
#include <algorithm>
#include <array>
#include <bitset>
#include <cassert>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <fstream>
#include <functional>
#include <iomanip>
#include <iostream>
#include <limits>
#include <list>
#include <map>
#include <numeric>
#include <queue>
#include <random>
#include <set>
#include <sstream>
#include <stack>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <utility>
#include <valarray>
#include <vector>

using namespace std;
using uint = uint32_t;
using LL = int64_t;
using ULL = uint64_t;
using PP = pair<LL, LL>;
template <typename T>
using PriorityQ = priority_queue<T, vector<T>, greater<T>>;
#define REP(i, a, n) for (LL i = (a), i##_max_ = (n); i < i##_max_; ++i)
#define REM(i, a, n) for (LL i = (LL)(n)-1, i##_min_ = (a); i >= i##_min_; --i)
#define FLOAT fixed << setprecision(16)
#define SPEEDUP                                                                \\
  {                                                                            \\
    cin.tie(NULL);                                                             \\
    ios::sync_with_stdio(false);                                               \\
  }
const int INF = 0x3FFFFFFF;
const LL INFLL = 0x3FFFFFFF3FFFFFFF;
const double INFD = 1.0e+308;
const double EPS = 1.0e-9;

void YesNo(bool b) { cout << (b ? "Yes" : "No") << endl; }
void YESNO(bool b) { cout << (b ? "YES" : "NO") << endl; }
template <class T, class U>
istream &operator>>(istream &ist, pair<T, U> &right) {
  return ist >> right.first >> right.second;
}
template <class T, class U>
ostream &operator<<(ostream &ost, const pair<T, U> &right) {
  return ost << right.first << ' ' << right.second;
}
template <class T, class TCompatible, size_t N>
void Fill(T (&dest)[N], const TCompatible &val) {
  fill(dest, dest + N, val);
}
template <class T, class TCompatible, size_t M, size_t N>
void Fill(T (&dest)[M][N], const TCompatible &val) {
  for (int i = 0; i < M; ++i)
    Fill(dest[i], val);
}
template <class T> T Next() {
  T buf;
  cin >> buf;
  return buf;
}
istream &Ignore(istream &ist) {
  string s;
  ist >> s;
  return ist;
}
bool Inside(int i, int j, int h, int w) {
  return i >= 0 && i < h && j >= 0 && j < w;
}

#ifdef ONLY_MY_ENVIR
#include "Accumulator.h"
#include "Algebraic.h"
#include "BIT.h"
#include "BinaryMatrix.h"
#include "BinaryTree.h"
#include "Bipartite.h"
#include "Compressor.h"
#include "Decompositions.h"
#include "DiscreteLog.h"
#include "DynamicMod.h"
#include "FFT.h"
#include "Factorization.h"
#include "FlowSolver.h"
#include "Graph.h"
#include "GraphUtil.h"
#include "IntMod.h"
#include "LIS.h"
#include "LazySegmentTree.h"
#include "Math.h"
#include "MathUtil.h"
#include "Matrix.h"
#include "MinCostFlowSolver.h"
#include "MinMax.h"
#include "Numbers.h"
#include "Optimize.h"
#include "Permutation.h"
#include "Polynomial.h"
#include "Position.h"
#include "Random.h"
#include "Range.h"
#include "Rational.h"
#include "RuntimeMod.h"
#include "SegmentTree.h"
#include "SegmentTree2D.h"
#include "Sets.h"
#include "Shortest.h"
#include "SlidingWindow.h"
#include "SpanningTree.h"
#include "StringSearching.h"
#include "SuffixArray.h"
#include "SwitchList.h"
#include "Timer.h"
#include "Tree.h"
#include "TreeUtil.h"
#include "UnionFind.h"
#include "Util.h"
#include "VectorUtil.h"
#endif

#ifdef __GNUC__
typedef __int128 LLL;
istream &operator>>(istream &ist, __int128 &val) {
  LL tmp;
  ist >> tmp;
  val = tmp;
  return ist;
}
ostream &operator<<(ostream &ost, __int128 val) {
  LL tmp = val;
  ost << tmp;
  return ost;
}
#endif

const int K = 26;
const int N = 365;
LL C[K];
LL S[N][K];

class Helper {
  int state[N];
  int prv[N];
  int nxt[N];

  LL score;
  LL prev_score;

  int memo_type;
  int memo_i;
  int memo_j;
  int memo_k;

  LL pen[K][N + 2];

public:
  Helper() {
    REP(i, 0, N) {
      int k = i % K;
      state[i] = k;
      prv[i] = max<int>(-1, i - K);
      nxt[i] = min<int>(N, i + K);
    }
    score = calcScore();

    REP(k, 0, K) {
      REP(i, 0, N + 2) { pen[k][i] = C[k] * i * (i - 1) / 2; }
    }
  }

  void change(int i, int bk, bool update_score) {
    if (state[i] == bk)
      return;
    int ak = state[i];
    state[i] = bk;

    int al = prv[i];
    int ar = nxt[i];
    if (al >= 0)
      nxt[al] = ar;
    if (ar < N)
      prv[ar] = al;

    int bl = i - 1;
    int br = i + 1;
    while (bl >= 0 && state[bl] != bk)
      --bl;
    if (bl >= 0) {
      br = nxt[bl];
    } else {
      while (br < N && state[br] != bk)
        ++br;
    }

    if (bl >= 0)
      nxt[bl] = i;
    if (br < N)
      prv[br] = i;
    prv[i] = bl;
    nxt[i] = br;

    if (update_score) {
      score -= S[i][ak];
      score += S[i][bk];
      score -= pen[ak][ar - al] - pen[ak][i - al] - pen[ak][ar - i];
      score += pen[bk][br - bl] - pen[bk][i - bl] - pen[bk][br - i];
    }
  }

  void changeSwap(int i, int j, bool update_score) {
    int ak = state[i];
    int bk = state[j];
    change(i, bk, update_score);
    change(j, ak, update_score);
  }

  LL step() {
    prev_score = score;

    memo_type = rnd(2);
    if (memo_type) {
      int i;
      int j;
      do {
        i = rnd(N);
        j = rnd(N);
      } while (abs(j - i) > 50);

      memo_i = i;
      memo_j = j;
      changeSwap(i, j, true);
    } else {
      int i = rnd(N);
      int k = rnd(K);
      memo_i = i;
      memo_k = state[i];
      change(i, k, true);
    }

    return score - prev_score;
  }

  void undo() {
    score = prev_score;
    if (memo_type) {
      changeSwap(memo_i, memo_j, false);
    } else {
      change(memo_i, memo_k, false);
    }
  }

  const int *getState() const { return state; }

  LL getScore() const { return score; }

  LL calcScore() const {
    LL good = 0;
    REP(i, 0, N) { good += S[i][state[i]]; }

    LL bad = 0;
    LL last[K];
    fill(last, last + K, -1);
    REP(i, 0, N) {
      last[state[i]] = i;
      REP(k, 0, K) { bad += C[k] * (i - last[k]); }
    }
    return good - bad;
  }
};

int main() {
#ifdef ONLY_MY_ENVIR
  ifstream ifs("sample.txt");
  ifs >> Ignore;
  REP(k, 0, K) ifs >> C[k];
  REP(i, 0, N) REP(k, 0, K) ifs >> S[i][k];
#else
  cin >> Ignore;
  REP(k, 0, K) cin >> C[k];
  REP(i, 0, N) REP(k, 0, K) cin >> S[i][k];
#endif

  Helper helper;
  const double tmp_start = 1e7;
  const double tmp_finish = 1e2;
  double tmp = tmp_start;

#ifdef ONLY_MY_ENVIR
  const int time = 1990000;
#else
  const int time = 1990000;
#endif

  Timer timer;
  timer.set(time);

  int z = 0;
  while (z % 4096 == 0 || !timer.elapsed()) {
    ++z;
    if (z % 4096 == 0) {
      double ratio = (double)timer.getMicrosec() / time;
      tmp = tmp_start * std::pow(tmp_finish / tmp_start, ratio);
#ifdef ONLY_MY_ENVIR
      cerr << tmp << ' ' << helper.getScore() << endl;
#endif
    }

    LL delta = helper.step();
    bool accepted =
        delta >= 0 ||
        -delta <= 8 * tmp && rnd() < std::exp(delta / tmp) * (1ll << 32);

    if (!accepted) {
      helper.undo();
    }
  }

  auto state = helper.getState();

#ifdef ONLY_MY_ENVIR
  ofstream ofs("out.txt");
  REP(i, 0, N) { ofs << state[i] + 1 << endl; }
#else
  REP(i, 0, N) { cout << state[i] + 1 << endl; }
#endif
  return 0;
}


Error: TLE

Fixed submission:

#ifndef TIMER_H
#define TIMER_H

#include <cstdint>

#ifdef ONLY_MY_ENVIR

#include <chrono>
class Timer {
  const std::chrono::time_point<std::chrono::system_clock> start;
  int64_t limit_microsec = 0;

public:
  Timer();
  void set(int64_t time_microsec);
  bool elapsed() const;
  int64_t getMicrosec() const;
};

#else

class Timer {
  static const uint64_t ClocksPerMicrosec;
  const uint64_t start_clocks;
  uint64_t limit_clocks;

  uint64_t getClocks() const;

public:
  Timer();
  void set(int64_t time_microsec);
  bool elapsed() const;
  int64_t getMicrosec() const;
};

#endif

#endif

#ifdef ONLY_MY_ENVIR
#include "Timer.h"
#endif

#ifdef ONLY_MY_ENVIR

using namespace std::chrono;

Timer::Timer() : start(system_clock::now()) {}

void Timer::set(int64_t time_microsec) { limit_microsec += time_microsec; }

bool Timer::elapsed() const { return getMicrosec() >= limit_microsec; }

int64_t Timer::getMicrosec() const {
  return duration_cast<microseconds>(system_clock::now() - start).count();
}

#else

const uint64_t Timer::ClocksPerMicrosec = 2987;

uint64_t Timer::getClocks() const {
  unsigned int lo, hi;
  __asm__ volatile("rdtsc" : "=a"(lo), "=d"(hi));
  return ((uint64_t)hi << 32) | lo;
}

Timer::Timer() : start_clocks(getClocks()), limit_clocks(start_clocks) {}

void Timer::set(int64_t time_microsec) {
  limit_clocks += time_microsec * ClocksPerMicrosec;
}

bool Timer::elapsed() const { return getClocks() >= limit_clocks; }

int64_t Timer::getMicrosec() const {
  return (getClocks() - start_clocks) / ClocksPerMicrosec;
}

#endif

#ifndef RANDOM_H
#define RANDOM_H

#include <cstdint>
#include <utility>

uint32_t rnd();
uint32_t rnd(uint32_t max);

template <class T> void shuffle(T &arr);

template <class T> void shuffle(T &arr) {
  for (int i = arr.size(); i > 1; --i) {
    std::swap(arr[i - 1], arr[rnd(i)]);
  }
}

#endif

#ifdef ONLY_MY_ENVIR
#include "Random.h"
#endif

#include <vector>

uint32_t rnd() {
  static uint32_t val = 3141592653ul;
  val ^= val << 13;
  val ^= val >> 17;
  val ^= val << 15;
  return val;
}

uint32_t rnd(uint32_t max) { return rnd() % max; }

#define _CRT_SECURE_NO_WARNINGS
#define _SCL_SECURE_NO_WARNINGS
#include <algorithm>
#include <array>
#include <bitset>
#include <cassert>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <fstream>
#include <functional>
#include <iomanip>
#include <iostream>
#include <limits>
#include <list>
#include <map>
#include <numeric>
#include <queue>
#include <random>
#include <set>
#include <sstream>
#include <stack>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <utility>
#include <valarray>
#include <vector>

using namespace std;
using uint = uint32_t;
using LL = int64_t;
using ULL = uint64_t;
using PP = pair<LL, LL>;
template <typename T>
using PriorityQ = priority_queue<T, vector<T>, greater<T>>;
#define REP(i, a, n) for (LL i = (a), i##_max_ = (n); i < i##_max_; ++i)
#define REM(i, a, n) for (LL i = (LL)(n)-1, i##_min_ = (a); i >= i##_min_; --i)
#define FLOAT fixed << setprecision(16)
#define SPEEDUP                                                                \\
  {                                                                            \\
    cin.tie(NULL);                                                             \\
    ios::sync_with_stdio(false);                                               \\
  }
const int INF = 0x3FFFFFFF;
const LL INFLL = 0x3FFFFFFF3FFFFFFF;
const double INFD = 1.0e+308;
const double EPS = 1.0e-9;

void YesNo(bool b) { cout << (b ? "Yes" : "No") << endl; }
void YESNO(bool b) { cout << (b ? "YES" : "NO") << endl; }
template <class T, class U>
istream &operator>>(istream &ist, pair<T, U> &right) {
  return ist >> right.first >> right.second;
}
template <class T, class U>
ostream &operator<<(ostream &ost, const pair<T, U> &right) {
  return ost << right.first << ' ' << right.second;
}
template <class T, class TCompatible, size_t N>
void Fill(T (&dest)[N], const TCompatible &val) {
  fill(dest, dest + N, val);
}
template <class T, class TCompatible, size_t M, size_t N>
void Fill(T (&dest)[M][N], const TCompatible &val) {
  for (int i = 0; i < M; ++i)
    Fill(dest[i], val);
}
template <class T> T Next() {
  T buf;
  cin >> buf;
  return buf;
}
istream &Ignore(istream &ist) {
  string s;
  ist >> s;
  return ist;
}
bool Inside(int i, int j, int h, int w) {
  return i >= 0 && i < h && j >= 0 && j < w;
}

#ifdef ONLY_MY_ENVIR
#include "Accumulator.h"
#include "Algebraic.h"
#include "BIT.h"
#include "BinaryMatrix.h"
#include "BinaryTree.h"
#include "Bipartite.h"
#include "Compressor.h"
#include "Decompositions.h"
#include "DiscreteLog.h"
#include "DynamicMod.h"
#include "FFT.h"
#include "Factorization.h"
#include "FlowSolver.h"
#include "Graph.h"
#include "GraphUtil.h"
#include "IntMod.h"
#include "LIS.h"
#include "LazySegmentTree.h"
#include "Math.h"
#include "MathUtil.h"
#include "Matrix.h"
#include "MinCostFlowSolver.h"
#include "MinMax.h"
#include "Numbers.h"
#include "Optimize.h"
#include "Permutation.h"
#include "Polynomial.h"
#include "Position.h"
#include "Random.h"
#include "Range.h"
#include "Rational.h"
#include "RuntimeMod.h"
#include "SegmentTree.h"
#include "SegmentTree2D.h"
#include "Sets.h"
#include "Shortest.h"
#include "SlidingWindow.h"
#include "SpanningTree.h"
#include "StringSearching.h"
#include "SuffixArray.h"
#include "SwitchList.h"
#include "Timer.h"
#include "Tree.h"
#include "TreeUtil.h"
#include "UnionFind.h"
#include "Util.h"
#include "VectorUtil.h"
#endif

#ifdef __GNUC__
typedef __int128 LLL;
istream &operator>>(istream &ist, __int128 &val) {
  LL tmp;
  ist >> tmp;
  val = tmp;
  return ist;
}
ostream &operator<<(ostream &ost, __int128 val) {
  LL tmp = val;
  ost << tmp;
  return ost;
}
#endif

const int K = 26;
const int N = 365;
LL C[K];
LL S[N][K];

class Helper {
  int state[N];
  int prv[N];
  int nxt[N];

  LL score;
  LL prev_score;

  int memo_type;
  int memo_i;
  int memo_j;
  int memo_k;

  LL pen[K][N + 2];

public:
  Helper() {
    REP(i, 0, N) {
      int k = i % K;
      state[i] = k;
      prv[i] = max<int>(-1, i - K);
      nxt[i] = min<int>(N, i + K);
    }
    score = calcScore();

    REP(k, 0, K) {
      REP(i, 0, N + 2) { pen[k][i] = C[k] * i * (i - 1) / 2; }
    }
  }

  void change(int i, int bk, bool update_score) {
    if (state[i] == bk)
      return;
    int ak = state[i];
    state[i] = bk;

    int al = prv[i];
    int ar = nxt[i];
    if (al >= 0)
      nxt[al] = ar;
    if (ar < N)
      prv[ar] = al;

    int bl = i - 1;
    int br = i + 1;
    while (bl >= 0 && state[bl] != bk)
      --bl;
    if (bl >= 0) {
      br = nxt[bl];
    } else {
      while (br < N && state[br] != bk)
        ++br;
    }

    if (bl >= 0)
      nxt[bl] = i;
    if (br < N)
      prv[br] = i;
    prv[i] = bl;
    nxt[i] = br;

    if (update_score) {
      score -= S[i][ak];
      score += S[i][bk];
      score -= pen[ak][ar - al] - pen[ak][i - al] - pen[ak][ar - i];
      score += pen[bk][br - bl] - pen[bk][i - bl] - pen[bk][br - i];
    }
  }

  void changeSwap(int i, int j, bool update_score) {
    int ak = state[i];
    int bk = state[j];
    change(i, bk, update_score);
    change(j, ak, update_score);
  }

  LL step() {
    prev_score = score;

    memo_type = rnd(2);
    if (memo_type) {
      int i;
      int j;
      do {
        i = rnd(N);
        j = rnd(N);
      } while (abs(j - i) > 50);

      memo_i = i;
      memo_j = j;
      changeSwap(i, j, true);
    } else {
      int i = rnd(N);
      int k = rnd(K);
      memo_i = i;
      memo_k = state[i];
      change(i, k, true);
    }

    return score - prev_score;
  }

  void undo() {
    score = prev_score;
    if (memo_type) {
      changeSwap(memo_i, memo_j, false);
    } else {
      change(memo_i, memo_k, false);
    }
  }

  const int *getState() const { return state; }

  LL getScore() const { return score; }

  LL calcScore() const {
    LL good = 0;
    REP(i, 0, N) { good += S[i][state[i]]; }

    LL bad = 0;
    LL last[K];
    fill(last, last + K, -1);
    REP(i, 0, N) {
      last[state[i]] = i;
      REP(k, 0, K) { bad += C[k] * (i - last[k]); }
    }
    return good - bad;
  }
};

int main() {
#ifdef ONLY_MY_ENVIR
  ifstream ifs("sample.txt");
  ifs >> Ignore;
  REP(k, 0, K) ifs >> C[k];
  REP(i, 0, N) REP(k, 0, K) ifs >> S[i][k];
#else
  cin >> Ignore;
  REP(k, 0, K) cin >> C[k];
  REP(i, 0, N) REP(k, 0, K) cin >> S[i][k];
#endif

  Helper helper;
  const double tmp_start = 1e7;
  const double tmp_finish = 1e2;
  double tmp = tmp_start;

  const int time = 19900000;
  Timer timer;
  timer.set(time);

  int z = 0;
  while (z % 4096 == 0 || !timer.elapsed()) {
    ++z;
    if (z % 4096 == 0) {
      double ratio = (double)timer.getMicrosec() / time;
      tmp = tmp_start * std::pow(tmp_finish / tmp_start, ratio);
#ifdef ONLY_MY_ENVIR
      cerr << tmp << ' ' << helper.getScore() << endl;
#endif
    }

    LL delta = helper.step();
    bool accepted =
        delta >= 0 ||
        -delta <= 8 * tmp && rnd() < std::exp(delta / tmp) * (1ll << 32);

    if (!accepted) {
      helper.undo();
    }
  }

  auto state = helper.getState();

#ifdef ONLY_MY_ENVIR
  ofstream ofs("out.txt");
  REP(i, 0, N) { ofs << state[i] + 1 << endl; }
#else
  REP(i, 0, N) { cout << state[i] + 1 << endl; }
#endif
  return 0;
}