Problem p02964 (C++)

Buggy submission (status: Time Limit Exceeded):
#include "bits/stdc++.h"

#define REP(i, x, y) for (int i = (x); i < (y); i++)
#define RREP(i, x, y) for (int i = (y)-1; i >= (x); i--)
#define all(x) (x).begin(), (x).end()
#define int long long

using namespace std;

// conversion
inline int toInt(string s) {
  int v;
  istringstream sin(s);
  sin >> v;
  return v;
}
template <class T> inline string toString(T x) {
  ostringstream sout;
  sout << x;
  return sout.str();
}

#ifdef LOCAL
#define eprintf(...) fprintf(stderr, __VA_ARGS__)
#define dump(x) cerr << #x << " = " << (x) << endl
#define debug(x)                                                               \
  cerr << #x << " = " << (x) << " (L" << __LINE__ << ")"                       \
       << " " << __FILE__ << endl
#else
#define eprintf(...) 42
#define dump(x) 42
#define debug(x) 42
#endif

typedef long long ll;

const ll MOD = 1e9 + 7;

struct Queue {
  Queue() {}
  Queue(int N) : s(vector<int>(N)), last(0) {}
  vector<int> s;
  int last;
};

void simulate(const int N, ll currentIndex, const ll limit, vector<int> &A,
              Queue &queue) {
  unordered_map<int, int> positions; // <number, position>
  unordered_map<int, int> numbers;   // <position, number>

  while (currentIndex < limit) {
    const int a = A[currentIndex % N];
    //        cout << "a:" << a << ", queue.last:" << queue.last << '\n';
    if (positions.find(a) != positions.end() && numbers[positions[a]] == a &&
        positions[a] < queue.last) {
      queue.last = positions[a];
    } else {
      queue.s[queue.last] = a;
      positions[a] = queue.last;
      numbers[queue.last] = a;
      queue.last++;
    }
    currentIndex++;
    //        REP(i,0,queue.last) {
    //            cout << queue.s[i] << " ";
    //        }
    //        cout << "\n";
  }
}

vector<int> generateDistanceListToNextIndex(int N, vector<int> &A) {
  vector<int> list(N, 0);
  unordered_map<int, int> previousIndex; // <number, index>

  REP(i, 0, 2 * N) {
    //        debug(i);
    const int currentNumber = A[i % N];
    if (previousIndex.find(currentNumber) != previousIndex.end() &&
        list[previousIndex[currentNumber] % N] == 0) {
      list[previousIndex[currentNumber] % N] = i - previousIndex[currentNumber];
      //            debug(previousIndex[currentNumber]);
      assert(list[previousIndex[currentNumber] % N] > 0);
    }
    previousIndex[currentNumber] = i;
  }

  REP(i, 0, N) {
    if (list[i] == 0)
      list[i] = N;
  }

  return list;
}

void solve(int N, ll K, vector<int> &A) {
  Queue queue(N);

  ll currentIndex = 0;
  const ll limit = N * K;

  if (K > 1) {
    const auto distanceListToNextIndex = generateDistanceListToNextIndex(N, A);

    ll cycle = 0;
    vector<ll> visitedWhen(N, -1);

    const ll preLimit = N * (K - 1);
    int count = 0;
    while (currentIndex < preLimit) {
      if (visitedWhen[currentIndex % N] != -1) {
        cycle = currentIndex - visitedWhen[currentIndex % N];
        break;
      }
      visitedWhen[currentIndex % N] = currentIndex;
      currentIndex += distanceListToNextIndex[currentIndex % N] + 1;
      count++;
      //            assert(currentIndex >= 0);
    }

    if (cycle != 0 && currentIndex < preLimit) {
      currentIndex += (N * K - currentIndex) / cycle * cycle;
    }
  }

  //    assert(limit - currentIndex <= 2 * N);

  simulate(N, currentIndex, limit, A, queue);

  stringstream ss;
  REP(i, 0, queue.last - 1) { ss << queue.s[i] << " "; }
  if (queue.last != 0)
    ss << queue.s[queue.last - 1];
  cout << ss.str() << '\n';
  return;
}

signed main() {
  ll N, K;
  cin >> N >> K;

  vector<int> A(N);
  REP(i, 0, N) cin >> A[i];

  solve(N, K, A);

  return 0;
}


Fixed submission:
#include "bits/stdc++.h"

