Problem p02904 (C++)

Buggy submission (status: Runtime Error):
#include <algorithm>
#include <climits>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <deque>
#include <iomanip>
#include <iostream>
#include <list>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <tuple>
#include <unordered_map>
#include <vector>
#define ll long long
#define pii pair<int, int>
#define pll pair<ll, ll>
#define vii vector<int>
#define vll vector<ll>
#define lb lower_bound
#define pb push_back
#define mp make_pair
#define rep(i, n) for (ll i = 0; i < n; i++)
#define rep2(i, a, b) for (ll i = a; i < b; i++)
#define repr(i, n) for (ll i = n - 1; i >= 0; i--)
#define all(x) x.begin(), x.end()
#define int ll
using namespace std;
const int INF(1 << 30);
const ll LLINF(1LL << 55LL);
const int MOD = 1000000007;
const int MAX = 510000;

struct UnionFind {
  vector<int> par;

  UnionFind(int n) : par(n, -1) {}
  void init(int n) { par.assign(n, -1); }

  int find(int x) {
    if (par[x] < 0)
      return x;
    else
      return par[x] = find(par[x]);
  }

  bool same(int x, int y) { return find(x) == find(y); }

  bool unite(int x, int y) {
    x = find(x);
    y = find(y);
    if (x == y)
      return false;
    if (par[x] > par[y])
      swap(x, y);
    par[x] += par[y];
    par[y] = x;
    return true;
  }

  int size(int x) { return -par[find(x)]; }

  void print(int x) {
    rep(i, x) { cout << par[i] << endl; }
    return;
  }
};

struct SegmentTree {
  static const int MAX_N = 1 << 8;
  int n, dat[2 * MAX_N - 1];
  SegmentTree(int n_) {
    n = 1;
    while (n < n_)
      n *= 2;
    for (int i = 0; i < 2 * n - 1; i++)
      dat[i] = INT_MAX;
  }
  void update(int k, int a) {
    k += n - 1;
    dat[k] = a;
    while (k > 0) {
      k = (k - 1) / 2;
      dat[k] = min(dat[k * 2 + 1], dat[k * 2 + 2]);
    }
  }
  int query(int a, int b, int k, int l, int r) {
    if (r <= a || b <= l)
      return INT_MAX;
    if (a <= l && r <= b)
      return dat[k];
    else {
      int vl = query(a, b, k * 2 + 1, l, (l + r) / 2);
      int vr = query(a, b, k * 2 + 2, (l + r) / 2, r);
      return min(vr, vl);
    }
  }
  int query(int a, int b) { return query(a, b, 0, 0, n); }
};

struct SegmentTree1 {
  static const int MAX_N = 1 << 12;
  int n, dat[2 * MAX_N - 1];
  SegmentTree1(int n_) {
    n = 1;
    while (n < n_)
      n *= 2;
    for (int i = 0; i < 2 * n - 1; i++)
      dat[i] = -INT_MAX;
  }
  void update(int k, int a) {
    k += n - 1;
    dat[k] = a;
    while (k > 0) {
      k = (k - 1) / 2;
      dat[k] = max(dat[k * 2 + 1], dat[k * 2 + 2]);
    }
  }
  int query(int a, int b, int k, int l, int r) {
    if (r <= a || b <= l)
      return -INT_MAX;
    if (a <= l && r <= b)
      return dat[k];
    else {
      int vl = query(a, b, k * 2 + 1, l, (l + r) / 2);
      int vr = query(a, b, k * 2 + 2, (l + r) / 2, r);
      return max(vr, vl);
    }
  }
  int query(int a, int b) { return query(a, b, 0, 0, n); }
};

signed main() {
  cin.tie(0);
  ios::sync_with_stdio(false);
  cout << fixed << setprecision(15);
  ll n, p[200010], k, a[200010];
  set<ll> st;
  pair<ll, ll> pl[200010];
  cin >> n >> k;
  SegmentTree sg(n), sg2(n);
  UnionFind uf(n);
  rep(i, n) {
    cin >> p[i];
    sg.update(i, p[i]);
    sg2.update(i, -p[i]);
  }
  for (ll i = 1; i < n - k + 1; i++) {
    pl[i] = pll(sg.query(i, i + k - 1), sg2.query(i, i + k - 1));
  }
  ll cnt = 1, ans = 0, S;
  a[0] = 1;

  for (ll i = 1; i < n; i++) {
    if (p[i - 1] < p[i])
      cnt++;
    else
      cnt = 1;
    a[i] = cnt;
    if (a[i] >= k)
      st.insert(i - k + 1);
  }
  if (st.size() > 0) {
    auto itr = st.begin();
    S = *itr;
    for (auto i : st) {
      uf.unite(S, i);
    }
  } /*
   vector<int> sum(n);
   rep(i,n-1){
       sum[i+1]=(p[i]>p[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);
   }*/
  /*
  rep(i,n-k){
      if(p[i]<pl[i+1].first && pl[i+1].second<p[i+k]){
          uf.unite(i,i+1);
      }
  }*/
  rep2(i, 1, n - k + 1) {
    if (sg.query(i - 1, i + k - 1) == p[i - 1] &&
        sg2.query(i, i + k) == -p[k + i - 1]) {
      // cout<<i<<"yes"<<endl;
      uf.unite(i - 1, i);
    }
  }
  rep(i, n - k + 1) {
    if (i == uf.find(i)) {
      // cout<<i<<endl;
      ++ans;
    }
  }
  // cout<<uf.find(0)<<endl;
  cout << ans << endl;
  return 0;
}

