Problem p02904 (C++)

Buggy submission (status: Runtime Error):
#include <bits/stdc++.h>
using namespace std;

#define REP(i, m, n) for (int i = (m); i < (int)(n); i++)
#define REPS(i, m, n) for (int i = (m); i <= (int)(n); i++)
#define rep(i, n) REP(i, 0, n)
#define reps(i, n) for (int i = 0; i <= (int)(n); i++)
#define rrep(i, x) for (int i = ((int)(x)-1); i >= 0; i--)
#define rreps(i, x) for (int i = (int)(x); i >= 0; i--)
#define all(x) (x).begin(), (x).end()
#define rall(x) (x).rbegin(), (x).rend()
#define pb push_back
typedef long long ll;
typedef pair<int, int> P;
const int inf = INT_MAX;
const ll INF = 1LL << 60;
const ll mod = 1e9 + 7;
template <class T> inline bool chmax(T &a, T b) {
  if (a < b) {
    a = b;
    return 1;
  }
  return 0;
}
template <class T> inline bool chmin(T &a, T b) {
  if (a > b) {
    a = b;
    return 1;
  }
  return 0;
}
template <typename A, size_t N, typename T>
void Fill(A (&array)[N], const T &val) {
  fill((T *)array, (T *)(array + N), val);
}

class UnionFind {
public:
  vector<ll> par;
  vector<ll> siz;

  UnionFind(ll sz_) : par(sz_), siz(sz_, 1LL) {
    for (ll i = 0; i < sz_; ++i)
      par[i] = i;
  }
  void init(ll sz_) {
    par.resize(sz_);
    siz.assign(sz_, 1LL);
    for (ll i = 0; i < sz_; ++i)
      par[i] = i;
  }

  ll root(ll x) {
    while (par[x] != x) {
      x = par[x] = par[par[x]];
    }
    return x;
  }

  bool unite(ll x, ll y) {
    x = root(x);
    y = root(y);
    if (x == y)
      return false;
    if (siz[x] < siz[y])
      swap(x, y);
    siz[x] += siz[y];
    par[y] = x;
    return true;
  }

  bool issame(ll x, ll y) { return root(x) == root(y); }

  ll size(ll x) { return siz[root(x)]; }
};

struct SegmentTree {
private:
  int n;
  vector<int> node;

public:
  SegmentTree(vector<int> v) {
    int sz = v.size();
    n = 1;
    // 2の累乗の大きさにする
    while (n < sz)
      n *= 2;
    // 余りをinfで埋める
    node.resize(2 * n - 1, inf);
    // 葉を構築
    for (int i = 0; i < sz; i++) {
      node[i + n - 1] = v[i];
    }
    // 親を構築
    for (int i = n - 2; i >= 0; i--) {
      node[i] = min(node[2 * i + 1], node[2 * i + 2]);
    }
  }

  void update(int x, int val) {
    x += (n - 1);
    node[x] = val;
    while (x > 0) {
      x = (x - 1) / 2;
      node[x] = min(node[2 * x + 1], node[2 * x + 2]);
    }
  }

  int getmin(int a, int b, int k = 0, int l = 0, int r = -1) {
    if (r < 0)
      r = n;
    if (r <= a || b <= l)
      return inf;
    if (a <= l && r <= b)
      return node[k];
    int vl = getmin(a, b, 2 * k + 1, l, (l + r) / 2);
    int vr = getmin(a, b, 2 * k + 2, (l + r) / 2, r);
    return min(vl, vr);
  }
};

int main() {
  cin.tie(0);
  ios::sync_with_stdio(false);

  int n, k;
  cin >> n >> k;
  SegmentTree sg1(vector<int>(2 * n, inf)), sg2(vector<int>(2 * n, inf));
  vector<int> a(n);
  rep(i, n) {
    cin >> a[i];
    sg1.update(i, a[i]);
    sg2.update(i, -a[i]);
  }
  UnionFind uf(n + 1);
  REP(i, 1, n - k + 1) {
    if (sg1.getmin(i - 1, i + k - 1) == a[i - 1] &&
        sg2.getmin(i, i + k) == -a[k + i - 1]) {
      uf.unite(i - 1, i);
    }
  }
  vector<int> sum(n);
  rep(i, n - 1) { sum[i + 1] = (a[i] > a[i + 1]); }
  rep(i, n) sum[i + 1] += sum[i];
  rep(i, n - k + 1) {
    if (sum[i] == sum[i + k - 1]) {
      uf.unite(i, n);
    }
  }
  int ans = 0;
  rep(i, n - k + 1) {
    if (uf.root(i) == i)
      ans++;
  }
  cout << ans << endl;
  return 0;
}