#define REP(i, x, y) for (int i = (x); i < (y); i++)
#define RREP(i, x, y) for (int i = (y)-1; i >= (x); i--)
#define all(x) (x).begin(), (x).end()
#define int long long

using namespace std;

// conversion
inline int toInt(string s) {
  int v;
  istringstream sin(s);
  sin >> v;
  return v;
}
template <class T> inline string toString(T x) {
  ostringstream sout;
  sout << x;
  return sout.str();
}

#ifdef LOCAL
#define eprintf(...) fprintf(stderr, __VA_ARGS__)
#define dump(x) cerr << #x << " = " << (x) << endl
#define debug(x)                                                               \
  cerr << #x << " = " << (x) << " (L" << __LINE__ << ")"                       \
       << " " << __FILE__ << endl
#else
#define eprintf(...) 42
#define dump(x) 42
#define debug(x) 42
#endif

typedef long long ll;

const ll MOD = 1e9 + 7;

struct Queue {
  Queue() {}
  Queue(int N) : s(vector<int>(N)), last(0) {}
  vector<int> s;
  int last;
};

void simulate(const int N, ll currentIndex, const ll limit, vector<int> &A,
              Queue &queue) {
  unordered_map<int, int> positions; // <number, position>
  unordered_map<int, int> numbers;   // <position, number>

  while (currentIndex < limit) {
    const int a = A[currentIndex % N];
    //        cout << "a:" << a << ", queue.last:" << queue.last << '\n';
    if (positions.find(a) != positions.end() && numbers[positions[a]] == a &&
        positions[a] < queue.last) {
      queue.last = positions[a];
    } else {
      queue.s[queue.last] = a;
      positions[a] = queue.last;
      numbers[queue.last] = a;
      queue.last++;
    }
    currentIndex++;
    //        REP(i,0,queue.last) {
    //            cout << queue.s[i] << " ";
    //        }
    //        cout << "\n";
  }
}

vector<int> generateDistanceListToNextIndex(int N, vector<int> &A) {
  vector<int> list(N, 0);
  unordered_map<int, int> previousIndex; // <number, index>

  REP(i, 0, 2 * N) {
    //        debug(i);
    const int currentNumber = A[i % N];
    if (previousIndex.find(currentNumber) != previousIndex.end() &&
        list[previousIndex[currentNumber] % N] == 0) {
      list[previousIndex[currentNumber] % N] = i - previousIndex[currentNumber];
      //            debug(previousIndex[currentNumber]);
      assert(list[previousIndex[currentNumber] % N] > 0);
    }
    previousIndex[currentNumber] = i;
  }

  REP(i, 0, N) {
    if (list[i] == 0)
      list[i] = N;
  }

  return list;
}

void solve(int N, ll K, vector<int> &A) {
  Queue queue(N);

  ll currentIndex = 0;
  const ll limit = N * K;

  if (K > 1) {
    const auto distanceListToNextIndex = generateDistanceListToNextIndex(N, A);

    ll cycle = 0;
    vector<ll> visitedWhen(N, -1);

    const ll preLimit = N * (K - 1);
    int count = 0;
    while (currentIndex < preLimit) {
      if (visitedWhen[currentIndex % N] != -1) {
        cycle = currentIndex - visitedWhen[currentIndex % N];
        break;
      }
      visitedWhen[currentIndex % N] = currentIndex;
      currentIndex += distanceListToNextIndex[currentIndex % N] + 1;
      count++;
      //            assert(currentIndex >= 0);
    }

    if (cycle != 0 && currentIndex < preLimit) {
      currentIndex += (N * K - currentIndex) / cycle * cycle;
    }

    while (currentIndex < preLimit) {
      currentIndex += distanceListToNextIndex[currentIndex % N] + 1;
      count++;
    }
  }

  //    assert(limit - currentIndex <= 2 * N);

  simulate(N, currentIndex, limit, A, queue);

  stringstream ss;
  REP(i, 0, queue.last - 1) { ss << queue.s[i] << " "; }
  if (queue.last != 0)
    ss << queue.s[queue.last - 1];
  cout << ss.str() << '\n';
  return;
}

signed main() {
  ll N, K;
  cin >> N >> K;

  vector<int> A(N);
  REP(i, 0, N) cin >> A[i];

  solve(N, K, A);

  return 0;
}