Problem p02652 (C++) — buggy submission, verdict: Time Limit Exceeded

// Marcin Knapik
#include <bits/stdc++.h>
#pragma GCC optimize("O3")
#pragma GCC optimize("Ofast")
#pragma GCC optimize("unroll-loops")

using namespace std;

// #include <ext/pb_ds/assoc_container.hpp> // order_of_key
// #include <ext/pb_ds/tree_policy.hpp> // find by order
// using namespace __gnu_pbds;
// #define ordered_set tree< int , null_type,less< int >,
// rb_tree_tag,tree_order_statistics_node_update>

// const ll MAX_LL = 0xFFFFFFFFFFFFFFFF;
// mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
#define losuj(a, b) uniform_int_distribution<ll>(a, b)(rng)

#define int ll
typedef long double ld;
typedef long long ll;
typedef pair<int, int> ii;
typedef vector<int> vi;
typedef vector<ll> vll;
typedef vector<vll> vvll;
typedef vector<ii> vii;
typedef vector<vi> vvi;
typedef vector<vii> vvii;
#define pll pair<long long, long long>
#define ull unsigned long long

#define sz(a) (int)(a).size()
#define pb push_back
#define all(c) (c).begin(), (c).end()
#define rall(c) (c).rbegin(), (c).rend()
#define FOR(i, a) for (int i = 0; i < (a); i++)
#define f first
#define s second

template <class T> inline bool setmin(T &a, T b) {
  if (a > b)
    return a = b, 1;
  return 0;
}
template <class T> inline bool setmax(T &a, T b) {
  if (a < b)
    return a = b, 1;
  return 0;
}

template <class T> inline T fast(T a, T b, T mod) {
  ll res = 1;
  while (b) {
    if (b & 1)
      res = (res * a) % mod;
    a = (a * a) % mod;
    b >>= 1;
  }
  return res;
}
template <class T> istream &operator>>(istream &os, vector<T> &container) {
  for (auto &u : container)
    os >> u;
  return os;
}
template <class T>
ostream &operator<<(ostream &os, const vector<T> &container) {
  for (auto &u : container)
    os << u << " ";
  return os;
}
template <class T> inline T gcd(T a, T b) {
  while (b)
    swap(a %= b, b);
  return abs(a);
}

const ll INF = 1e9 + 7;
const ll mod = 998244353;
const ll BIG_INF = 1e18 + 7;
const ll N = 1e6 + 7;
const ll T = 1 << 20;
const ld inf = 1e18;

ll m, n, k, q;

int solve(string &s, int below) {
  vi pref = {0};
  for (int i = 0; i < sz(s); i++)
    pref.pb(pref.back() + (s[i] == '0' ? -1 : 1));

  vi min_suf = pref;
  for (int i = sz(s) - 1; i >= 0; i--)
    min_suf[i] = min(min_suf[i + 1], pref[i]);

  int dod = 0, maxi = 0;

  for (int i = 1; i <= sz(s); i++) {
    if (s[i - 1] == '?' and min_suf[i] - dod - 2 >= min_suf[0] - below)
      dod += 2;
    maxi = max(maxi, pref[i] - dod);
  }

  return maxi - (min_suf[0] - below);
}

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

  string s;
  cin >> s;
  cout << min(solve(s, 0), solve(s, 1)) << '\\n';
}

Error: TLE

Fixed submission:

// Marcin Knapik
#include <bits/stdc++.h>
#pragma GCC optimize("O3")
#pragma GCC optimize("Ofast")
#pragma GCC optimize("unroll-loops")

using namespace std;

// #include <ext/pb_ds/assoc_container.hpp> // order_of_key
// #include <ext/pb_ds/tree_policy.hpp> // find by order
// using namespace __gnu_pbds;
// #define ordered_set tree< int , null_type,less< int >,
// rb_tree_tag,tree_order_statistics_node_update>

// const ll MAX_LL = 0xFFFFFFFFFFFFFFFF;
// mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
#define losuj(a, b) uniform_int_distribution<ll>(a, b)(rng)

