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;
using ll = long long;
using P = pair<int, int>;

double TIME_LIMIT = 1.95;

struct RandomNumberGenerator {
  mt19937 mt;
  RandomNumberGenerator()
      : mt(chrono::steady_clock::now().time_since_epoch().count()) {}
  int operator()(int a, int b) { // [a, b)
    uniform_int_distribution<int> dist(a, b - 1);
    return dist(mt);
  }
  int operator()(int b) { // [0, b)
    return (*this)(0, b);
  }
};

// 状態
struct STATE {
  int Type;
  int D;
  map<int, int> c;
  map<P, int> s;
};

struct QUERY {
  int day;
  int type;
  QUERY(int d, int t) : day(d), type(t) {}
};

RandomNumberGenerator rnd;

struct SCHEDULE {
  vector<int> t;
  STATE &state;
  int schedule_score;
  SCHEDULE(STATE &st) : state(st) {
    // 初期化
    rep(i, state.D) {
      int type = rnd(state.Type) + 1;
      held(type);
    }
    init_score();
  }
  int current_day() { return t.size(); }
  int type(int day) { return t[day - 1]; }
  void held(int type) { t.push_back(type); }
  void init_score() {
    map<int, int> last_day;
    int score = 0;
    int m_day = t.size();
    for (int day = 1; day <= m_day; day++) {
      int type = t[day - 1];
      int ps = state.s[P(day, type)];
      int ng = 0;
      last_day[type] = day;
      for (int t = 1; t <= state.Type; t++) {
        ng += state.c[t] * (day - last_day[t]);
      }
      score = score + ps - ng;
    }
    schedule_score = score;
  }
  void modify(QUERY &query, int score) {
    t[query.day - 1] = query.type;
    schedule_score = score;
  }
  int score_if_modify(QUERY &query) {
    // TODO: 高速化
    map<int, int> last_day;
    int score = 0;
    int m_day = t.size();
    for (int day = 1; day <= m_day; day++) {
      int type = t[day - 1];

      if (day == query.day) {
        type = query.type;
      }

      int ps = state.s[P(day, type)];
      int ng = 0;
      last_day[type] = day;
      for (int t = 1; t <= state.Type; t++) {
        ng += state.c[t] * (day - last_day[t]);
      }
      score = score + ps - ng;
    }
    return score;
  }
};

// 状態の初期化
STATE init() {
  STATE state;
  int Type = 26;
  int D;
  cin >> D;
  state.Type = 26;
  state.D = D;
  rep(i, Type) {
    int c_i;
    cin >> c_i;
    state.c[i + 1] = c_i;
  }
  rep(d, D) {
    rep(t, Type) {
      int s_dt;
      cin >> s_dt;
      state.s[P(d + 1, t + 1)] = s_dt;
    }
  }
  return state;
}

QUERY generate_query(STATE &state) {
  int day = rnd(state.D) + 1;
  int type = rnd(state.Type) + 1;
  return QUERY(day, type);
}

int main() {
  STATE state = init();
  SCHEDULE schedule(state);

  while (true) {
    if ((double)clock() / CLOCKS_PER_SEC > TIME_LIMIT)
      break;

    int pre_score = schedule.schedule_score;
    QUERY query = generate_query(state);
    int new_score = schedule.score_if_modify(query);
    if (new_score > pre_score) {
      schedule.modify(query, new_score);
    }
  }

  rep(i, state.D) { cout << schedule.t[i] << endl; }

  // cout << (double)clock() / CLOCKS_PER_SEC << endl;
  return 0;
}


Error: TLE

Fixed submission:

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

double TIME_LIMIT = 2;

struct RandomNumberGenerator {
  mt19937 mt;
  RandomNumberGenerator()
      : mt(chrono::steady_clock::now().time_since_epoch().count()) {}
  int operator()(int a, int b) { // [a, b)
    uniform_int_distribution<int> dist(a, b - 1);
    return dist(mt);
  }
  int operator()(int b) { // [0, b)
    return (*this)(0, b);
  }
};

// 状態
struct STATE {
  int Type;
  int D;
  map<int, int> c;
  map<P, int> s;
};

struct QUERY {
  int day;
  int type;
  QUERY(int d, int t) : day(d), type(t) {}
};

RandomNumberGenerator rnd;

struct SCHEDULE {
  vector<int> t;
  STATE &state;
  int schedule_score;
  SCHEDULE(STATE &st) : state(st) {
    // 初期化
    rep(i, state.D) {
      int type = rnd(state.Type) + 1;
      held(type);
    }
    init_score();
  }
  int current_day() { return t.size(); }
  int type(int day) { return t[day - 1]; }
  void held(int type) { t.push_back(type); }
  void init_score() {
    map<int, int> last_day;
    int score = 0;
    int m_day = t.size();
    for (int day = 1; day <= m_day; day++) {
      int type = t[day - 1];
      int ps = state.s[P(day, type)];
      int ng = 0;
      last_day[type] = day;
      for (int t = 1; t <= state.Type; t++) {
        ng += state.c[t] * (day - last_day[t]);
      }
      score = score + ps - ng;
    }
    schedule_score = score;
  }
  void modify(QUERY &query, int score) {
    t[query.day - 1] = query.type;
    schedule_score = score;
  }
  int score_if_modify(QUERY &query) {
    // TODO: 高速化
    map<int, int> last_day;
    int score = 0;
    int m_day = t.size();
    for (int day = 1; day <= m_day; day++) {
      int type = t[day - 1];

      if (day == query.day) {
        type = query.type;
      }

      int ps = state.s[P(day, type)];
      int ng = 0;
      last_day[type] = day;
      for (int t = 1; t <= state.Type; t++) {
        ng += state.c[t] * (day - last_day[t]);
      }
      score = score + ps - ng;
    }
    return score;
  }
};

// 状態の初期化
STATE init() {
  STATE state;
  int Type = 26;
  int D;
  cin >> D;
  state.Type = 26;
  state.D = D;
  rep(i, Type) {
    int c_i;
    cin >> c_i;
    state.c[i + 1] = c_i;
  }
  rep(d, D) {
    rep(t, Type) {
      int s_dt;
      cin >> s_dt;
      state.s[P(d + 1, t + 1)] = s_dt;
    }
  }
  return state;
}

QUERY generate_query(STATE &state) {
  int day = rnd(state.D) + 1;
  int type = rnd(state.Type) + 1;
  return QUERY(day, type);
}

int main() {
  STATE state = init();
  SCHEDULE schedule(state);

  while (true) {
    if ((double)clock() / CLOCKS_PER_SEC > TIME_LIMIT)
      break;

    int pre_score = schedule.schedule_score;
    QUERY query = generate_query(state);
    int new_score = schedule.score_if_modify(query);
    if (new_score > pre_score) {
      schedule.modify(query, new_score);
    }
  }

  rep(i, state.D) { cout << schedule.t[i] << endl; }
  return 0;
}