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

#define DEBUG

#include <fstream>
#include <iostream>

#include <bits/stdc++.h>
#include <cstdio>
#include <sys/time.h>
#include <sys/timeb.h>
#include <time.h>

using namespace std;
#define ll long long
#define uint unsigned int
#define ulong unsigned long long int
#define Vec vector
#define V2 vector<vector<ll>>

class Xor128 {
private:
  uint x, y, z, w;

public:
  void init(uint seed = 0) {
    x = 123456789;
    y = 362436069;
    z = 521288629;
    w = 88675123;
    z ^= seed;
  }
  Xor128() { init(); }
  Xor128(uint seed) { init(seed); }
  uint Next() {
    uint t = x ^ (x << 11);
    x = y;
    y = z;
    z = w;
    return w = (w ^ (w >> 19)) ^ (t ^ (t >> 8));
  }
  int Next(int ul) { return ul == 0 ? 0 : NextI(0, ul - 1); }
  int NextI(int from, int to) {
    int mod = to - from + 1;
    int ret = (int)(Next() % mod);
    return ret + from;
  }

  double NextD() { return (Next() & 1048575) / 1048575.0; }
};

class Timer {
public:
  Timer() { cycle_per_sec = (ulong)2.7e9; }
  void Start() { begin_cycle = getCycle(); }
  double getTime() {
    return (double)(getCycle() - begin_cycle) / cycle_per_sec;
  }
  int elapsedMilliseconds() { return (int)(1000 * getTime()); }

  ulong getCycle() {
    uint low, high;
    __asm__ volatile("rdtsc" : "=a"(low), "=d"(high));
    return ((ulong)low) | ((ulong)high << 32);
  }

private:
  ulong begin_cycle;
  ulong cycle_per_sec;
};

Timer T;
ll Now() { return (ll)T.elapsedMilliseconds(); }

const double Eps = 1e-9;
inline bool InRange(int t, int l, int r) { return l <= t && t < r; }
void Swap(int &a, int &b) {
  int t = a;
  a = b;
  b = t;
}

// SA template

Xor128 lottery(25252525);
const double Csa = 1200;
// double C = 1200;

bool SAgain(double score, double prev, long now, long start,
            long limitDuration) {
  if (score > prev)
    return true;
  double ratio = -(prev - score) / prev;
  double remainingTime = (now - start) / (double)limitDuration;
  if (remainingTime > 1.0)
    return false;
  remainingTime = 1 - remainingTime;

  double acProb = exp(Csa * ratio / remainingTime);

  return (lottery.NextD() + Eps) < acProb;
}
bool MCgain(double score, double prev, long now, long start,
            long limitDuration) {
  if (score < prev)
    return true;
  return false;
}

template <typename T> bool InRange(T t, T l, T r) { return l <= t && t < r; }
const int Inf = (int)1e9;

int D;
Vec<ll> C;
V2 S;

void OutputAns(Vec<int> &a) {
  for (int i = 0; i < D; i++) {
    printf("%d\\n", a[i] + 1);
  }
}

ll calcNaive(Vec<int> &a) {
  Vec<int> last(26);
  for (int i = 0; i < 26; i++)
    last[i] = -1;
  ll ret = 0;
  for (int i = 0; i < D; i++) {
    ret += S[i][a[i]];
    last[a[i]] = i;
    for (int j = 0; j < 26; j++) {
      ret -= C[j] * (i - last[j]);
    }
  }
  return ret;
}
ll calcLine(Vec<int> &a) {
  Vec<int> last(26);
  for (int i = 0; i < 26; i++)
    last[i] = -1;
  ll ret = 0;
  for (int i = 0; i < D; i++) {
    ret += S[i][a[i]];
    ll d = (i - last[a[i]]) - 1;
    ret -= d * (d + 1) / 2 * C[a[i]];
    last[a[i]] = i;
  }

  for (int i = 0; i < 26; i++) {
    ll d = (D - last[i]) - 1;
    ret -= d * (d + 1) / 2 * C[i];
  }
  return ret;
}

