Problem p03747 (C++)

Buggy submission (status: Runtime Error):
#include <algorithm>
#include <bitset>
#include <cassert>
#include <cmath>
#include <complex>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <fstream>
#include <iostream>
#include <map>
#include <memory>
#include <numeric>
#include <queue>
#include <set>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <utility>
#include <vector>

using namespace std;

#define ws ws_____________________
#define y1 y1_____________________
#define y0 y0_____________________
#define left left_________________
#define right right_______________
#define next next_________________
#define prev prev_________________
#define hash hash_________________

#define pb push_back
#define fst first
#define snd second
#define mp make_pair
#define sz(C) ((int)(C).size())
#define forn(i, n) for (int i = 0; i < int(n); ++i)
#define ford(i, n) for (int i = int(n) - 1; i >= 0; --i)
#define all(C) begin(C), end(C)

typedef long long ll;
typedef unsigned long long ull;
typedef unsigned int uint;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef vector<ll> vll;
typedef vector<int> vi;
typedef vector<vi> vvi;
typedef vector<pii> vii;
typedef long double ld;
typedef complex<double> cd;

#define FILE_NAME "a"

struct ant {
  ll x;
  int w;
  int id;

  void read(int ii) {
    id = ii;
    cin >> x >> w;
    --w;
  }

  bool operator<(const ant &other) const { return x < other.x; }
};

const int MAXN = 2e5 + 10;

int N;
ll L, T;
vector<ant> ants;

bool read() {
  cin >> N >> L >> T;
  ants.resize(N);
  forn(i, N) { ants[i].read(i); }
  return 1;
}

ll coord(ll x) {
  x %= L;
  if (x < 0) {
    x += L;
  }
  return x;
}

const ll INF = 1e16;

ll mult(ll x, ll y) {
  if (!y) {
    return 0;
  }
  if (x >= INF / y) {
    return INF;
  }
  return min(INF, x * y);
}

ll final[MAXN];

void make_ans(bool is_left = true) {
  vll finals;
  forn(i, N) {
    ll pos = ants[i].x + (ants[i].w ? -1 : +1) * T;
    finals.pb(coord(pos));
  }

  sort(all(finals));
  int id0 = -1;
  srand(3);
  forn(i, N) {
    if (finals[i] == final[ants[0].id]) {
      id0 = i;
      if (!is_left) {
        assert((i + 1 < N && finals[i + 1] == final[ants[0].id]));
        ++id0;
      }
      break;
    }
  }
  assert(id0 != -1);
  for (int i = 1; i < N; ++i) {
    final[ants[i].id] = finals[(id0 + i) % N];
  }
}

