Problem p03202 (C++)

Buggy submission (status: Time Limit Exceeded):
#include <algorithm>/*{{{*/
#include <cassert>
#include <cctype>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <vector>
using namespace std;
typedef long long lld;
typedef long double lf;
typedef unsigned long long uld;
typedef pair<int, int> pii;
#define fi first
#define se second
#define pb push_back
#define mk make_pair
#define FOR(i, a, b) for (int i = (a); i <= (b); ++i)
#define ROF(i, a, b) for (int i = (a); i >= (b); --i)
namespace RA {
int r(int p) { return 1ll * rand() * rand() % p; }
int r(int L, int R) { return r(R - L + 1) + L; }
} // namespace RA
/******************heading******************/

const int N = 2e5 + 5;

int n;
int a[N];

namespace S1 {
int c[40]; // 在这一位上是右儿子的边数
bool check(int k) {
  int len = 0;
  memset(c, 0, sizeof(c));
  FOR(i, 1, n) {
    if (a[i] > len) {
      FOR(j, len + 1, a[i])++ c[j];
      len = a[i];
    } else {
      int pos = a[i];
      while (c[pos] == k)
        --pos;
      if (pos == 0)
        return 0;
      c[pos]++;
      FOR(j, pos + 1, 30) c[j] = 0; // 清空
      FOR(j, pos + 1, a[i]) c[j]++;
      len = a[i];
    }
  }
  return 1;
}
} // namespace S1
int tot = 0;

namespace S2 {
map<int, int> c;
bool check(int k) {
  int len = 0;
  c.clear();
  FOR(i, 1, n) {
    if (a[i] > len) {
    } else {
      int pos = a[i];
      while (tot < 4e6 && pos && c[pos] == k - 1)
        --pos, ++tot;
      if (pos == 0)
        return 0;
      c[pos]++;
      map<int, int>::iterator it = c.find(pos);
      ++it;
      c.erase(it, c.end());
    }
    len = a[i];
    // if(tot>=1e7)return 0;
    if (tot >= 4e6)
      return 0;
  }
  return 1;
}
} // namespace S2
int main() {
  scanf("%d", &n);
  FOR(i, 1, n) scanf("%d", &a[i]);
  int l = 1, r = n + 1, mid;
  while (l < r && tot < 4e6)
    mid = (l + r) >> 1, S2::check(mid) ? r = mid : l = mid + 1;
  if (tot >= 4e6) {
    FOR(i, 1, n) a[i] = min(a[i], 30);
    l = 1, r = n + 1;
    while (l < r)
      mid = (l + r) >> 1, S1::check(mid) ? r = mid : l = mid + 1;
  }
  printf("%d\n", l);
  return 0;
}


Fixed submission:
#include <algorithm>/*{{{*/
#include <cassert>
#include <cctype>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <vector>
using namespace std;
typedef long long lld;
typedef long double lf;
typedef unsigned long long uld;
typedef pair<int, int> pii;
#define fi first
#define se second
#define pb push_back
#define mk make_pair
#define FOR(i, a, b) for (int i = (a); i <= (b); ++i)
#define ROF(i, a, b) for (int i = (a); i >= (b); --i)
namespace RA {
int r(int p) { return 1ll * rand() * rand() % p; }
int r(int L, int R) { return r(R - L + 1) + L; }
} // namespace RA
/******************heading******************/

const int N = 2e5 + 5;

int n;
int a[N];

namespace S1 {
int c[40]; // 在这一位上是右儿子的边数
bool check(int k) {
  int len = 0;
  memset(c, 0, sizeof(c));
  FOR(i, 1, n) {
    if (a[i] > len) {
      FOR(j, len + 1, a[i])++ c[j];
      len = a[i];
    } else {
      int pos = a[i];
      while (c[pos] == k)
        --pos;
      if (pos == 0)
        return 0;
      c[pos]++;
      FOR(j, pos + 1, 30) c[j] = 0; // 清空
      FOR(j, pos + 1, a[i]) c[j]++;
      len = a[i];
    }
  }
  return 1;
}
} // namespace S1
int tot = 0;

namespace S2 {
map<int, int> c;
bool check(int k) {
  int len = 0;
  c.clear();
  FOR(i, 1, n) {
    if (a[i] > len) {
    } else {
      int pos = a[i];
      if (k == 1)
        return 0;
      while (tot < 4e6 && pos && c.count(pos) && c[pos] == k - 1)
        --pos, ++tot;
      if (pos == 0)
        return 0;
      c[pos]++;
      map<int, int>::iterator it = c.find(pos);
      ++it;
      c.erase(it, c.end());
    }
    len = a[i];
    // if(tot>=1e7)return 0;
    if (tot >= 4e6)
      return 0;
  }
  return 1;
}
} // namespace S2
int main() {
  scanf("%d", &n);
  FOR(i, 1, n) scanf("%d", &a[i]);
  int l = 1, r = n + 1, mid;
  while (l < r && tot < 4e6)
    mid = (l + r) >> 1, S2::check(mid) ? r = mid : l = mid + 1;
  if (tot >= 4e6) {
    FOR(i, 1, n) a[i] = min(a[i], 30);
    l = 1, r = n + 1;
    while (l < r)
      mid = (l + r) >> 1, S1::check(mid) ? r = mid : l = mid + 1;
  }
  printf("%d\n", l);
  return 0;
}