void debug1() {
  Vec<int> a{1, 17, 13, 14, 13};
  for (int i = 0; i < a.size(); i++)
    a[i]--;
  cerr << calcNaive(a) << endl;
  cerr << calcLine(a) << endl;
}

ll maxSc = 0;
Vec<int> maxAr;
void initMax() {
  maxAr.resize(D);
  maxSc = -(ll)1e9;
}

bool UpdateMax(Vec<int> &a, ll sc, bool recalc = false) {

  if (recalc)
    sc = calcNaive(a);
  if (maxSc >= sc)
    return false;
  // cerr << sc << "," << maxSc << endl;
  maxSc = sc;
  for (int i = 0; i < D; i++)
    maxAr[i] = a[i];
  return true;
}

void SA(Vec<int> &a, ll tl, int seed = 2525) {

  ll tstart = Now();
  Xor128 rnd(seed);
  ll sc = calcLine(a);
  UpdateMax(a, sc);

  ll ma = sc;
  ll cnt = 0;
  ll timeLimitDuration = tl - tstart;
  ll t1 = Now();

  Vec<int> b(D);
  for (int i = 0; i < D; i++) {
    b[i] = a[i];
  }

  Vec<int> last(2, -1);

  while (true) {
    cnt++;
    if (cnt % 1000 == 0 && (t1 = Now()) - tstart > timeLimitDuration)
      break;
    int bw = rnd.Next(2);
    if (bw == 0) {
      /*
      int rp = rnd.Next(D * 26);
      int idx = rp / 26;
      int val = rp % 26;
      */
      int idx = rnd.Next(D);
      int val = rnd.Next(26);
      int fr = b[idx];

      if (fr == val)
        continue;
      b[idx] = val;
      /*
      int lose = 0;
      last[0] = last[1] = -1;
      for(int i=0;i<D;i++){
              if(b[i] != val && b[i] != fr) continue;
              int iid = b[i] == val ? 0 : 1;
              lose += S[i][iid];
              int d = (i - last[iid]) - 1;
              lose -= d * (d + 1) / 2 * C[iid];
              last[iid] = i;
      }
      for(int i=0;i<2;i++){
              int d = (D - last[i]) - 1;
              lose -= d * (d + 1) / 2 * C[i];
      }

      int gain = 0;
      b[idx] = val;
      last[0] = last[1] = -1;
      for(int i=0;i<D;i++){
              if(b[i] != val && b[i] != fr) continue;
              int iid = b[i] == val ? 0 : 1;
              gain += S[i][iid];
              int d = (i - last[iid]) - 1;
              gain -= d * (d + 1) / 2 * C[iid];
              last[iid] = i;
      }
      for(int i=0;i<2;i++){
              int d = (D - last[i]) - 1;
              gain -= d * (d + 1) / 2 * C[i];
      }
      printf("%d %d\\n", sc + gain - lose, calcLine(b));
      assert(sc + gain - lose == calcLine(b));
      */
      ll nsc = calcLine(b);
      if (SAgain(nsc, sc, t1, tstart, timeLimitDuration)) {
        // sc = sc + gain - lose;
        sc = nsc;
        UpdateMax(b, sc);
      } else {
        b[idx] = fr;
      }

    } else {
      /*
      int rp = rnd.Next(D * 10);
      int left = rp / 10;
      int right = min(left + (rp % 10), D - 1);
      */
      int left = rnd.Next(D);
      int right = min(rnd.Next(10) + left, D - 1);

      if (left == right)
        continue;
      Swap(b[left], b[right]);
      ll nsc = calcLine(b);
      if (SAgain(nsc, sc, t1, tstart, timeLimitDuration)) {
        // sc = sc + gain - lose;
        sc = nsc;
        UpdateMax(b, sc);
      } else {
        Swap(b[left], b[right]);
      }
    }
  }

  // cerr << "cnt: " << cnt << endl;
}