#define int ll
typedef long double ld;
typedef long long ll;
typedef pair<int, int> ii;
typedef vector<int> vi;
typedef vector<ll> vll;
typedef vector<vll> vvll;
typedef vector<ii> vii;
typedef vector<vi> vvi;
typedef vector<vii> vvii;
#define pll pair<long long, long long>
#define ull unsigned long long

#define sz(a) (int)(a).size()
#define pb push_back
#define all(c) (c).begin(), (c).end()
#define rall(c) (c).rbegin(), (c).rend()
#define FOR(i, a) for (int i = 0; i < (a); i++)
#define f first
#define s second

template <class T> inline bool setmin(T &a, T b) {
  if (a > b)
    return a = b, 1;
  return 0;
}
template <class T> inline bool setmax(T &a, T b) {
  if (a < b)
    return a = b, 1;
  return 0;
}

template <class T> inline T fast(T a, T b, T mod) {
  ll res = 1;
  while (b) {
    if (b & 1)
      res = (res * a) % mod;
    a = (a * a) % mod;
    b >>= 1;
  }
  return res;
}
template <class T> istream &operator>>(istream &os, vector<T> &container) {
  for (auto &u : container)
    os >> u;
  return os;
}
template <class T>
ostream &operator<<(ostream &os, const vector<T> &container) {
  for (auto &u : container)
    os << u << " ";
  return os;
}
template <class T> inline T gcd(T a, T b) {
  while (b)
    swap(a %= b, b);
  return abs(a);
}

const ll INF = 1e9 + 7;
const ll mod = 998244353;
const ll BIG_INF = 1e18 + 7;
const ll N = 1e6 + 7;
const ll T = 1 << 20;
const ld inf = 1e18;

ll m, n, k, q;
int tree_min[T * 2];
int lazy_min[T * 2];

void push_min(int u) {
  tree_min[u] += lazy_min[u];
  if (u < T) {
    lazy_min[u * 2] += lazy_min[u];
    lazy_min[u * 2 + 1] += lazy_min[u];
  }
  lazy_min[u] = 0;
}

int ask_min(int pocz, int kon, int u = 1, int lo = 0, int hi = T - 1) {
  push_min(u);
  if (kon < lo or hi < pocz)
    return INF;
  if (lo >= pocz and hi <= kon)
    return tree_min[u];
  int mid = (lo + hi) / 2;
  return min(ask_min(pocz, kon, u * 2, lo, mid),
             ask_min(pocz, kon, u * 2 + 1, mid + 1, hi));
}

void add_min(int pocz, int kon, int val, int u = 1, int lo = 0,
             int hi = T - 1) {
  push_min(u);
  if (kon < lo or hi < pocz)
    return;
  if (lo >= pocz and hi <= kon) {
    lazy_min[u] += val;
    push_min(u);
    return;
  }
  int mid = (lo + hi) / 2;
  add_min(pocz, kon, val, u * 2, lo, mid);
  add_min(pocz, kon, val, u * 2 + 1, mid + 1, hi);
  tree_min[u] = min(tree_min[u * 2], tree_min[u * 2 + 1]);
}

int tree_max[T * 2];
int lazy_max[T * 2];

void push_max(int u) {
  tree_max[u] += lazy_max[u];
  if (u < T) {
    lazy_max[u * 2] += lazy_max[u];
    lazy_max[u * 2 + 1] += lazy_max[u];
  }
  lazy_max[u] = 0;
}

int ask_max(int pocz, int kon, int u = 1, int lo = 0, int hi = T - 1) {
  push_max(u);
  if (kon < lo or hi < pocz)
    return -INF;
  if (lo >= pocz and hi <= kon)
    return tree_max[u];
  int mid = (lo + hi) / 2;
  return max(ask_max(pocz, kon, u * 2, lo, mid),
             ask_max(pocz, kon, u * 2 + 1, mid + 1, hi));
}