void solve1() {
  if (ants[0].w == 1) {
    final[ants[0].id] = coord(ants[0].x - T);
    make_ans();
    return;
  }

  assert(!ants[0].x);

  vll opposite;
  vll my;
  for (int i = 1; i < N; ++i) {
    if (ants[i].w == 1) {
      opposite.pb(ants[i].x);
    } else {
      my.pb(ants[i].x);
    }
  }

  // forn(i, N) {
  // 	printf("x=%lld w=%d\n", ants[i].x, ants[i].w);
  // }

  if (opposite.empty() || opposite.front() - ants[0].x >= 2 * T) {
    final[ants[0].id] = coord(ants[0].x + T);
    make_ans();
    return;
  }

  // printf("opposite:\n");
  // for (int x : opposite) {
  // 	printf("%d ", x);
  // }
  // puts("");
  // printf("my:\n");
  // for (int x : my) {
  // 	printf("%d ", x);
  // }
  // puts("");

  ll nT = 2 * T;
  ll dist = opposite.front() - ants[0].x;
  for (auto &x : opposite) {
    x -= dist;
    assert(x >= 0);
  }
  nT -= dist;

  // printf("nT=%d\n", nT);

  vll go;
  if (!my.empty()) {
    ll prv = ants[0].x;
    ford(i, sz(my)) {
      ll dist = prv - my[i];
      if (dist < 0) {
        dist += L;
      }
      go.pb(dist);
      prv = my[i];
    }
    go.pb(my.front() - ants[0].x);
  } else {
    go.pb(L);
  }

  for (auto d : go) {
    assert(d > 0);
  }

  vll stay;
  ll prv = opposite.front();
  for (int i = 1; i < sz(opposite); ++i) {
    ll dist = opposite[i] - prv;
    stay.pb(dist);
    prv = opposite[i];
  }
  stay.pb(ants[0].x - opposite.back() + L);

  for (auto d : stay) {
    assert(d > 0);
  }

  vll pref_go(sz(go) + 1);
  forn(i, sz(go)) { pref_go[i + 1] = pref_go[i] + go[i]; }

  vll pref_stay(sz(stay) + 1);
  forn(i, sz(stay)) { pref_stay[i + 1] = pref_stay[i] + stay[i]; }

  // printf("go:\n");
  // for (int x : go) {
  // 	printf("%d ", x);
  // }
  // puts("");
  // printf("stay:\n");
  // for (int x : stay) {
  // 	printf("%d ", x);
  // }
  // puts("");

  ll Left = -1;
  ll Right = 2 * nT + 1;
  while (Left != Right - 1) {
    ll len = (Left + Right) / 2;
    assert(len >= 0);

    ll cnt_go = (len + 1) / 2;
    ll cnt_stay = len - cnt_go;

    ll was_go = mult(cnt_go / sz(go), pref_go[sz(go)]);
    was_go += pref_go[cnt_go % sz(go)];
    ll was_stay = mult(cnt_stay / sz(stay), pref_stay[sz(stay)]);
    was_stay += pref_stay[cnt_stay % sz(stay)];

    if (was_go + was_stay <= nT) {
      Left = len;
    } else {
      Right = len;
    }
  }

  {
    ll len = Left;
    assert(len >= 0);
    // printf("len=%lld\n", len);
    ll cnt_go = (len + 1) / 2;
    ll cnt_stay = len - cnt_go;

    ll was_go = mult(cnt_go / sz(go), pref_go[sz(go)]);
    was_go += pref_go[cnt_go % sz(go)];
    ll was_stay = mult(cnt_stay / sz(stay), pref_stay[sz(stay)]);
    was_stay += pref_stay[cnt_stay % sz(stay)];

    // printf("was=%lld\n", was);
    ll dist = was_go;
    if (len % 2 == 0) {
      dist += nT - was_go - was_stay;
    }
    // printf("dist=%lld\n", dist);
    ll pos = coord(ants[0].x - dist);
    // printf("x0=%d, pos=%lld\n", ants[0].x, pos);
    // printf("pos=%lld, T=%d, L=%d\n", pos, T, L);
    final[ants[0].id] = coord(pos + T);
    make_ans(len % 2 == 0);
  }
}

void solve() {
  ll offset = 0;
  int id = -1;
  forn(i, N) {
    if (ants[i].w == 0) {
      id = i;
      break;
    }
  }
  if (id != -1) {
    // ants[id].x + off = 0
    offset = -ants[id].x;
    forn(i, N) { ants[i].x = coord(ants[i].x + offset); }
    vector<ant> nants;
    for (int i = id; i < N; ++i) {
      nants.pb(ants[i]);
    }
    forn(i, id) { nants.pb(ants[i]); }
    ants.swap(nants);
  }
  solve1();

  forn(i, N) { cout << coord(final[i] - offset) << '\n'; }
}

int main() {
#ifdef LOCAL
  freopen(FILE_NAME ".in", "r", stdin);
  // freopen(FILE_NAME ".out", "w", stdout);
#endif

  while (read()) {
    solve();

    break;
  }

#ifdef LOCAL
  cerr.precision(5);
  cerr << "Time: " << fixed << (double)clock() / CLOCKS_PER_SEC << endl;
#endif
  return 0;
}