void randomSample(Vec<int> &a) {
  Xor128 rnd(2525);
  for (int i = 0; i < D; i++)
    a[i] = rnd.Next(26);
}
void greedyS(Vec<int> &a) {
  for (int i = 0; i < D; i++) {
    int ma = -1;
    int idx = -1;
    for (int j = 0; j < 26; j++) {
      if (ma < S[i][j]) {
        ma = S[i][j];
        idx = j;
      }
    }
    a[i] = idx;
  }
}
void greedyScore(Vec<int> &a) {
  Vec<int> prev(26, 0);

  for (int i = 0; i < D; i++) {
    int ma = -1;
    int idx = -1;
    for (int j = 0; j < 26; j++) {
      if (ma < S[i][j] + (i + 1 - prev[j]) * C[j]) {
        ma = S[i][j] + (i + 1 - prev[j]) * C[j];
        idx = j;
      }
    }
    a[i] = idx;
    prev[idx] = i + 1;
  }
}

void Solve() {
  // debug1();
  initMax();
  Vec<int> a(D);
  // randomSample(a);
  // greedtS(a);
  greedyScore(a);

  int tl = 2150;
  SA(a, tl, 2525);

  // cerr << maxSc << endl;
  // cerr << calcNaive(maxAr) << endl;
  OutputAns(maxAr);
}

int main(int argc, char *argv[]) {
  // C = stod(argv[1]);
  T.Start();
  cin >> D;
  C.resize(26);
  for (int i = 0; i < 26; i++)
    cin >> C[i];
  S.resize(D);
  for (int i = 0; i < D; i++)
    S[i].resize(26);
  for (int i = 0; i < D; i++) {
    for (int j = 0; j < 26; j++) {
      cin >> S[i][j];
    }
  }

  Solve();

  /*	for(int i=0;i<md.size();i++){
                  cerr << "sc: " << md[i] << " at: " << msc[i] << endl;
          }
  */
  /*
          ofstream fout("score.csv");
          fout << "C,score" << endl;
          fout << C << "," << maxSc << endl;
          fout.close();
  */
  return 0;
}

Error: TLE

Fixed submission:

#define DEBUG

#include <fstream>
#include <iostream>

#include <bits/stdc++.h>
#include <cstdio>
#include <sys/time.h>
#include <sys/timeb.h>
#include <time.h>

using namespace std;
#define ll long long
#define uint unsigned int
#define ulong unsigned long long int
#define Vec vector
#define V2 vector<vector<ll>>

class Xor128 {
private:
  uint x, y, z, w;

public:
  void init(uint seed = 0) {
    x = 123456789;
    y = 362436069;
    z = 521288629;
    w = 88675123;
    z ^= seed;
  }
  Xor128() { init(); }
  Xor128(uint seed) { init(seed); }
  uint Next() {
    uint t = x ^ (x << 11);
    x = y;
    y = z;
    z = w;
    return w = (w ^ (w >> 19)) ^ (t ^ (t >> 8));
  }
  int Next(int ul) { return ul == 0 ? 0 : NextI(0, ul - 1); }
  int NextI(int from, int to) {
    int mod = to - from + 1;
    int ret = (int)(Next() % mod);
    return ret + from;
  }

  double NextD() { return (Next() & 1048575) / 1048575.0; }
};

class Timer {
public:
  Timer() { cycle_per_sec = (ulong)2.7e9; }
  void Start() { begin_cycle = getCycle(); }
  double getTime() {
    return (double)(getCycle() - begin_cycle) / cycle_per_sec;
  }
  int elapsedMilliseconds() { return (int)(1000 * getTime()); }

  ulong getCycle() {
    uint low, high;
    __asm__ volatile("rdtsc" : "=a"(low), "=d"(high));
    return ((ulong)low) | ((ulong)high << 32);
  }

private:
  ulong begin_cycle;
  ulong cycle_per_sec;
};

Timer T;
ll Now() { return (ll)T.elapsedMilliseconds(); }

const double Eps = 1e-9;
inline bool InRange(int t, int l, int r) { return l <= t && t < r; }
void Swap(int &a, int &b) {
  int t = a;
  a = b;
  b = t;
}