Fixed submission:
#include <algorithm>
#include <climits>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <deque>
#include <iomanip>
#include <iostream>
#include <list>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <tuple>
#include <unordered_map>
#include <vector>
#define ll long long
#define pii pair<int, int>
#define pll pair<ll, ll>
#define vii vector<int>
#define vll vector<ll>
#define lb lower_bound
#define pb push_back
#define mp make_pair
#define rep(i, n) for (ll i = 0; i < n; i++)
#define rep2(i, a, b) for (ll i = a; i < b; i++)
#define repr(i, n) for (ll i = n - 1; i >= 0; i--)
#define all(x) x.begin(), x.end()
#define int ll
using namespace std;
const int INF(1 << 30);
const ll LLINF(1LL << 55LL);
const int MOD = 1000000007;
const int MAX = 510000;

struct UnionFind {
  vector<int> par;

  UnionFind(int n) : par(n, -1) {}
  void init(int n) { par.assign(n, -1); }

  int find(int x) {
    if (par[x] < 0)
      return x;
    else
      return par[x] = find(par[x]);
  }

  bool same(int x, int y) { return find(x) == find(y); }

  bool unite(int x, int y) {
    x = find(x);
    y = find(y);
    if (x == y)
      return false;
    if (par[x] > par[y])
      swap(x, y);
    par[x] += par[y];
    par[y] = x;
    return true;
  }

  int size(int x) { return -par[find(x)]; }

  void print(int x) {
    rep(i, x) { cout << par[i] << endl; }
    return;
  }
};

struct SegmentTree {
  static const int MAX_N = 1 << 18;
  int n, dat[2 * MAX_N - 1];
  SegmentTree(int n_) {
    n = 1;
    while (n < n_)
      n *= 2;
    for (int i = 0; i < 2 * n - 1; i++)
      dat[i] = INT_MAX;
  }
  void update(int k, int a) {
    k += n - 1;
    dat[k] = a;
    while (k > 0) {
      k = (k - 1) / 2;
      dat[k] = min(dat[k * 2 + 1], dat[k * 2 + 2]);
    }
  }
  int query(int a, int b, int k, int l, int r) {
    if (r <= a || b <= l)
      return INT_MAX;
    if (a <= l && r <= b)
      return dat[k];
    else {
      int vl = query(a, b, k * 2 + 1, l, (l + r) / 2);
      int vr = query(a, b, k * 2 + 2, (l + r) / 2, r);
      return min(vr, vl);
    }
  }
  int query(int a, int b) { return query(a, b, 0, 0, n); }
};

struct SegmentTree1 {
  static const int MAX_N = 1 << 12;
  int n, dat[2 * MAX_N - 1];
  SegmentTree1(int n_) {
    n = 1;
    while (n < n_)
      n *= 2;
    for (int i = 0; i < 2 * n - 1; i++)
      dat[i] = -INT_MAX;
  }
  void update(int k, int a) {
    k += n - 1;
    dat[k] = a;
    while (k > 0) {
      k = (k - 1) / 2;
      dat[k] = max(dat[k * 2 + 1], dat[k * 2 + 2]);
    }
  }
  int query(int a, int b, int k, int l, int r) {
    if (r <= a || b <= l)
      return -INT_MAX;
    if (a <= l && r <= b)
      return dat[k];
    else {
      int vl = query(a, b, k * 2 + 1, l, (l + r) / 2);
      int vr = query(a, b, k * 2 + 2, (l + r) / 2, r);
      return max(vr, vl);
    }
  }
  int query(int a, int b) { return query(a, b, 0, 0, n); }
};

signed main() {
  cin.tie(0);
  ios::sync_with_stdio(false);
  cout << fixed << setprecision(15);
  ll n, p[200010], k, a[200010];
  set<ll> st;
  pair<ll, ll> pl[200010];
  cin >> n >> k;
  SegmentTree sg(n), sg2(n);
  UnionFind uf(n);
  rep(i, n) {
    cin >> p[i];
    sg.update(i, p[i]);
    sg2.update(i, -p[i]);
  }
  for (ll i = 1; i < n - k + 1; i++) {
    pl[i] = pll(sg.query(i, i + k - 1), sg2.query(i, i + k - 1));
  }
  ll cnt = 1, ans = 0, S;
  a[0] = 1;

  for (ll i = 1; i < n; i++) {
    if (p[i - 1] < p[i])
      cnt++;
    else
      cnt = 1;
    a[i] = cnt;
    if (a[i] >= k)
      st.insert(i - k + 1);
  }
  if (st.size() > 0) {
    auto itr = st.begin();
    S = *itr;
    for (auto i : st) {
      uf.unite(S, i);
    }
  } /*
   vector<int> sum(n);
   rep(i,n-1){
       sum[i+1]=(p[i]>p[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);
   }*/
  /*
  rep(i,n-k){
      if(p[i]<pl[i+1].first && pl[i+1].second<p[i+k]){
          uf.unite(i,i+1);
      }
  }*/
  rep2(i, 1, n - k + 1) {
    if (sg.query(i - 1, i + k - 1) == p[i - 1] &&
        sg2.query(i, i + k) == -p[k + i - 1]) {
      // cout<<i<<"yes"<<endl;
      uf.unite(i - 1, i);
    }
  }
  rep(i, n - k + 1) {
    if (i == uf.find(i)) {
      // cout<<i<<endl;
      ++ans;
    }
  }
  // cout<<uf.find(0)<<endl;
  cout << ans << endl;
  return 0;
}