Problem p02620 (C++)

Buggy submission (status: Runtime Error):
/*
マラソン用　テンプレート
*/
/*力が欲しいか…？
#pragma GCC optimize("Ofast","unroll-loops","omit-frame-pointer","inline")
//Optimization flags #pragma GCC
option("arch=native","tune=native","no-zero-upper") //Enable AVX #pragma GCC
target("avx")  //Enable AVX
*/
// #include <x86intrin.h>
#include <algorithm>
#include <bitset>
#include <cassert>
#include <chrono>
#include <cmath>
#include <complex>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <functional>
#include <iomanip>
#include <iostream>
#include <limits>
#include <map>
#include <queue>
#include <random>
#include <set>
#include <stack>
#include <string>
#include <tuple>
#include <vector>

using namespace std;
using namespace chrono;

template <class T, class U> inline constexpr bool chmin(T &a, const U b) {
  if (a <= b)
    return false;
  a = b;
  return true;
}
template <class T, class U> inline constexpr bool chmax(T &a, const U b) {
  if (a >= b)
    return false;
  a = b;
  return true;
}
#define bit(n, k) (((n) >> (k)) & 1)

inline void bin101() {
  ios::sync_with_stdio(false);
  cin.tie(nullptr);
  cout << fixed << setprecision(20);
}

using i8 = int8_t;
using i16 = int16_t;
using i32 = int32_t;
using i64 = int64_t;

using u8 = uint8_t;
using u16 = uint16_t;
using u32 = uint32_t;
using u64 = uint64_t;

// Xorshift(色々なbit)とTimerを書く

struct Timer {
  chrono::high_resolution_clock::time_point st;

  Timer() { start(); }

  void start() { st = chrono::high_resolution_clock::now(); }
  chrono::milliseconds::rep span() {
    auto ed = chrono::high_resolution_clock::now();
    return chrono::duration_cast<chrono::milliseconds>(ed - st).count();
  }
};

struct Test {
  chrono::high_resolution_clock::time_point st;
  Test() { start(); }
  u64 sum = 0;
  u64 cnt = 0;
  void start() { st = chrono::high_resolution_clock::now(); }
  void span() {
    sum += chrono::duration_cast<chrono::nanoseconds>(
               chrono::high_resolution_clock::now() - st)
               .count();
    cnt++;
  }
  void print() {
    cerr << "TEST" << endl;
    cerr << "cnt:" << cnt << "ave:" << (long double)sum / cnt << endl;
  }
  void reset() {
    sum = 0;
    cnt = 0;
    st = chrono::high_resolution_clock::now();
  }
};

struct Xor32 {
  u32 x = 1234567;
  inline u32 rnd_make() {
    x ^= (x << 13);
    x = x ^ (x >> 17);
    return x = x ^ (x << 5);
  }
  inline u32 operator()() { return rnd_make(); }
  //[a,b]
  inline int operator()(int a, int b) {
    int dis = b - a + 1;
    int add = rnd_make() % dis;
    return a + add;
  }
};

struct Xor8 {
  uint8_t x[128];
  uint8_t cnt = 0;
  Xor8() {
    uint_fast8_t y = 10;
    for (int i = 0; i < 128; i++) {
      y ^= (y >> 1);
      y ^= (y << 1);
      y ^= (y >> 2);
      x[i] = (y & 0b11111);
    }
  }
  inline uint8_t rnd_make() {
    if (bit(cnt, 7))
      cnt = 0;
    return x[cnt++];
  }
  inline uint8_t operator()() { return rnd_make(); }
  inline uint8_t operator()(int a, int b) {
    int dis = b - a + 1;
    int add = rnd_make() % dis;
    return a + add;
  }
};

int D = 365;
int c[26];
int s[366][26];
int last[366][26];
int hand[366];
set<int> used[26];

Xor32 Rand;
Timer TIME;

void ans_print() {
  for (int i = 1; i <= D; i++) {
    cout << hand[i] + 1 << "\n";
  }
}
// http://shindannin.hatenadiary.com/entry/20121224/1356364040
// http://gasin.hatenadiary.jp/entry/2019/09/03/162613
inline bool yakinamashi(float plus) {
  static float startTemp = 2000000; // 差の最大値
  static float endTemp = 10;        // 差の最小値
  static float endTime = 1960;
  float temp =
      startTemp + (endTemp - startTemp) * TIME.span() /
                      endTime; // 時間がたつにつれ、startTemp→endTempに変化
  // cerr<<temp<<endl;
  float probability = exp(plus / temp);
  // cerr<<plus<<" "<<probability<<endl;
  return probability > (float)(Rand() % 100) / 100;
}