Fixed submission:
#include <algorithm>
#include <bitset>
#include <cassert>
#include <cmath>
#include <complex>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <fstream>
#include <iostream>
#include <map>
#include <memory>
#include <numeric>
#include <queue>
#include <set>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <utility>
#include <vector>

using namespace std;

#define ws ws_____________________
#define y1 y1_____________________
#define y0 y0_____________________
#define left left_________________
#define right right_______________
#define next next_________________
#define prev prev_________________
#define hash hash_________________

#define pb push_back
#define fst first
#define snd second
#define mp make_pair
#define sz(C) ((int)(C).size())
#define forn(i, n) for (int i = 0; i < int(n); ++i)
#define ford(i, n) for (int i = int(n) - 1; i >= 0; --i)
#define all(C) begin(C), end(C)

typedef long long ll;
typedef unsigned long long ull;
typedef unsigned int uint;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef vector<ll> vll;
typedef vector<int> vi;
typedef vector<vi> vvi;
typedef vector<pii> vii;
typedef long double ld;
typedef complex<double> cd;

#define FILE_NAME "a"

struct ant {
  ll x;
  int w;
  int id;

  void read(int ii) {
    id = ii;
    cin >> x >> w;
    --w;
  }

  bool operator<(const ant &other) const { return x < other.x; }
};

const int MAXN = 2e5 + 10;

int N;
ll L, T;
vector<ant> ants;

bool read() {
  cin >> N >> L >> T;
  ants.resize(N);
  forn(i, N) { ants[i].read(i); }
  return 1;
}

ll coord(ll x) {
  x %= L;
  if (x < 0) {
    x += L;
  }
  return x;
}

const ll INF = 1e16;

ll mult(ll x, ll y) {
  if (!y) {
    return 0;
  }
  if (x >= INF / y) {
    return INF;
  }
  return min(INF, x * y);
}

ll final[MAXN];

void make_ans(bool is_left = true) {
  vll finals;
  forn(i, N) {
    ll pos = ants[i].x + (ants[i].w ? -1 : +1) * T;
    finals.pb(coord(pos));
  }

  sort(all(finals));
  int id0 = -1;
  srand(3);
  forn(i, N) {
    if (finals[i] == final[ants[0].id]) {
      id0 = i;
      if (!is_left) {
        if (i + 1 < N && finals[i + 1] == final[ants[0].id]) {
          ++id0;
        }
      }
      break;
    }
  }
  assert(id0 != -1);
  for (int i = 1; i < N; ++i) {
    final[ants[i].id] = finals[(id0 + i) % N];
  }
}

