Problem p04052 (C++)

Buggy submission (status: Runtime Error):
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <queue>
using namespace std;

const int MAX_N = 500005;

int P[MAX_N];

class Segment {
public:
  Segment *ls, *rs;
  int l, r, mx;
  inline Segment() { ls = rs = NULL; }
  inline int _max(int x, int y) { return P[x] > P[y] ? x : y; }
  void maintain() { mx = _max(ls->mx, rs->mx); }
  void build(int L, int R) {
    l = L, r = R;
    if (l == r) {
      mx = l;
      return;
    }
    int mid = (L + R) >> 1;
    if (!ls)
      ls = new Segment;
    if (!rs)
      rs = new Segment;

    ls->build(l, mid), rs->build(mid + 1, r);
    maintain();
  }
  int ask(int L, int R) {
    if (L <= l && r <= R)
      return mx;
    int mid = (l + r) >> 1;
    if (mid < L)
      return rs->ask(L, R);
    else if (mid >= R)
      return ls->ask(L, R);
    else
      return _max(ls->ask(L, R), rs->ask(L, R));
  }
  void modify(int pos, int val) {
    if (l == r) {
      P[pos] = val;
      return;
    }
    int mid = (l + r) >> 1;
    if (mid >= pos)
      ls->modify(pos, val);
    else
      rs->modify(pos, val);
    maintain();
  }
} *rt;

priority_queue<int> q;
int left[MAX_N], right[MAX_N], ans[MAX_N], id[MAX_N], N, K;
bool vis[MAX_N];

void insert(int x) {
  if (vis[x])
    return;

  int l = max(1, x - K + 1), r = min(N, x + K - 1);
  int tmp2 = rt->ask(l, r);
  if (P[x] != -1 && P[tmp2] <= P[x])
    q.push(x), vis[x] = 1;
}

int main() {

#ifndef ONLINE_JUDGE
  freopen("input.in", "r", stdin);
#endif

  rt = new Segment;

  scanf("%d%d", &N, &K);

  for (int i = 1; i <= N; ++i)
    scanf("%d", &P[i]);

  rt->build(1, N);

  int tot = 0;

  for (int i = 1; i <= N; i += K) {
    ++tot;
    left[tot] = i, right[tot] = min(i + K - 1, N);

    for (int j = left[tot]; j <= right[tot]; ++j)
      id[j] = tot;

    int tmp = rt->ask(left[tot], right[tot]);
    insert(tmp);
  }

  for (int i = N; i; --i) {
    int x = q.top();
    q.pop();
    ans[x] = i, rt->modify(x, -1);
    int le = id[x] - 1, ri = id[x] + 1;
    insert(rt->ask(left[id[x]], right[id[x]]));

    if (le >= 1)
      insert(rt->ask(left[le], right[le]));

    if (ri <= tot)
      insert(rt->ask(left[ri], right[ri]));
  }

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

Fixed submission:
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <queue>
using namespace std;

const int MAX_N = 500005;

int P[MAX_N];

class Segment {
public:
  Segment *ls, *rs;
  int l, r, mx;
  inline Segment() { ls = rs = NULL; }
  inline int _max(int x, int y) { return P[x] > P[y] ? x : y; }
  void maintain() { mx = _max(ls->mx, rs->mx); }
  void build(int L, int R) {
    l = L, r = R;
    if (l == r) {
      mx = l;
      return;
    }
    int mid = (L + R) >> 1;
    if (!ls)
      ls = new Segment;
    if (!rs)
      rs = new Segment;

    ls->build(l, mid), rs->build(mid + 1, r);
    maintain();
  }
  int ask(int L, int R) {
    if (L <= l && r <= R)
      return mx;
    int mid = (l + r) >> 1;
    if (mid < L)
      return rs->ask(L, R);
    else if (mid >= R)
      return ls->ask(L, R);
    else
      return _max(ls->ask(L, R), rs->ask(L, R));
  }
  void modify(int pos, int val) {
    if (l == r) {
      P[pos] = val;
      return;
    }
    int mid = (l + r) >> 1;
    if (mid >= pos)
      ls->modify(pos, val);
    else
      rs->modify(pos, val);
    maintain();
  }
} *rt;

priority_queue<int> q;
int left[MAX_N], right[MAX_N], ans[MAX_N], id[MAX_N], N, K;
bool vis[MAX_N];

void insert(int x) {
  if (vis[x])
    return;

  int l = max(1, x - K + 1), r = min(N, x + K - 1);
  int tmp2 = rt->ask(l, r);
  if (P[x] != -1 && P[tmp2] <= P[x])
    q.push(x), vis[x] = 1;
}

int main() {

  rt = new Segment;

  scanf("%d%d", &N, &K);

  for (int i = 1; i <= N; ++i)
    scanf("%d", &P[i]);

  rt->build(1, N);

  int tot = 0;

  for (int i = 1; i <= N; i += K) {
    ++tot;
    left[tot] = i, right[tot] = min(i + K - 1, N);

    for (int j = left[tot]; j <= right[tot]; ++j)
      id[j] = tot;

    int tmp = rt->ask(left[tot], right[tot]);
    insert(tmp);
  }

  for (int i = N; i; --i) {
    int x = q.top();
    q.pop();
    ans[x] = i, rt->modify(x, -1);
    int le = id[x] - 1, ri = id[x] + 1;
    insert(rt->ask(left[id[x]], right[id[x]]));

    if (le >= 1)
      insert(rt->ask(left[le], right[le]));

    if (ri <= tot)
      insert(rt->ask(left[ri], right[ri]));
  }

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