#include <bits/stdc++.h>
using namespace std;
template <typename T>
void ckmn(T &a, T b) {
  a = min(a, b);
}
template <typename T>
void ckmx(T &a, T b) {
  a = max(a, b);
}
int ri() {
  int x;
  scanf("%i", &x);
  return x;
}
void rd() {}
template <typename... T>
void rd(int &x, T &...args) {
  scanf("%i", &x);
  rd(args...);
}
template <typename... T>
void rd(long long &x, T &...args) {
  scanf("%lld", &x);
  rd(args...);
}
template <typename... T>
void rd(double &x, T &...args) {
  scanf("%lf", &x);
  rd(args...);
}
template <typename... T>
void rd(pair<int, int> &x, T &...args) {
  scanf("%i %i", &x.first, &x.second);
  rd(args...);
}
const int N = 1000050;
const int M = 2 * N;
int lzy[M], mx[M], mn[M], ls[M], rs[M], tsz, root;
void Build(int &c, int ss, int se, int a[]) {
  c = ++tsz;
  if (ss == se) {
    mn[c] = mx[c] = a[ss];
    return;
  }
  int mid = ss + se >> 1;
  Build(ls[c], ss, mid, a);
  Build(rs[c], mid + 1, se, a);
  mn[c] = min(mn[ls[c]], mn[rs[c]]);
  mx[c] = max(mx[ls[c]], mx[rs[c]]);
}
void Add(int c, int ss, int se, int qs, int qe, int x) {
  if (qs > qe || qs > se || ss > qe) return;
  if (qs <= ss && qe >= se) {
    lzy[c] += x;
    mn[c] += x;
    mx[c] += x;
    return;
  }
  int mid = ss + se >> 1;
  Add(ls[c], ss, mid, qs, qe, x);
  Add(rs[c], mid + 1, se, qs, qe, x);
  mn[c] = min(mn[ls[c]], mn[rs[c]]) + lzy[c];
  mx[c] = max(mx[ls[c]], mx[rs[c]]) + lzy[c];
}
int GetMax(int c, int ss, int se) {
  if (ss == se) return ss;
  int mid = ss + se >> 1;
  if (mx[ls[c]] + lzy[c] == mx[c])
    return GetMax(ls[c], ss, mid);
  else
    return GetMax(rs[c], mid + 1, se);
}
int GetMin(int c, int ss, int se) {
  if (ss == se) return ss;
  int mid = ss + se >> 1;
  if (mn[rs[c]] + lzy[c] == mn[c])
    return GetMin(rs[c], mid + 1, se);
  else
    return GetMin(ls[c], ss, mid);
}
void P(int c, int ss, int se, int add) {
  printf("%i (%i %i): %i %i %i\n", c, ss, se, mn[c], mx[c], lzy[c]);
  if (ss == se) {
    return;
  }
  int mid = ss + se >> 1;
  P(ls[c], ss, mid, add + lzy[c]);
  P(rs[c], mid + 1, se, add + lzy[c]);
}
char s[N];
int bal[N];
int main() {
  int n;
  scanf("%s", s + 1);
  n = strlen(s + 1);
  set<int> pos;
  for (int i = 1; i <= n; i++) {
    if (s[i] == '0')
      bal[i] = bal[i - 1] - 1;
    else
      bal[i] = bal[i - 1] + 1;
    if (s[i] == '?') pos.insert(i);
  }
  Build(root, 0, n, bal);
  set<int> was;
  int las = 1e9;
  int psp = 0;
  while (1) {
    int mnp = GetMin(root, 0, n);
    int mxp = GetMax(root, 0, n);
    if (mx[root] - mn[root] == 1) break;
    if (mnp > mxp) {
      auto it = pos.upper_bound(mxp);
      if (it != pos.begin()) {
        it--;
        Add(root, 0, n, *it, n, -2);
        was.insert(*it);
        int ans1 = mx[root] - mn[root];
        auto jt = was.upper_bound(*it);
        if (jt != was.end()) {
          Add(root, 0, n, *jt, n, 2);
          int ans2 = mx[root] - mn[root];
          if (ans2 < ans1) {
            pos.insert(*jt);
            was.erase(*jt);
          } else
            Add(root, 0, n, *jt, n, -2);
        }
        pos.erase(it);
      }
      break;
    }
    int tmp = mx[root];
    auto it = pos.upper_bound(mxp);
    if (it != pos.begin()) {
      it--;
      if (*it > mnp) {
        Add(root, 0, n, *it, n, -2);
        was.insert(*it);
        if (las == tmp + 1 && psp > mxp) {
          int mx1 = mx[root];
          auto jt = was.upper_bound(*it);
          if (jt != was.end()) {
            Add(root, 0, n, *jt, n, 2);
            int mx2 = mx[root];
            if (mx2 == mx1) {
              pos.insert(*jt);
              was.erase(*jt);
            } else
              Add(root, 0, n, *jt, n, -2);
          }
        }
        pos.erase(it);
      } else
        break;
    } else
      break;
    psp = mxp;
    las = tmp;
  }
  printf("%i\n", mx[root] - mn[root]);
  return 0;
}