// SA template

Xor128 lottery(25252525);
const double Csa = 1200;
// double C = 1200;

bool SAgain(double score, double prev, long now, long start,
            long limitDuration) {
  if (score > prev)
    return true;
  double ratio = -(prev - score) / prev;
  double remainingTime = (now - start) / (double)limitDuration;
  if (remainingTime > 1.0)
    return false;
  remainingTime = 1 - remainingTime;

  double acProb = exp(Csa * ratio / remainingTime);

  return (lottery.NextD() + Eps) < acProb;
}
bool MCgain(double score, double prev, long now, long start,
            long limitDuration) {
  if (score < prev)
    return true;
  return false;
}

template <typename T> bool InRange(T t, T l, T r) { return l <= t && t < r; }
const int Inf = (int)1e9;

int D;
Vec<ll> C;
V2 S;

void OutputAns(Vec<int> &a) {
  for (int i = 0; i < D; i++) {
    printf("%d\\n", a[i] + 1);
  }
}

ll calcNaive(Vec<int> &a) {
  Vec<int> last(26);
  for (int i = 0; i < 26; i++)
    last[i] = -1;
  ll ret = 0;
  for (int i = 0; i < D; i++) {
    ret += S[i][a[i]];
    last[a[i]] = i;
    for (int j = 0; j < 26; j++) {
      ret -= C[j] * (i - last[j]);
    }
  }
  return ret;
}
ll calcLine(Vec<int> &a) {
  Vec<int> last(26);
  for (int i = 0; i < 26; i++)
    last[i] = -1;
  ll ret = 0;
  for (int i = 0; i < D; i++) {
    ret += S[i][a[i]];
    ll d = (i - last[a[i]]) - 1;
    ret -= d * (d + 1) / 2 * C[a[i]];
    last[a[i]] = i;
  }

  for (int i = 0; i < 26; i++) {
    ll d = (D - last[i]) - 1;
    ret -= d * (d + 1) / 2 * C[i];
  }
  return ret;
}

void debug1() {
  Vec<int> a{1, 17, 13, 14, 13};
  for (int i = 0; i < a.size(); i++)
    a[i]--;
  cerr << calcNaive(a) << endl;
  cerr << calcLine(a) << endl;
}

ll maxSc = 0;
Vec<int> maxAr;
void initMax() {
  maxAr.resize(D);
  maxSc = -(ll)1e9;
}

bool UpdateMax(Vec<int> &a, ll sc, bool recalc = false) {

  if (recalc)
    sc = calcNaive(a);
  if (maxSc >= sc)
    return false;
  // cerr << sc << "," << maxSc << endl;
  maxSc = sc;
  for (int i = 0; i < D; i++)
    maxAr[i] = a[i];
  return true;
}