int main() {
  bin101();
  cin >> D;
  for (int i = 0; i < 26; i++)
    cin >> c[i];
  for (int i = 1; i <= D; i++) {
    for (int j = 0; j < 26; j++)
      cin >> s[i][j];
  }

  i64 ret = 0;

  for (int i = 1; i <= D; i++) {
    int t = Rand(0, 25);
    cin >> t;
    hand[i] = t;
    used[t].insert(i);
    ret += s[i][t];
    last[i][t] = i;
    for (int j = 0; j < 26; j++) {
      if (j != t)
        last[i][j] = last[i - 1][j];
      ret -= c[j] * (i - last[i][j]);
    }
  }
  for (int i = 0; i < 26; i++) {
    used[i].insert(D + 1);
    used[i].insert(0);
  }
  cerr << ret << endl;
  i64 plus;
  i64 max_plus = 0;
  int d, post, pre;
  u32 cnt = 0;
  int M;
  cin >> M;
  while (M--) {
    if ((cnt & 0b1111111) == 0b1111111) {
      if (TIME.span() > 1960)
        break;
    }
    cnt++;
    plus = 0;
    d = Rand(1, 365), post = Rand(0, 25);
    cin >> d >> post;
    post--;
    pre = hand[d];
    // まずはsの反映
    plus += (s[d][post] - s[d][pre]);
    auto pre_middle = used[pre].find(d);
    auto pre_sita = pre_middle;
    pre_sita--;
    auto pre_ue = pre_middle;
    pre_ue++;
    plus -= c[pre] * (*pre_ue - d) * (d - *pre_sita);

    auto post_ue = used[post].upper_bound(d);
    auto post_sita = post_ue;
    post_sita--;
    plus += c[post] * (*post_ue - d) * (d - *post_sita);
    if (true || plus > 0 || yakinamashi(plus)) {
      hand[d] = post;
      used[pre].erase(pre_middle);
      used[post].insert(d);
      ret += plus;
    }
    cout << ret << endl;
  }
}


Fixed submission:
/*
マラソン用　テンプレート
*/
/*力が欲しいか…？
#pragma GCC optimize("Ofast","unroll-loops","omit-frame-pointer","inline")
//Optimization flags #pragma GCC
option("arch=native","tune=native","no-zero-upper") //Enable AVX #pragma GCC
target("avx")  //Enable AVX
*/
// #include <x86intrin.h>
#include <algorithm>
#include <bitset>
#include <cassert>
#include <chrono>
#include <cmath>
#include <complex>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <functional>
#include <iomanip>
#include <iostream>
#include <limits>
#include <map>
#include <queue>
#include <random>
#include <set>
#include <stack>
#include <string>
#include <tuple>
#include <vector>

using namespace std;
using namespace chrono;

template <class T, class U> inline constexpr bool chmin(T &a, const U b) {
  if (a <= b)
    return false;
  a = b;
  return true;
}
template <class T, class U> inline constexpr bool chmax(T &a, const U b) {
  if (a >= b)
    return false;
  a = b;
  return true;
}
#define bit(n, k) (((n) >> (k)) & 1)

inline void bin101() {
  ios::sync_with_stdio(false);
  cin.tie(nullptr);
  cout << fixed << setprecision(20);
}

using i8 = int8_t;
using i16 = int16_t;
using i32 = int32_t;
using i64 = int64_t;

using u8 = uint8_t;
using u16 = uint16_t;
using u32 = uint32_t;
using u64 = uint64_t;

// Xorshift(色々なbit)とTimerを書く

struct Timer {
  chrono::high_resolution_clock::time_point st;

  Timer() { start(); }

  void start() { st = chrono::high_resolution_clock::now(); }
  chrono::milliseconds::rep span() {
    auto ed = chrono::high_resolution_clock::now();
    return chrono::duration_cast<chrono::milliseconds>(ed - st).count();
  }
};

