Problem:
Score : 800 points

Problem Statement

Given is a string S, where each character is 0, 1, or ?.

Consider making a string S' by replacing each occurrence of ? with 0 or 1 (we can choose the character for each ? independently).
Let us define the unbalancedness of S' as follows:

(The unbalancedness of S') = \max \{ The absolute difference between the number of occurrences of 0 and 1 between the l-th and r-th character of S (inclusive) :\ 1 \leq l \leq r \leq |S|\}

Find the minimum possible unbalancedness of S'.

Constraints

1 \leq |S| \leq 10^6

Each character of S is 0, 1, or ?.

Input

Input is given from Standard Input in the following format:

S

Output

Print the minimum possible unbalancedness of S'.

Sample Input 1

0??

Sample Output 1

1

We can make S'= 010 and achieve the minimum possible unbalancedness of 1.

Sample Input 2

0??0

Sample Output 2

2

Sample Input 3

??00????0??0????0?0??00??1???11?1?1???1?11?111???1

Sample Output 3

4

Solution in C++ (GCC 9.2.1) (judge verdict: Wrong Answer)

#include<bits/stdc++.h>
#define rep(i,n) for((i)=1;(i)<=(n);(i)++)
using namespace std;
int n,i,j,b[1000005],can_be_1[2],fa[1000005];
int fnd(int x){if(fa[x]==x)return x;return fa[x]=fnd(fa[x]);}
int get(int x){x=fnd(x);while(x&&!b[x]){fa[x]=fnd(x-1);x=fa[x];}return x;}
int ans,sa[1000005],sb[1000005],sc[1000005];
int stk[1000005],tp;
string st;
struct tri{
	int a,b,c;
};
tri a[1000005];int len;
struct seg{
	int mx,mi,mxs;
}tr[4000005];
seg operator +(seg x,seg y){
	seg z;
	z.mi=min(x.mi,y.mi);
	z.mx=max(x.mx,y.mx);
	if(x.mx==z.mx) z.mxs=x.mxs; else z.mxs=y.mxs;
	return z;
}
int tag[1000005];
void pushup(int x){
	tr[x]=tr[x+x]+tr[x+x+1];
}
void upd(int x,int y){
	tr[x].mx+=y;
	tr[x].mi+=y;
	tag[x]+=y;
}
void pushdo(int x){
	if(tag[x]){
		upd(x+x,tag[x]);
		upd(x+x+1,tag[x]);
		tag[x]=0;
	}
}
void build(int x,int l,int r){
	if(l==r){
		tr[x]=(seg){sa[l],sb[l],l};
		return;
	}
	int mid=(l+r)/2;
	build(x+x,l,mid);
	build(x+x+1,mid+1,r);
	pushup(x);
}
void update(int x,int l,int r,int ql,int qr,int c){
	if(ql<=l&&r<=qr){
		upd(x,c);return;
	}
	int mid=(l+r)/2;pushdo(x);
	if(ql<=mid)update(x+x,l,mid,ql,qr,c);
	if(qr>mid)update(x+x+1,mid+1,r,ql,qr,c);
	pushup(x); 
}
seg query(int x,int l,int r,int ql,int qr){
	if(ql<=l&&r<=qr){
		return tr[x];
	}
	int mid=(l+r)/2;pushdo(x);
	if(qr<=mid)return query(x+x,l,mid,ql,qr);
	if(ql>mid)return query(x+x+1,mid+1,r,ql,qr);
	return query(x+x,l,mid,ql,qr)+query(x+x+1,mid+1,r,ql,qr);
}
void print1(int x,int l,int r){
	if(l==r){
		cerr<<tr[x].mx<<' ';
		return;
	}
	int mid=(l+r)/2;
	pushdo(x); 
	print1(x+x,l,mid);
	print1(x+x+1,mid+1,r);
}
void print2(int x,int l,int r){
	if(l==r){
		cerr<<tr[x].mi<<' ';
		return;
	}
	int mid=(l+r)/2;
	pushdo(x); 
	print2(x+x,l,mid);
	print2(x+x+1,mid+1,r);
}
int main(){
	can_be_1[0]=can_be_1[1]=1;
	cin>>st;n=st.size();
	a[++len]=(tri){0,0,0};
	int ca=0,cb=0,cc=0,cd=0;
	rep(i,n){
		if(cd&&st[i-1]!='?'){
			b[len]=cd;
			cd=0;
		}
		if(st[i-1]=='0'){
			can_be_1[(i&1)^1]=0;
			ca=max(ca,++cc);
		}
		if(st[i-1]=='1'){
			can_be_1[(i&1)]=0;
			cb=min(cb,--cc);
		}
		if(st[i-1]=='?'){
			if(!cd){
				a[++len]=(tri){ca,cb,cc};
				ca=cb=cc=0;
			}
			cd++;
		}
	}
	if(cd) b[len]=cd;
	a[++len]=(tri){ca,cb,cc};
	n=len;
	rep(i,n){
		sa[i]=sc[i-1]+b[i-1]+a[i].a;
		sb[i]=sc[i-1]+b[i-1]+a[i].b;
		sc[i]=sc[i-1]+a[i].c+b[i-1];
	}
	build(1,1,n);
	ans=tr[1].mx-tr[1].mi;
	set<pair<int,int> > lst;
	rep(i,n)fa[i]=i;
	for(;;){
		seg tmp=tr[1];
		int pos=get(tmp.mxs-1);
		if(tmp.mx==0||pos<=1) break;
		seg tl=query(1,1,n,1,pos);
		int tt=min((tmp.mx-tl.mx+1)/2,b[pos]);
		b[pos]-=tt;
		assert(tt);
		update(1,1,n,pos+1,n,-(tt-1)*2);
		ans=min(ans,tr[1].mx-tr[1].mi);
		update(1,1,n,pos+1,n,-2);
		ans=min(ans,tr[1].mx-tr[1].mi);
		if(tmp.mx-tt*2<tl.mx){lst.insert(make_pair(pos+1,tmp.mxs));
			set<pair<int,int> >::iterator it=lst.upper_bound(make_pair(pos+1,tmp.mxs));
			if(it!=lst.end()){
				update(1,1,n,it->first,n,2);
				b[it->first]++;
				fa[it->first]=fa[it->second]=it->first;
				ans=min(ans,tr[1].mx-tr[1].mi);
			}
		}
//		print1(1,1,n);cerr<<endl;
//		print2(1,1,n);cerr<<endl<<endl;
	}
	if(lst.size()){
		update(1,1,n,lst.begin()->first,n,2);
		ans=min(ans,tr[1].mx-tr[1].mi);
	}
	if(ans==0) ans=1;
	if(ans==1&&!can_be_1[0]&&!can_be_1[1]) ans=2;
	cout<<ans<<endl;
	return 0;
}