#include<bits/stdc++.h>
#define pb emplace_back
using namespace std;
using ll = long long;
const int maxn = 100010;
int n;
char w[maxn];
struct sgt {
	int mx[maxn<<1], mn[maxn<<1], tag[maxn<<1], sm[maxn<<1], bid[maxn<<1], sid[maxn<<1];
	void init() {
		for (int i = n;i < n+n;++i) bid[i] = sid[i] = i - n;
	}
	void add_node(int i, int val) {
		tag[i] += val, mx[i] += val, mn[i] += val, sm[i] += val;
	}
	void push(int i) {
		if (i < n && tag[i]) {
			add_node(i<<1, tag[i]);
			add_node(i<<1|1, tag[i]);
			tag[i] = 0;
		}
	}
	void update(int i) {
		if (i < n) {
			push(i);
			mx[i] = max(mx[i<<1], mx[i<<1|1]);
			mn[i] = min(mn[i<<1], mn[i<<1|1]);
			bid[i] = mx[i] == mx[i<<1] ? bid[i<<1] : bid[i<<1|1];
			sid[i] = mn[i] == mn[i<<1] ? sid[i<<1] : sid[i<<1|1];
		}
	}
	void add(int l, int r, int val) {
		if (val == 1) w[l] = '1';
		else w[l] = '0';
		l += n, r += n;
		int sl = l>>1, sr = r>>1;
		for (;l < r;l>>=1, r>>=1) {
			if (l&1) add_node(l++, val);
			if (r&1) add_node(--r, val);
		}
		for (;sl;sl>>=1, sr>>=1) update(sl), update(sr);
	}
	void pa(int p) {
		for (int i = 20;i > 0;--i) push(p>>i);
	}
	int sum(int l) {
		int res = 0;
		for (l += n;l;l>>=1)
			res += tag[l];
		return res;
	}
	pair<int,int> query(int l, int r) {
		if (l >= r) return {-1, -1};
		pa(l+=n), pa(r+=n);
		pair<int,int> rid{-1, -1}, res{INT_MIN, INT_MAX};
		auto getb = [&](int i) {
			if (mx[i] > res.first) res.first = mx[i], rid.first = bid[i];
			if (mn[i] < res.second) res.second = mn[i], rid.second = sid[i];
			if (mx[i] == res.first) rid.first = min(rid.first, bid[i]);
			if (mn[i] == res.second) rid.second = min(rid.second, sid[i]);
		};
		for (;l < r;l>>=1, r>>=1) {
			if (l&1) getb(l++);
			if (r&1) getb(--r);
		}
		return rid;
	}
	int cost() {
		return max(0, mx[1]) - mn[1];
	}
	pair<int,int> tov(auto a) {
		if (a.first == -1) return {0, 0};
		auto [l, r] = a;
		pa(l+=n), pa(r+=n);
		return {mx[l], mn[r]};
	}
}tree;
bool mk[maxn];
signed main(){
	ios_base::sync_with_stdio(0), cin.tie(0);
	cin >> w;
	n = strlen(w);
	tree.init();
	vector<int> pos[2];
	pos[0] = pos[1] = {-1};
	for (int i = 0;i < n;++i) 
		if (w[i] == '1') pos[1].pb(i);
		else if (w[i] == '0') pos[0].pb(i);
	pos[0].pb(n), pos[1].pb(n);

	for (int i = 0;i < n;++i)  {
		if (w[i] == '1')
			tree.add(i, n, 1);
		else if (w[i] == '0')
			tree.add(i, n, -1);
	}
	int up = 0, dn = 0, sum = 0;
	for (int i = 0;i < n;++i){
		if (w[i] == '?') {
			mk[i] = true;
			if (sum < 0) tree.add(i, n, 1);
			else if (sum > 0) tree.add(i, n, -1);
			else {
				int p0 = *lower_bound(pos[0].begin(), pos[0].end(), i), p1 = *lower_bound(pos[1].begin(), pos[1].end(), i);
				if (p0 < p1)
					tree.add(i, n, ((p0^i)&1) ? 1 : -1);
				else 
					tree.add(i, n, ((~p1^i)&1) ? 1 : -1);
			}
		}
		sum += w[i] == '1' ? 1 : -1;
	}
	for (int i = 0;i < n;++i) if (mk[i]) {
		int v = w[i] == '1' ? 1 : -1;
		int a = tree.cost();
//		assert(v == tree.sum(i) - (i ? tree.sum(i-1) : 0));
		tree.add(i, n, -v * 2);
		if (tree.cost() < a)
			w[i] ^= 1;
		else tree.add(i, n, v * 2), w[i] = v == 1 ? '1' : '0';
	}
//	for (int i = 0;i < n;++i)
//		cout << tree.sum(i) << ' ';
//	cout << '\n';
	
	cerr << w << '\n';
cout << tree.cost() << '\n';
//	tie(up, dn) = tree.tov(tree.query(0, n));
//	cout << up - dn << '\n';
}