struct Test {
  chrono::high_resolution_clock::time_point st;
  Test() { start(); }
  u64 sum = 0;
  u64 cnt = 0;
  void start() { st = chrono::high_resolution_clock::now(); }
  void span() {
    sum += chrono::duration_cast<chrono::nanoseconds>(
               chrono::high_resolution_clock::now() - st)
               .count();
    cnt++;
  }
  void print() {
    cerr << "TEST" << endl;
    cerr << "cnt:" << cnt << "ave:" << (long double)sum / cnt << endl;
  }
  void reset() {
    sum = 0;
    cnt = 0;
    st = chrono::high_resolution_clock::now();
  }
};

struct Xor32 {
  u32 x = 1234567;
  inline u32 rnd_make() {
    x ^= (x << 13);
    x = x ^ (x >> 17);
    return x = x ^ (x << 5);
  }
  inline u32 operator()() { return rnd_make(); }
  //[a,b]
  inline int operator()(int a, int b) {
    int dis = b - a + 1;
    int add = rnd_make() % dis;
    return a + add;
  }
};

struct Xor8 {
  uint8_t x[128];
  uint8_t cnt = 0;
  Xor8() {
    uint_fast8_t y = 10;
    for (int i = 0; i < 128; i++) {
      y ^= (y >> 1);
      y ^= (y << 1);
      y ^= (y >> 2);
      x[i] = (y & 0b11111);
    }
  }
  inline uint8_t rnd_make() {
    if (bit(cnt, 7))
      cnt = 0;
    return x[cnt++];
  }
  inline uint8_t operator()() { return rnd_make(); }
  inline uint8_t operator()(int a, int b) {
    int dis = b - a + 1;
    int add = rnd_make() % dis;
    return a + add;
  }
};

int D = 365;
int c[26];
int s[366][26];
int last[366][26];
int hand[366];
set<int> used[26];

Xor32 Rand;
Timer TIME;

void ans_print() {
  for (int i = 1; i <= D; i++) {
    cout << hand[i] + 1 << "\n";
  }
}
// http://shindannin.hatenadiary.com/entry/20121224/1356364040
// http://gasin.hatenadiary.jp/entry/2019/09/03/162613
inline bool yakinamashi(float plus) {
  static float startTemp = 2000000; // 差の最大値
  static float endTemp = 10;        // 差の最小値
  static float endTime = 1960;
  float temp =
      startTemp + (endTemp - startTemp) * TIME.span() /
                      endTime; // 時間がたつにつれ、startTemp→endTempに変化
  // cerr<<temp<<endl;
  float probability = exp(plus / temp);
  // cerr<<plus<<" "<<probability<<endl;
  return probability > (float)(Rand() % 100) / 100;
}

int main() {
  bin101();
  cin >> D;
  for (int i = 0; i < 26; i++)
    cin >> c[i];
  for (int i = 1; i <= D; i++) {
    for (int j = 0; j < 26; j++)
      cin >> s[i][j];
  }

  i64 ret = 0;

  for (int i = 1; i <= D; i++) {
    int t = Rand(0, 25);
    cin >> t;
    t--;
    hand[i] = t;
    used[t].insert(i);
    ret += s[i][t];
    last[i][t] = i;
    for (int j = 0; j < 26; j++) {
      if (j != t)
        last[i][j] = last[i - 1][j];
      ret -= c[j] * (i - last[i][j]);
    }
  }
  for (int i = 0; i < 26; i++) {
    used[i].insert(D + 1);
    used[i].insert(0);
  }
  cerr << ret << endl;
  i64 plus;
  i64 max_plus = 0;
  int d, post, pre;
  u32 cnt = 0;
  int M;
  cin >> M;
  while (M--) {
    if ((cnt & 0b1111111) == 0b1111111) {
      if (TIME.span() > 1960)
        break;
    }
    cnt++;
    plus = 0;
    d = Rand(1, 365), post = Rand(0, 25);
    cin >> d >> post;
    post--;
    pre = hand[d];
    // まずはsの反映
    plus += (s[d][post] - s[d][pre]);
    auto pre_middle = used[pre].find(d);
    auto pre_sita = pre_middle;
    pre_sita--;
    auto pre_ue = pre_middle;
    pre_ue++;
    plus -= c[pre] * (*pre_ue - d) * (d - *pre_sita);

    auto post_ue = used[post].upper_bound(d);
    auto post_sita = post_ue;
    post_sita--;
    plus += c[post] * (*post_ue - d) * (d - *post_sita);
    if (true || plus > 0 || yakinamashi(plus)) {
      hand[d] = post;
      used[pre].erase(pre_middle);
      used[post].insert(d);
      ret += plus;
    }
    cout << ret << endl;
  }
}