void SA(Vec<int> &a, ll tl, int seed = 2525) {

  ll tstart = Now();
  Xor128 rnd(seed);
  ll sc = calcLine(a);
  UpdateMax(a, sc);

  ll ma = sc;
  ll cnt = 0;
  ll timeLimitDuration = tl - tstart;
  ll t1 = Now();

  Vec<int> b(D);
  for (int i = 0; i < D; i++) {
    b[i] = a[i];
  }

  Vec<int> last(2, -1);

  while (true) {
    cnt++;
    if (cnt % 1000 == 0 && (t1 = Now()) - tstart > timeLimitDuration)
      break;
    int bw = rnd.Next(2);
    if (bw == 0) {
      /*
      int rp = rnd.Next(D * 26);
      int idx = rp / 26;
      int val = rp % 26;
      */
      int idx = rnd.Next(D);
      int val = rnd.Next(26);
      int fr = b[idx];

      if (fr == val)
        continue;
      b[idx] = val;
      /*
      int lose = 0;
      last[0] = last[1] = -1;
      for(int i=0;i<D;i++){
              if(b[i] != val && b[i] != fr) continue;
              int iid = b[i] == val ? 0 : 1;
              lose += S[i][iid];
              int d = (i - last[iid]) - 1;
              lose -= d * (d + 1) / 2 * C[iid];
              last[iid] = i;
      }
      for(int i=0;i<2;i++){
              int d = (D - last[i]) - 1;
              lose -= d * (d + 1) / 2 * C[i];
      }

      int gain = 0;
      b[idx] = val;
      last[0] = last[1] = -1;
      for(int i=0;i<D;i++){
              if(b[i] != val && b[i] != fr) continue;
              int iid = b[i] == val ? 0 : 1;
              gain += S[i][iid];
              int d = (i - last[iid]) - 1;
              gain -= d * (d + 1) / 2 * C[iid];
              last[iid] = i;
      }
      for(int i=0;i<2;i++){
              int d = (D - last[i]) - 1;
              gain -= d * (d + 1) / 2 * C[i];
      }
      printf("%d %d\\n", sc + gain - lose, calcLine(b));
      assert(sc + gain - lose == calcLine(b));
      */
      ll nsc = calcLine(b);
      if (SAgain(nsc, sc, t1, tstart, timeLimitDuration)) {
        // sc = sc + gain - lose;
        sc = nsc;
        UpdateMax(b, sc);
      } else {
        b[idx] = fr;
      }

    } else {
      /*
      int rp = rnd.Next(D * 10);
      int left = rp / 10;
      int right = min(left + (rp % 10), D - 1);
      */
      int left = rnd.Next(D);
      int right = min(rnd.Next(10) + left, D - 1);

      if (left == right)
        continue;
      Swap(b[left], b[right]);
      ll nsc = calcLine(b);
      if (SAgain(nsc, sc, t1, tstart, timeLimitDuration)) {
        // sc = sc + gain - lose;
        sc = nsc;
        UpdateMax(b, sc);
      } else {
        Swap(b[left], b[right]);
      }
    }
  }

  // cerr << "cnt: " << cnt << endl;
}

void randomSample(Vec<int> &a) {
  Xor128 rnd(2525);
  for (int i = 0; i < D; i++)
    a[i] = rnd.Next(26);
}
void greedyS(Vec<int> &a) {
  for (int i = 0; i < D; i++) {
    int ma = -1;
    int idx = -1;
    for (int j = 0; j < 26; j++) {
      if (ma < S[i][j]) {
        ma = S[i][j];
        idx = j;
      }
    }
    a[i] = idx;
  }
}
void greedyScore(Vec<int> &a) {
  Vec<int> prev(26, 0);

  for (int i = 0; i < D; i++) {
    int ma = -1;
    int idx = -1;
    for (int j = 0; j < 26; j++) {
      if (ma < S[i][j] + (i + 1 - prev[j]) * C[j]) {
        ma = S[i][j] + (i + 1 - prev[j]) * C[j];
        idx = j;
      }
    }
    a[i] = idx;
    prev[idx] = i + 1;
  }
}

void Solve() {
  // debug1();
  initMax();
  Vec<int> a(D);
  // randomSample(a);
  // greedtS(a);
  greedyScore(a);

  int tl = 19500;
  SA(a, tl, 2525);

  // cerr << maxSc << endl;
  // cerr << calcNaive(maxAr) << endl;
  OutputAns(maxAr);
}

int main(int argc, char *argv[]) {
  // C = stod(argv[1]);
  T.Start();
  cin >> D;
  C.resize(26);
  for (int i = 0; i < 26; i++)
    cin >> C[i];
  S.resize(D);
  for (int i = 0; i < D; i++)
    S[i].resize(26);
  for (int i = 0; i < D; i++) {
    for (int j = 0; j < 26; j++) {
      cin >> S[i][j];
    }
  }

  Solve();

  /*	for(int i=0;i<md.size();i++){
                  cerr << "sc: " << md[i] << " at: " << msc[i] << endl;
          }
  */
  /*
          ofstream fout("score.csv");
          fout << "C,score" << endl;
          fout << C << "," << maxSc << endl;
          fout.close();
  */
  return 0;
}