void add_max(int pocz, int kon, int val, int u = 1, int lo = 0,
             int hi = T - 1) {
  push_max(u);
  if (kon < lo or hi < pocz)
    return;
  if (lo >= pocz and hi <= kon) {
    lazy_max[u] += val;
    push_max(u);
    return;
  }
  int mid = (lo + hi) / 2;
  add_max(pocz, kon, val, u * 2, lo, mid);
  add_max(pocz, kon, val, u * 2 + 1, mid + 1, hi);
  tree_max[u] = max(tree_max[u * 2], tree_max[u * 2 + 1]);
}

void solve() {
  string s;
  cin >> s;

  int pref = 0;
  for (int i = 0; i < sz(s); i++) {
    if (s[i] == '0')
      pref--;
    else
      pref++;
    add_max(i + 1, i + 1, pref);
    add_min(i + 1, i + 1, pref);
  }

  int mini = ask_min(0, sz(s));

  // cout << "PRZED OBYDWOMA " << endl;

  // for(int i = 1; i <= sz(s) + 1; i++){
  // 	for(int j = 0; j < sz(s) + 2 - i; j++){
  // 		cout << ask_max(j, j + i - 1) << ' ';
  // 	}
  // 	cout << endl;
  // }

  for (int i = 0; i < sz(s); i++)
    if (s[i] == '?') {
      if (ask_min(i + 1, sz(s)) > mini + 1) {
        add_max(i + 1, sz(s), -2);
        add_min(i + 1, sz(s), -2);
      }
    }

  // cout << "PO PJERSZYM" << endl;
  // for(int i = 1; i <= sz(s) + 1; i++){
  // 	for(int j = 0; j < sz(s) + 2 - i; j++)
  // 		cout << ask_min(j, j + i - 1) << ' ';
  // 	cout << endl;
  // }
  // for(int i = 1; i <= sz(s) + 1; i++){
  // 	for(int j = 0; j < sz(s) + 2 - i; j++)
  // 		cout << ask_max(j, j + i - 1) << ' ';
  // 	cout << endl;
  // }

  int opcja1 = ask_max(0, sz(s)) - ask_min(0, sz(s));

  FOR(i, T * 2) { tree_max[i] = tree_min[i] = lazy_max[i] = lazy_min[i] = 0; }

  pref = 0;
  for (int i = 0; i < sz(s); i++) {
    if (s[i] == '0')
      pref--;
    else
      pref++;
    add_max(i + 1, i + 1, pref);
    add_min(i + 1, i + 1, pref);
  }

  // cout << "PRZED DRUGIM " << endl;

  // for(int i = 1; i <= sz(s) + 1; i++){
  // 	for(int j = 0; j < sz(s) + 2 - i; j++){
  // 		cout << ask_max(j, j + i - 1) << ' ';
  // 	}
  // 	cout << endl;
  // }

  mini = ask_min(0, sz(s));

  for (int i = 0; i < sz(s); i++)
    if (s[i] == '?') {
      if (ask_min(i + 1, sz(s)) > mini + 1 or
          (ask_min(i + 1, sz(s)) == mini + 1 and
           ask_max(i + 1, sz(s)) > ask_max(0, i))) {
        add_max(i + 1, sz(s), -2);
        add_min(i + 1, sz(s), -2);
      }
    }

  // cout << "PO DRUGIM" << endl;
  // for(int i = 1; i <= sz(s) + 1; i++){
  // 	for(int j = 0; j < sz(s) + 2 - i; j++){
  // 		cout << ask_min(j, j + i - 1) << ' ';
  // 	}
  // 	cout << endl;
  // }
  // for(int i = 1; i <= sz(s) + 1; i++){
  // 	for(int j = 0; j < sz(s) + 2 - i; j++){
  // 		cout << ask_max(j, j + i - 1) << ' ';
  // 	}
  // 	cout << endl;
  // }

  cout << min(opcja1, ask_max(0, sz(s)) - ask_min(0, sz(s))) << '\\n';
}

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

  q = 1;
  // cin >> q;
  while (q--)
    solve();
}