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

#include <algorithm>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <set>
#include <vector>
using namespace std;
typedef long long ll;
typedef long double ldb;
const int MAXM = 4e2 + 5;
const int MAXN = 26 + 5;
const int MAXT = 2e7 + 5;
const int inf = 0x3f3f3f3f;
const ll linf = 0x3f3f3f3f3f3f3f3f;

int n = 26, m;
int c[MAXN];
int a[MAXM][MAXN];

int p[MAXM], beg[MAXM];
set<int> idx[MAXN];
int ans;

void init(void) {
  for (int i = 1; i <= n; ++i) {
    idx[i].clear();
    idx[i].insert(0);
    idx[i].insert(m + 1);
  }

  for (int k = 1; k <= m; ++k)
    idx[p[k]].insert(k);
}

struct Oper {
  int pos, x;
} oper[MAXT];
int tcnt = 0;

int recalc(register int pos, register int x) {
  register int old = p[pos];
  if (old == x)
    return ans;

  oper[++tcnt] = (Oper){pos, x};

  register int res = ans;

  idx[old].erase(pos);

  set<int>::iterator it = idx[old].upper_bound(pos);
  register int nxt = *it;
  register int lst = *(--it);

  res -= (pos - lst) * c[old] * (nxt - pos) + a[pos][old];

  it = idx[x].upper_bound(pos);
  nxt = *it;
  lst = *(--it);

  res += (pos - lst) * c[x] * (nxt - pos) + a[pos][x];

  idx[x].insert(pos);

  p[pos] = x;
  return res;
}

int main(void) {
  srand(time(0));

  scanf("%d", &m);
  for (int i = 1; i <= n; ++i)
    scanf("%d", &c[i]);
  for (int i = 1; i <= m; ++i)
    for (int j = 1; j <= n; ++j)
      scanf("%d", &a[i][j]);

  static int lst[MAXN];

  ans = 0;
  for (int k = 1; k <= m; ++k) {
    int mx = -inf;
    int mxi = -1;
    for (int i = 1; i <= n; ++i) {
      int res = a[k][i];
      for (int j = 1; j <= n; ++j)
        if (j != i)
          res -= c[j] * (k - lst[j]);

      if (mxi == -1 || mx < res)
        mxi = i, mx = res;
    }
    lst[mxi] = k;

    ans += mx;
    p[k] = mxi;
  }

  for (int i = 1; i <= m; ++i)
    beg[i] = p[i];

  init();

  static int pp[MAXM];
  static int qq[MAXM];

  for (int i = 1; i <= m; ++i)
    pp[i] = i;
  for (int i = 1; i <= n; ++i)
    qq[i] = i;

  const ldb Delta = 0.97;
  ldb Temp = 10000;

  int mxans = ans, mxi = 0;

  int T = 400;
  while (T--) {
    random_shuffle(pp + 1, pp + m + 1);

    for (int i = 1; i <= m; ++i) {
      random_shuffle(qq + 1, qq + n + 1);
      for (int j = 1; j <= n; ++j) {
        int pos = pp[i];
        int x = qq[j];

        int old = p[pos];
        int res = recalc(pos, x);

        if (res > ans || (ans - res) / Temp > (ldb)rand() / RAND_MAX) {
          if (res > mxans)
            mxans = res, mxi = tcnt;
          ans = res;
        } else
          recalc(pos, old);

        Temp *= Delta;
      }
    }
  }

  for (int i = 1; i <= m; ++i)
    p[i] = beg[i];
  for (int i = 1; i <= mxi; ++i)
    p[oper[i].pos] = oper[i].x;

  for (int i = 1; i <= m; ++i)
    printf("%d\\n", p[i]);
  return 0;
}

Error: TLE

Fixed submission:

#include <algorithm>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <set>
#include <vector>
using namespace std;
typedef long long ll;
typedef long double ldb;
const int MAXM = 4e2 + 5;
const int MAXN = 26 + 5;
const int MAXT = 2e7 + 5;
const int inf = 0x3f3f3f3f;
const ll linf = 0x3f3f3f3f3f3f3f3f;

int n = 26, m;
int c[MAXN];
int a[MAXM][MAXN];

int p[MAXM], beg[MAXM];
set<int> idx[MAXN];
int ans;

void init(void) {
  for (int i = 1; i <= n; ++i) {
    idx[i].clear();
    idx[i].insert(0);
    idx[i].insert(m + 1);
  }

  for (int k = 1; k <= m; ++k)
    idx[p[k]].insert(k);
}

struct Oper {
  int pos, x;
} oper[MAXT];
int tcnt = 0;

int recalc(register int pos, register int x) {
  register int old = p[pos];
  if (old == x)
    return ans;

  oper[++tcnt] = (Oper){pos, x};

  register int res = ans;

  idx[old].erase(pos);

  set<int>::iterator it = idx[old].upper_bound(pos);
  register int nxt = *it;
  register int lst = *(--it);

  res -= (pos - lst) * c[old] * (nxt - pos) + a[pos][old];

  it = idx[x].upper_bound(pos);
  nxt = *it;
  lst = *(--it);

  res += (pos - lst) * c[x] * (nxt - pos) + a[pos][x];

  idx[x].insert(pos);

  p[pos] = x;
  return res;
}

int main(void) {
  srand(time(0));

  scanf("%d", &m);
  for (int i = 1; i <= n; ++i)
    scanf("%d", &c[i]);
  for (int i = 1; i <= m; ++i)
    for (int j = 1; j <= n; ++j)
      scanf("%d", &a[i][j]);

  static int lst[MAXN];

  ans = 0;
  for (int k = 1; k <= m; ++k) {
    int mx = -inf;
    int mxi = -1;
    for (int i = 1; i <= n; ++i) {
      int res = a[k][i];
      for (int j = 1; j <= n; ++j)
        if (j != i)
          res -= c[j] * (k - lst[j]);

      if (mxi == -1 || mx < res)
        mxi = i, mx = res;
    }
    lst[mxi] = k;

    ans += mx;
    p[k] = mxi;
  }

  for (int i = 1; i <= m; ++i)
    beg[i] = p[i];

  init();

  static int pp[MAXM];
  static int qq[MAXM];

  for (int i = 1; i <= m; ++i)
    pp[i] = i;
  for (int i = 1; i <= n; ++i)
    qq[i] = i;

  const ldb Delta = 0.97;
  ldb Temp = 10000000;

  int mxans = ans, mxi = 0;

  int T = 700;
  while (T--) {
    random_shuffle(pp + 1, pp + m + 1);

    for (int i = 1; i <= m; ++i) {
      random_shuffle(qq + 1, qq + n + 1);
      for (int j = 1; j <= n; ++j) {
        int pos = pp[i];
        int x = qq[j];

        int old = p[pos];
        int res = recalc(pos, x);

        if (res > ans || (ans - res) / Temp > (ldb)rand() / RAND_MAX) {
          if (res > mxans)
            mxans = res, mxi = tcnt;
          ans = res;
        } else
          recalc(pos, old);

        Temp *= Delta;
      }
    }
  }

  for (int i = 1; i <= m; ++i)
    p[i] = beg[i];
  for (int i = 1; i <= mxi; ++i)
    p[oper[i].pos] = oper[i].x;

  for (int i = 1; i <= m; ++i)
    printf("%d\\n", p[i]);
  return 0;
}