void solve1() {
  if (ants[0].w == 1) {
    final[ants[0].id] = coord(ants[0].x - T);
    make_ans();
    return;
  }

  assert(!ants[0].x);

  vll opposite;
  vll my;
  for (int i = 1; i < N; ++i) {
    if (ants[i].w == 1) {
      opposite.pb(ants[i].x);
    } else {
      my.pb(ants[i].x);
    }
  }

  // forn(i, N) {
  // 	printf("x=%lld w=%d\n", ants[i].x, ants[i].w);
  // }

  if (opposite.empty() || opposite.front() - ants[0].x >= 2 * T) {
    final[ants[0].id] = coord(ants[0].x + T);
    make_ans();
    return;
  }

  // printf("opposite:\n");
  // for (int x : opposite) {
  // 	printf("%d ", x);
  // }
  // puts("");
  // printf("my:\n");
  // for (int x : my) {
  // 	printf("%d ", x);
  // }
  // puts("");

  ll nT = 2 * T;
  ll dist = opposite.front() - ants[0].x;
  for (auto &x : opposite) {
    x -= dist;
    assert(x >= 0);
  }
  nT -= dist;

  // printf("nT=%d\n", nT);

  vll go;
  if (!my.empty()) {
    ll prv = ants[0].x;
    ford(i, sz(my)) {
      ll dist = prv - my[i];
      if (dist < 0) {
        dist += L;
      }
      go.pb(dist);
      prv = my[i];
    }
    go.pb(my.front() - ants[0].x);
  } else {
    go.pb(L);
  }

  for (auto d : go) {
    assert(d > 0);
  }

  vll stay;
  ll prv = opposite.front();
  for (int i = 1; i < sz(opposite); ++i) {
    ll dist = opposite[i] - prv;
    stay.pb(dist);
    prv = opposite[i];
  }
  stay.pb(ants[0].x - opposite.back() + L);

  for (auto d : stay) {
    assert(d > 0);
  }

  vll pref_go(sz(go) + 1);
  forn(i, sz(go)) { pref_go[i + 1] = pref_go[i] + go[i]; }

  vll pref_stay(sz(stay) + 1);
  forn(i, sz(stay)) { pref_stay[i + 1] = pref_stay[i] + stay[i]; }

  // printf("go:\n");
  // for (int x : go) {
  // 	printf("%d ", x);
  // }
  // puts("");
  // printf("stay:\n");
  // for (int x : stay) {
  // 	printf("%d ", x);
  // }
  // puts("");

  ll Left = -1;
  ll Right = 2 * nT + 1;
  while (Left != Right - 1) {
    ll len = (Left + Right) / 2;
    assert(len >= 0);

    ll cnt_go = (len + 1) / 2;
    ll cnt_stay = len - cnt_go;

    ll was_go = mult(cnt_go / sz(go), pref_go[sz(go)]);
    was_go += pref_go[cnt_go % sz(go)];
    ll was_stay = mult(cnt_stay / sz(stay), pref_stay[sz(stay)]);
    was_stay += pref_stay[cnt_stay % sz(stay)];

    if (was_go + was_stay <= nT) {
      Left = len;
    } else {
      Right = len;
    }
  }

  {
    ll len = Left;
    assert(len >= 0);
    // printf("len=%lld\n", len);
    ll cnt_go = (len + 1) / 2;
    ll cnt_stay = len - cnt_go;

    ll was_go = mult(cnt_go / sz(go), pref_go[sz(go)]);
    was_go += pref_go[cnt_go % sz(go)];
    ll was_stay = mult(cnt_stay / sz(stay), pref_stay[sz(stay)]);
    was_stay += pref_stay[cnt_stay % sz(stay)];

    // printf("was=%lld\n", was);
    ll dist = was_go;
    if (len % 2 == 0) {
      dist += nT - was_go - was_stay;
    }
    // printf("dist=%lld\n", dist);
    ll pos = coord(ants[0].x - dist);
    // printf("x0=%d, pos=%lld\n", ants[0].x, pos);
    // printf("pos=%lld, T=%d, L=%d\n", pos, T, L);
    final[ants[0].id] = coord(pos + T);
    make_ans(len % 2 == 0);
  }
}

void solve() {
  ll offset = 0;
  int id = -1;
  forn(i, N) {
    if (ants[i].w == 0) {
      id = i;
      break;
    }
  }
  if (id != -1) {
    // ants[id].x + off = 0
    offset = -ants[id].x;
    forn(i, N) { ants[i].x = coord(ants[i].x + offset); }
    vector<ant> nants;
    for (int i = id; i < N; ++i) {
      nants.pb(ants[i]);
    }
    forn(i, id) { nants.pb(ants[i]); }
    ants.swap(nants);
  }
  solve1();

  forn(i, N) { cout << coord(final[i] - offset) << '\n'; }
}

int main() {
#ifdef LOCAL
  freopen(FILE_NAME ".in", "r", stdin);
  // freopen(FILE_NAME ".out", "w", stdout);
#endif

  while (read()) {
    solve();

    break;
  }

#ifdef LOCAL
  cerr.precision(5);
  cerr << "Time: " << fixed << (double)clock() / CLOCKS_PER_SEC << endl;
#endif
  return 0;
}