Fixed submission:
#include <bits/stdc++.h>
using namespace std;

#define REP(i, m, n) for (int i = (m); i < (int)(n); i++)
#define REPS(i, m, n) for (int i = (m); i <= (int)(n); i++)
#define rep(i, n) REP(i, 0, n)
#define reps(i, n) for (int i = 0; i <= (int)(n); i++)
#define rrep(i, x) for (int i = ((int)(x)-1); i >= 0; i--)
#define rreps(i, x) for (int i = (int)(x); i >= 0; i--)
#define all(x) (x).begin(), (x).end()
#define rall(x) (x).rbegin(), (x).rend()
#define pb push_back
typedef long long ll;
typedef pair<int, int> P;
const int inf = INT_MAX;
const ll INF = 1LL << 60;
const ll mod = 1e9 + 7;
template <class T> inline bool chmax(T &a, T b) {
  if (a < b) {
    a = b;
    return 1;
  }
  return 0;
}
template <class T> inline bool chmin(T &a, T b) {
  if (a > b) {
    a = b;
    return 1;
  }
  return 0;
}
template <typename A, size_t N, typename T>
void Fill(A (&array)[N], const T &val) {
  fill((T *)array, (T *)(array + N), val);
}

class UnionFind {
public:
  vector<ll> par;
  vector<ll> siz;

  UnionFind(ll sz_) : par(sz_), siz(sz_, 1LL) {
    for (ll i = 0; i < sz_; ++i)
      par[i] = i;
  }
  void init(ll sz_) {
    par.resize(sz_);
    siz.assign(sz_, 1LL);
    for (ll i = 0; i < sz_; ++i)
      par[i] = i;
  }

  ll root(ll x) {
    while (par[x] != x) {
      x = par[x] = par[par[x]];
    }
    return x;
  }

  bool unite(ll x, ll y) {
    x = root(x);
    y = root(y);
    if (x == y)
      return false;
    if (siz[x] < siz[y])
      swap(x, y);
    siz[x] += siz[y];
    par[y] = x;
    return true;
  }

  bool issame(ll x, ll y) { return root(x) == root(y); }

  ll size(ll x) { return siz[root(x)]; }
};

struct SegmentTree {
private:
  int n;
  vector<int> node;

public:
  SegmentTree(vector<int> v) {
    int sz = v.size();
    n = 1;
    // 2の累乗の大きさにする
    while (n < sz)
      n *= 2;
    // 余りをinfで埋める
    node.resize(2 * n - 1, inf);
    // 葉を構築
    for (int i = 0; i < sz; i++) {
      node[i + n - 1] = v[i];
    }
    // 親を構築
    for (int i = n - 2; i >= 0; i--) {
      node[i] = min(node[2 * i + 1], node[2 * i + 2]);
    }
  }

  void update(int x, int val) {
    x += (n - 1);
    node[x] = val;
    while (x > 0) {
      x = (x - 1) / 2;
      node[x] = min(node[2 * x + 1], node[2 * x + 2]);
    }
  }

  int getmin(int a, int b, int k = 0, int l = 0, int r = -1) {
    if (r < 0)
      r = n;
    if (r <= a || b <= l)
      return inf;
    if (a <= l && r <= b)
      return node[k];
    int vl = getmin(a, b, 2 * k + 1, l, (l + r) / 2);
    int vr = getmin(a, b, 2 * k + 2, (l + r) / 2, r);
    return min(vl, vr);
  }
};

int main() {
  cin.tie(0);
  ios::sync_with_stdio(false);

  int n, k;
  cin >> n >> k;
  SegmentTree sg1(vector<int>(2 * n, inf)), sg2(vector<int>(2 * n, inf));
  vector<int> a(n);
  rep(i, n) {
    cin >> a[i];
    sg1.update(i, a[i]);
    sg2.update(i, -a[i]);
  }
  UnionFind uf(n + 1);
  REP(i, 1, n - k + 1) {
    if (sg1.getmin(i - 1, i + k - 1) == a[i - 1] &&
        sg2.getmin(i, i + k) == -a[k + i - 1]) {
      uf.unite(i - 1, i);
    }
  }
  vector<int> sum(n + 1);
  rep(i, n - 1) { sum[i + 1] = (a[i] > a[i + 1]); }
  rep(i, n) sum[i + 1] += sum[i];
  rep(i, n - k + 1) {
    if (sum[i] == sum[i + k - 1]) {
      uf.unite(i, n);
    }
  }
  int ans = 0;
  rep(i, n - k + 1) {
    if (uf.root(i) == i)
      ans++;
  }
  cout << ans << endl;
  return 0;
}