Problem:
C: 短絡評価
問題
直大くんと北大くんはゲームをしています。
北大くんは、まず以下の BNF で表される論理式を生成します。
<formula>  ::= <or-expr>
<or-expr>  ::= <and-expr>
             | <or-expr> "|" <and-expr>
<and-expr> ::= <term>
             | <and-expr> "&" <term>
<term>     ::= "(" <or-expr> ")" | "?"
&
は論理積を、
|
は論理和を表し、
&
の方が
|
より先に評価されます。
直大くんは、この論理式を（文字列として見て）左から読んでいき、
?
を見つけたとき以下の行動をします。
その
?
を
0
にしても
1
にしても論理式の評価結果が変わらないことが確定しているなら、何もせず読み進める。
そうでないなら、北大くんに 1 円払い、その
?
を
0
または
1
に書き換える。
論理式は以下のように評価されます。いわゆる普通の論理式です。
(0 & ?) == 0
(1 & 0) == 0
(1 & 1) == 1
(0 | 0) == 0
(0 | 1) == 1
(1 | ?) == 1
直大くんが論理式の評価結果を確定させるために支払う必要がある最小金額はいくらでしょう？ 評価結果を
0
にする場合と
1
にする場合でそれぞれ求めてください。
入力形式
上の BNF に従う論理式が一行で与えられます。
制約
論理式の長さは
2\times 10^5
を超えない。
出力形式
評価結果を
0
、
1
にするために必要な最小金額を空白区切りで出力してください。
入力例1
?&?|?&?|?&?
出力例1
3 2
0
にしたい場合は
0 0 0
で書き換えて
0&?|0&?|0&?
とし、
1
にしたい場合は
1 1
で書き換えて
1&1|?&?|?&?
とするのが最適です。
入力例2
?&?&?|?&?&?
出力例2
2 3
それぞれ
0&?&?|0&?&?
、
1&1&1|?&?&?
となります。
入力例3
(?|?|?)&?&?&?&?|?&?|?&?
出力例3
4 4

Submitted solutions:

code_snippet: #include<bits/stdc++.h>
#pragma GCC target("avx2")

#pragma GCC optimize("Ofast")

#pragma GCC optimize("O3")
#pragma GCC optimize("unroll-loops")
using namespace std;
#define lp(i,n) for(int i=0;i<(int)(n);i++)
#define lps(i,j,n) for(int i=j;i<n;i++)

#define fordebug int hoge;cin>>hoge;

#define DEKAI 1000000007
#define floot10 cout<<fixed<<setprecision(15)1
#define all(v) v.begin(),v.end()
double PI = acos(-1);

namespace {
#define __DECLARE__(C)						\
  template <typename T>						\
  std::ostream &operator<<(std::ostream &, const C<T> &);

#define __DECLAREM__(C)						\
  template <typename T, typename U>				\
  std::ostream &operator<<(std::ostream &, const C<T, U> &);

  __DECLARE__(std::vector)
  __DECLARE__(std::deque)
  __DECLARE__(std::set)
  __DECLARE__(std::stack)
  __DECLARE__(std::queue)
  __DECLARE__(std::priority_queue)
  __DECLARE__(std::unordered_set)
  __DECLAREM__(std::map)
  __DECLAREM__(std::unordered_map)

  template <typename T, typename U>
  std::ostream &operator<<(std::ostream &, const std::pair<T, U> &);
  template <typename... T>
  std::ostream &operator<<(std::ostream &, const std::tuple<T...> &);
  template <typename T, std::size_t N>
  std::ostream &operator<<(std::ostream &, const std::array<T, N> &);

  template <typename Tuple, std::size_t N>
  struct __TuplePrinter__ {
    static void print(std::ostream &os, const Tuple &t) {
      __TuplePrinter__<Tuple, N - 1>::print(os, t);
      os << ", " << std::get<N - 1>(t);
    }
  };

  template <typename Tuple>
  struct __TuplePrinter__<Tuple, 1> {
    static void print(std::ostream &os, const Tuple &t) { os << std::get<0>(t); }
  };

  template <typename... T>
  std::ostream &operator<<(std::ostream &os, const std::tuple<T...> &t) {
    os << '(';
    __TuplePrinter__<decltype(t), sizeof...(T)>::print(os, t);
    os << ')';
    return os;
  }

  template <typename T, typename U>
  std::ostream &operator<<(std::ostream &os, const std::pair<T, U> &v) {
    return os << '(' << v.first << ", " << v.second << ')';
  }

#define __INNER__                               \
  os << '[';                                    \
  for (auto it = begin(c); it != end(c);) {     \
    os << *it;                                  \
    os << (++it != end(c) ? ", " : "");         \
  }                                             \
  return os << ']';

  template <typename T, std::size_t N>
  std::ostream &operator<<(std::ostream &os, const std::array<T, N> &c) {
    __INNER__
      }

#define __DEFINE__(C)						\
  template <typename T>						\
  std::ostream &operator<<(std::ostream &os, const C<T> &c) {	\
    __INNER__							\
      }

#define __DEFINEM__(C)							\
  template <typename T, typename U>					\
  std::ostream &operator<<(std::ostream &os, const C<T, U> &c) {	\
    __INNER__								\
      }

#define __DEFINEW__(C, M1, M2)					\
  template <typename T>						\
  std::ostream &operator<<(std::ostream &os, const C<T> &c) {	\
    std::deque<T> v;						\
    for (auto d = c; !d.empty(); d.pop()) v.M1(d.M2());		\
    return os << v;						\
  }

  __DEFINE__(std::vector)
  __DEFINE__(std::deque)
  __DEFINE__(std::set)
  __DEFINEW__(std::stack, push_front, top)
  __DEFINEW__(std::queue, push_back, front)
  __DEFINEW__(std::priority_queue, push_front, top)
  __DEFINE__(std::unordered_set)
  __DEFINEM__(std::map)
  __DEFINEM__(std::unordered_map)
}


template <signed M, unsigned T>
struct mod_int {
  constexpr static signed MODULO = M;
  constexpr static unsigned TABLE_SIZE = T;

  signed x;

  mod_int() : x(0) {}

  mod_int(long long y) : x(static_cast<signed>(y >= 0 ? y % MODULO : MODULO - (-y) % MODULO)) {}

  mod_int(int y) : x(y >= 0 ? y % MODULO : MODULO - (-y) % MODULO) {}

  mod_int &operator+=(const mod_int &rhs) {
    if ((x += rhs.x) >= MODULO) x -= MODULO;
    return *this;
  }

  mod_int &operator-=(const mod_int &rhs) {
    if ((x += MODULO - rhs.x) >= MODULO) x -= MODULO;
    return *this;
  }

  mod_int &operator*=(const mod_int &rhs) {
    x = static_cast<signed>(1LL * x * rhs.x % MODULO);
    return *this;
  }

  mod_int &operator/=(const mod_int &rhs) {
    x = static_cast<signed>((1LL * x * rhs.inv().x) % MODULO);
    return *this;
  }

  mod_int operator-() const { return mod_int(-x); }

  mod_int operator+(const mod_int &rhs) const { return mod_int(*this) += rhs; }

  mod_int operator-(const mod_int &rhs) const { return mod_int(*this) -= rhs; }

  mod_int operator*(const mod_int &rhs) const { return mod_int(*this) *= rhs; }

  mod_int operator/(const mod_int &rhs) const { return mod_int(*this) /= rhs; }

  bool operator<(const mod_int &rhs) const { return x < rhs.x; }

  mod_int inv() const {
    assert(x != 0);
    if (x <= static_cast<signed>(TABLE_SIZE)) {
      if (_inv[1].x == 0) prepare();
      return _inv[x];
    } else {
      signed a = x, b = MODULO, u = 1, v = 0, t;
      while (b) {
        t = a / b;
        a -= t * b;
        std::swap(a, b);
        u -= t * v;
        std::swap(u, v);
      }
      return mod_int(u);
    }
  }

  mod_int pow(long long t) const {
    assert(!(x == 0 && t == 0));
    mod_int e = *this, res = mod_int(1);
    for (; t; e *= e, t >>= 1)
      if (t & 1) res *= e;
    return res;
  }

  mod_int fact() {
    if (_fact[0].x == 0) prepare();
    return _fact[x];
  }

  mod_int inv_fact() {
    if (_fact[0].x == 0) prepare();
    return _inv_fact[x];
  }

  mod_int choose(mod_int y) {
    assert(y.x <= x);
    return this->fact() * y.inv_fact() * mod_int(x - y.x).inv_fact();
  }

  static mod_int _inv[TABLE_SIZE + 1];

  static mod_int _fact[TABLE_SIZE + 1];

  static mod_int _inv_fact[TABLE_SIZE + 1];

  static void prepare() {
    _inv[1] = 1;
    for (int i = 2; i <= (int)TABLE_SIZE; ++i) {
      _inv[i] = 1LL * _inv[MODULO % i].x * (MODULO - MODULO / i) % MODULO;
    }
    _fact[0] = 1;
    for (unsigned i = 1; i <= TABLE_SIZE; ++i) {
      _fact[i] = _fact[i - 1] * int(i);
    }
    _inv_fact[TABLE_SIZE] = _fact[TABLE_SIZE].inv();
    for (int i = (int)TABLE_SIZE - 1; i >= 0; --i) {
      _inv_fact[i] = _inv_fact[i + 1] * (i + 1);
    }
  }
};

template <int M, unsigned F>
std::ostream &operator<<(std::ostream &os, const mod_int<M, F> &rhs) {
  return os << rhs.x;
}

template <int M, unsigned F>
std::istream &operator>>(std::istream &is, mod_int<M, F> &rhs) {
  long long s;
  is >> s;
  rhs = mod_int<M, F>(s);
  return is;
}

template <int M, unsigned F>
mod_int<M, F> mod_int<M, F>::_inv[TABLE_SIZE + 1];

template <int M, unsigned F>
mod_int<M, F> mod_int<M, F>::_fact[TABLE_SIZE + 1];

template <int M, unsigned F>
mod_int<M, F> mod_int<M, F>::_inv_fact[TABLE_SIZE + 1];

template <int M, unsigned F>
bool operator==(const mod_int<M, F> &lhs, const mod_int<M, F> &rhs) {
  return lhs.x == rhs.x;
}

template <int M, unsigned F>
bool operator!=(const mod_int<M, F> &lhs, const mod_int<M, F> &rhs) {
  return !(lhs == rhs);
}

const int MF = 1000010;
const int MOD = 1000000007;

using mint = mod_int<MOD, MF>;

mint binom(int n, int r) { return (r < 0 || r > n || n < 0) ? 0 : mint(n).choose(r); }

mint fact(int n) { return mint(n).fact(); }

mint inv_fact(int n) { return mint(n).inv_fact(); }

#define int long long
#define INF 10000000000000000
#define PI acos(-1)

struct node{
  int operation;
  // 0 ? 1 | 2 &
  node* left;
  node* right;
};
int it = 0;
vector<node> tree;

void parse(string &s,node* n){
  //cout<<s<<endl;
  vector<int> kt(s.size());
  int kstl=0;
  stack<int> st;
  lp(i,s.size()){
    if(s[i]=='('){
      kstl++;
      kt[i]=kstl;
      st.push(kstl);
    }
    else if(s[i]==')'){
      kt[i]=st.top();
      st.pop();
      
    }
    else{
      kt[i]=-1;
    }
  }
  int deleted=0;
  while(s[0]=='('&&s[s.size()-1]==')'){
    if(kt[deleted]!=kt[kt.size()-1-deleted])break;
    s=s.substr(1,s.size()-2);
    deleted++;
  }
  if(s=="?"){
    n->operation=0;
    return;
  }

  node* left = &tree[it];
  it++;
  node* right = &tree[it];
  it++;
  n->left = left;
  n->right = right;

  

  int sep = -1;
  // OR search
  int kst = 0;
  lp(i,s.size()){
    if(s[i]=='(')kst++;
    if(s[i]==')')kst--;
    if(s[i]=='|'){
      if(kst!=0)continue;
      sep=i;
      break;
    }
  }

  if(sep != -1){
    n->operation = 1;
    string l = s.substr(0, sep);
    string r = s.substr(sep+1,s.size()-sep-1);
    parse(l,left);
    parse(r,right);
    return;
  }
  
  // AND search
  kst = 0;
  lp(i,s.size()){
    if(s[i]=='(')kst++;
    if(s[i]==')')kst--;
    if(s[i]=='&'){
      if(kst!=0)continue;
      sep=i;
      break;
    }
  }

  if(sep != -1){
    n->operation = 2;
    string l = s.substr(0, sep);
    string r = s.substr(sep+1,s.size()-sep-1);
    parse(l,left);
    parse(r,right);
  }
  else{
    cout<<"???????????"<<endl;
    return;
  }
  return;
}

int solve(node* n, int target){
  int op = n->operation;
  //cout<<op<<endl;
  if(op==0)return 1;

  if(target==0){
    if(op==1){
      return solve(n->left,0)+solve(n->right,0);
    }
    if(op==2){
      return min(solve(n->left,0), solve(n->left, 1)+solve(n->right,0));
    }
  }
  if(target==1){
    if(op==1){
      return min(solve(n->left,1), solve(n->left, 0)+solve(n->right,1));
    }
    if(op==2){
      return solve(n->left,1)+solve(n->right, 1);  
    }
  }
  return DEKAI;
}

signed main(){
  string s;
  cin>>s;
  node simpl;
  tree.assign(s.size(), simpl);
  node* top = &tree[it];
  it++;
  parse(s,top);
  
  cout<<solve(top,0)<<" "<<solve(top,1)<<endl;
  return 0;
}
accuracy: 1
time_ms: 100
memory_kb: 63592
final_rank: 10

code_snippet: #include <bits/stdc++.h>
using namespace std;

struct data {
  long long a, b;
};

long long n;
string s;

void solve();
data calcor(int &id);
data calcand(int &id);
data calcterm(int &id);

int main() {
  cin >> s;
  n = s.size();
  solve();
  return 0;
}

void solve() {
  int id = 0;
  data res = calcor(id);
  cout << res.a << " " << res.b << endl;
}

data calcor(int &id) {
  data res = {0, (long long)1e10};
  vector<data> v;
  while(id < n) {
    v.push_back(calcand(id));
    if(s[id] == '|')
      ++id;
    else
      break;
  }
  for(int i = 0; i < v.size(); ++i) {
    res.b = min(res.b, res.a + v[i].b);
    res.a += v[i].a;
  }
  return res;
}
data calcand(int &id) {
  data res = {(long long)(1e10), 0};
  vector<data> v;
  while(id < n) {
    v.push_back(calcterm(id));
    if(s[id] == '&')
      ++id;
    else
      break;
  }
  res.a = v[0].a;
  for(int i = 0; i < v.size(); ++i) {
    res.a = min(res.a, res.b + v[i].a);
    res.b += v[i].b;
  }
  return res;
}

data calcterm(int &id) {
  data res = {1, 1};
  if(s[id] == '(') {
    res = calcor(++id);
    assert(s[id] == ')');
    ++id;
    return res;
  }
  assert(s[id] == '?');
  ++id;
  return res;
}
accuracy: 1
time_ms: 10
memory_kb: 3312
final_rank: 1

code_snippet: #include <bits/stdc++.h>
using namespace std;

struct data {
  long long a, b;
};

long long n;
string s;

void solve();
data calcor(int &id);
data calcand(int &id);
data calcterm(int &id);

int main() {
  cin >> s;
  n = s.size();
  solve();
  return 0;
}

void solve() {
  int id = 0;
  data res = calcor(id);
  cout << res.a << " " << res.b << endl;
}

data calcor(int &id) {
  data res = {0, (long long)1e10};
  vector<data> v;
  while(id < n) {
    if(s[id] == '|')
      ++id;
    else if(s[id] == ')')
      break;
    v.push_back(calcand(id));
  }
  for(int i = 0; i < v.size(); ++i) {
    res.b = min(res.b, res.a + v[i].b);
    res.a += v[i].a;
  }
  return res;
}
data calcand(int &id) {
  data res = {(long long)(1e10), 0};
  vector<data> v;
  while(id < n) {
    if(s[id] == '&')
      ++id;
    else if(s[id] != '?' && s[id] != '(')
      break;
    v.push_back(calcterm(id));
  }
  res.a = v[0].a;
  for(int i = 0; i < v.size(); ++i) {
    res.a = min(res.a, res.b + v[i].a);
    res.b += v[i].b;
  }
  return res;
}

data calcterm(int &id) {
  data res = {1, 1};
  if(s[id] == '(') {
    res = calcor(++id);
    assert(s[id] == ')');
    ++id;
    return res;
  }
  assert(s[id] == '?');
  ++id;
  return res;
}
accuracy: 1
time_ms: 10
memory_kb: 3312
final_rank: 1

code_snippet: #include <iostream>
#include <vector>
#include <queue>
#include <utility>
#include <string>
#define llint long long
#define inf 1e18

using namespace std;
typedef pair<llint, llint> P;

struct node{
	char c;
	vector<int> vec;
	node(){}
	node(char c){
		this->c = c;
	}
};

string s;
vector<node> tree;
int dp[200005][2];

int parseOR(int &p);

int parseTerm(int &p)
{
	if(s[p] == '('){
		p++;
		int ret = parseOR(p);
		p++;
		return ret;
	}
	else if(s[p] == '?'){
		tree.push_back(node('?'));
		p++;
		return tree.size()-1;
	}
}

int parseAND(int &p)
{
	tree.push_back(node('&'));
	int root = tree.size()-1;
	
	int res = parseTerm(p);
	tree[root].vec.push_back(res);
	
	while(1){
		if(s[p] == '&'){
			p++;
			int res = parseTerm(p);
			tree[root].vec.push_back(res);
		}
		else break;
	}
	return root;
}

int parseOR(int &p)
{
	tree.push_back(node('|'));
	int root = tree.size()-1;
	
	int res = parseAND(p);
	tree[root].vec.push_back(res);
	
	while(1){
		if(s[p] == '|'){
			p++;
			int res = parseAND(p);
			tree[root].vec.push_back(res);
		}
		else break;
	}
	return root;
}

void dfs(int v)
{
	//cout << v << endl;
	for(int i = 0; i < tree[v].vec.size(); i++) dfs(tree[v].vec[i]);
	
	dp[v][0] = dp[v][1] = 1e9;
	if(tree[v].c == '?') dp[v][0] = dp[v][1] = 1;
	if(tree[v].c == '|'){
		int sum = 0;
		for(int i = 0; i < tree[v].vec.size(); i++){
			int u = tree[v].vec[i];
			dp[v][1] = min(dp[v][1], sum + dp[u][1]);
			sum += dp[u][0];
		}
		dp[v][0] = sum;
	}
	if(tree[v].c == '&'){
		int sum = 0;
		for(int i = 0; i < tree[v].vec.size(); i++){
			int u = tree[v].vec[i];
			dp[v][0] = min(dp[v][0], sum + dp[u][0]);
			sum += dp[u][1];
		}
		dp[v][1] = sum;
	}
}

int main(void)
{
	ios::sync_with_stdio(0);
	cin.tie(0);
	
	cin >> s;
	s += "#";
	
	int p = 0;
	int root = parseOR(p);
	
	/*for(int i = 0; i < tree.size(); i++){
		for(int j = 0; j < tree[i].vec.size(); j++) cout << tree[i].vec[j] << " "; cout << endl;
	}*/
	
	dfs(root);
	cout << dp[root][0] << " " << dp[root][1] << endl;
	
	return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 15656
final_rank: 7

code_snippet: #define _USE_MATH_DEFINES
#include <bits/stdc++.h>
using namespace std;

#define INF_LL (int64)1e18
#define INF (int64)1e9
#define REP(i, n) for(int64 i = 0; i < (n); i++)
#define FOR(i, a, b) for(int64 i = (a); i < (b); i++)
#define all(x) x.begin(),x.end()
#define fs first
#define sc second

using int32 = int_fast32_t;
using int64 = int_fast64_t;
using PII = pair<int32, int32>;
using PLL = pair<int64, int64>;

template<typename A, typename B> inline void chmin(A &a, B b) { if(a > b) a = b; }
template<typename A, typename B> inline void chmax(A &a, B b) { if(a < b) a = b; }

template<typename T>
vector<T> make_v(size_t a) { return vector<T>(a); }

template<typename T, typename... Ts>
auto make_v(size_t a, Ts... ts) {
    return vector<decltype(make_v<T>(ts...))>(a, make_v<T>(ts...));
}

template<typename T,typename U,typename... V>
typename enable_if<is_same<T, U>::value!=0>::type
fill_v(U &u,const V... v){u=U(v...);}

template<typename T,typename U,typename... V>
typename enable_if<is_same<T, U>::value==0>::type
fill_v(U &u,const V... v){
    for(auto &e:u) fill_v<T>(e,v...);
}

string s;

int64 om[212345][2], am[212345][2], term_m[212345][2];
int64 om_s[212345][2], am_s[212345][2], term_m_s[212345][2];
int64 or_exp(const string&, int64&, int64);
int64 and_exp(const string&, int64&, int64);
int64 term(const string&, int64&, int64);

int64 formula(const string& s, int64& p, int64 tar) {
    return or_exp(s, p, tar);
}

int64 or_exp(const string& s, int64& p, int64 tar) {
    if (~om[p][tar]) {
        int64 q = p;
        p = om_s[p][tar];
        return om[q][tar];
    }
    int64 q = p;
    int64 &ret = om[p][tar], &rs = om_s[p][tar];
    ret = and_exp(s, p, tar);
//    cout << "or " << p << " " << q << ": " << endl;
    p = q;
//    cout << "or (" << p << " " << q << ") " << endl;
    int64 sum = and_exp(s, p, 1-tar);
//    cout << "or (" << p << " " << q << ") " << endl;
    while (p < s.size() && s[p] == '|') {
        p++;
        if (tar == 0) {
            ret += and_exp(s, p, tar);
        } else {
            q = p;
            chmin(ret, sum + and_exp(s, p, tar));
            p = q;
            sum += and_exp(s, p, 1-tar);
        }
    }
//    cout << "or " << p << " " << tar << " " << ret << endl;
    rs = p;
    return ret;
}

int64 and_exp(const string& s, int64& p, int64 tar) {
    if (~am[p][tar]) {
        int64 q = p;
        p = am_s[p][tar];
        return am[q][tar];
    }
    int64 &ret = am[p][tar], &rs = am_s[p][tar];
    int64 q = p;
    ret = term(s, p, tar);
    p = q;
    int64 sum = term(s, p, 1-tar);
//    cout << "and (" << q << " " << p << ") " << endl;
    while (p < s.size() && s[p] == '&') {
        p++;
        if (tar == 1) {
            ret += term(s, p, tar);
        } else {
            q = p;
            chmin(ret, sum + term(s, p, tar));
            p = q;
            sum += term(s, p, 1-tar);
        }
    }
    rs = p;
    return ret;
}

int64 term(const string& s, int64& p, int64 tar) {
    if (~term_m[p][tar]) {
        int64 q = p;
        p = term_m_s[p][tar];
        return term_m[q][tar];
    }
    int64& ret = term_m[p][tar], &rs = term_m_s[p][tar];
    if (s[p] == '(') {
        p++;
        ret = or_exp(s, p, tar);
        p++;
    } else {
        p++;
        ret = 1;
    }
    rs = p;
//    cout << "term " << p << " " << tar << " " << ret << endl;
    return ret;
}

int main(void) {
    memset(om, -1, sizeof om);
    memset(am, -1, sizeof am);
    memset(term_m, -1, sizeof term_m);
    cin >> s;
    REP(i, 2) {
        int64 p = 0;
        cout << formula(s, p, i) << (i == 0 ? " " : "");
    }

    cout << endl;
}
accuracy: 1
time_ms: 10
memory_kb: 22684
final_rank: 8

code_snippet: #include <bits/stdc++.h>
using namespace std;

string S;
int pt;
int target;

pair<int, int> calc_or(), calc_and(), calc_term();

pair<int, int> calc_or(){
    vector<int> ret0, ret1;
    while(true){
        auto r = calc_and();
        ret0.push_back(r.first);
        ret1.push_back(r.second);
        if(S[pt] == '|'){
            pt++;
        }else{
            break;
        }
    }

    int sz = ret0.size();
    int ans0 = accumulate(ret0.begin(), ret0.end(), 0);
    int ans1 = ret1[0], sum = 0;
    for(int i=0; i<sz-1; i++){
        sum += ret0[i];
        ans1 = min(ans1, sum + ret1[i+1]);
    }
    return {ans0, ans1};
}

pair<int, int> calc_and(){
    vector<int> ret0, ret1;
    while(true){
        auto r = calc_term();
        ret0.push_back(r.first);
        ret1.push_back(r.second);
        if(S[pt] == '&'){
            pt++;
        }else{
            break;
        }
    }

    int sz = ret0.size();
    int ans1 = accumulate(ret1.begin(), ret1.end(), 0);
    int ans0 = ret0[0], sum = 0;
    for(int i=0; i<sz-1; i++){
        sum += ret1[i];
        ans0 = min(ans0, sum + ret0[i+1]);
    }
    return {ans0, ans1};
}

pair<int, int> calc_term(){
    if(S[pt] == '?'){
        pt++;
        return {1, 1};
    }else{
        pt++;
        auto ret = calc_or();
        pt++;
        return ret;
    }
}

int main(){

    cin >> S;
    S.push_back('$');

    pt = 0;
    auto ans = calc_or();
    cout << ans.first << " " << ans.second << endl;
    return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 3336
final_rank: 3

code_snippet: #include <bits/stdc++.h>

using namespace std;
typedef long long ll;
const ll MOD = 1e9 + 7;
const ll INF = 1e13;

struct Node {
    char type;
    vector<Node> child;
    Node(char _type) {
        type = _type;
    }
    void trav(string ind) {
        cout << ind << type << endl;
        for(Node node : child)
            node.trav(ind + " ");
    }
    int need0() {
        if(type == '&') {
            return min(child[0].need1() + child[1].need0(), child[0].need0());
        } else if(type == '|') {
            return child[0].need0() + child[1].need0();
        } else {
            return 1;
        }
    }
    int need1() {
        if(type == '|') {
            return min(child[0].need0() + child[1].need1(), child[0].need1());
        } else if(type == '&') {
            return child[0].need1() + child[1].need1();
        } else {
            return 1;
        }
    }
};

int main() {
    string S;
    cin >> S;
    stack<char> st;
    vector<Node> nodes;
    for(int i = 0; i < S.size(); ++i) {
        char c = S[i];
        if(c == '&') {
            while(!st.empty() && st.top() == '&') {
                nodes.push_back(Node('&'));
                st.pop();
            }
            st.push('&');
        } else if(c == '|') {
            while(!st.empty() && st.top() != '(') {
                nodes.push_back(Node(st.top()));
                st.pop();
            }
            st.push('|');
        } else if(c == '?') {
            nodes.push_back(Node(c));
        } else if(c == '(') {
            st.push('(');
        } else {
            while(!st.empty() && st.top() != '(') {
                nodes.push_back(Node(st.top()));
                st.pop();
            }
            st.pop();
        }
    }
    while(!st.empty()) {
        nodes.push_back(Node(st.top()));
        st.pop();
    }
    stack<Node> nst;
    for(int i = 0; i < nodes.size(); ++i) {
        Node node = nodes[i];
        if(node.type == '?') {
            nst.push(node);
        } else if(node.type == '&') {
            Node n2 = nst.top();
            nst.pop();
            Node n1 = nst.top();
            nst.pop();
            node.child.push_back(n1);
            node.child.push_back(n2);
            nst.push(node);
        } else {
            Node n2 = nst.top();
            nst.pop();
            Node n1 = nst.top();
            nst.pop();
            node.child.push_back(n1);
            node.child.push_back(n2);
            nst.push(node);
        }
    }
    Node root = nst.top();
    cout << root.need0() << " " << root.need1() << endl;
    return 0;
}
accuracy: 1
time_ms: 390
memory_kb: 24384
final_rank: 11

code_snippet: #include <iostream>
#include <vector>
#include <string>
#include <cmath>
#include <algorithm>
#include <utility>
#include <queue>
#include <set>
#include <map>
#include <deque>
#include <iomanip>
#include <cstdio>
#include <stack>
#include <numeric>

using namespace std;
typedef  long long ll;
typedef pair<int,int> PII;
typedef vector<int> VI;
typedef vector<VI> VVI;
#define  MP make_pair
#define  PB push_back
#define inf 1000000007
#define mod 1000000007
#define rep(i,n) for(int i=0;i<(int)(n);++i)
int n;
string s;
// 四則演算の式をパースして、その評価結果を返す。
pair<int,int> expression(int &begin);

// 乗算除算の式をパースして、その評価結果を返す。
pair<int,int> term(int &begin);
// 数字の列をパースして、その数を返す。
pair<int,int> number(int &begin);
pair<int,int> number(int &begin) {
    int ret = 1;
    begin++;
    return MP(1,1);
}
pair<int,int> factor(int &begin) {
    if (s[begin]== '(') {
        begin++; // '('を飛ばす。
        pair<int,int> ret = expression(begin);
        begin++; // ')'を飛ばす。
        return ret;
    } else {
        return number(begin);
    }
}
pair<int,int> term(int &begin) {
    pair<int,int> ret = factor(begin);
    vector<pair<int,int> > v;
    v.push_back(ret);
    for (;;) {
        if(begin==n)break;
        if(s[begin]!='&')break;
        begin++;
        pair<int,int> p = factor(begin);
        v.push_back(p);
    }
    pair<int,int> res=MP(inf,inf);
    int smz = 0;
    int smo = 0;
    for(auto x:v){
        res.first = min(res.first,smo + x.first);
        smz += x.first;
        smo += x.second;

    }
    res.second = min(res.second,smo);
    
    return res;
}

pair<int,int> expression(int &begin) {
    pair<int,int> ret = term(begin);
    vector<pair<int,int> > v;
    v.push_back(ret);
    for (;;) {
        if(begin==n)break;
        if (s[begin] != '|') {
           break;
        }
        begin++;
        pair<int,int> p = term(begin);
        v.push_back(p);
    }
    pair<int,int> res=MP(inf,inf);
    int smz = 0;
    int smo = 0;
    for(auto x:v){
        res.second = min(res.second,smz + x.second);
        smz += x.first;
        smo += x.second;

    }
    res.first = min(res.first,smz);
    return res;
}
int main(){
    cin >> s;
    n = s.size();
    int id = 0;
    pair<int,int> res = expression(id);
    cout << res.first << " " << res.second << endl;
    return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 3336
final_rank: 3

code_snippet: #include <bits/stdc++.h>

using namespace std;

using int64 = long long;
const int mod = 1e9 + 7;

const int64 infll = (1LL << 60) - 1;
const int64 infll2 = (1LL << 58) - 1;
const int inf = (1 << 30) - 1;


template< typename T1, typename T2 >
ostream &operator<<(ostream &os, const pair< T1, T2 > &p) {
  os << p.first << " " << p.second;
  return os;
}

template< typename T1, typename T2 >
istream &operator>>(istream &is, pair< T1, T2 > &p) {
  is >> p.first >> p.second;
  return is;
}

template< typename T >
ostream &operator<<(ostream &os, const vector< T > &v) {
  for(int i = 0; i < (int) v.size(); i++) {
    os << v[i] << (i + 1 != v.size() ? " " : "");
  }
  return os;
}

template< typename T >
istream &operator>>(istream &is, vector< T > &v) {
  for(T &in : v) is >> in;
  return is;
}

template< typename T1, typename T2 >
inline bool chmax(T1 &a, T2 b) { return a < b && (a = b, true); }

template< typename T1, typename T2 >
inline bool chmin(T1 &a, T2 b) { return a > b && (a = b, true); }

template< typename T = int64 >
vector< T > make_v(size_t a) {
  return vector< T >(a);
}

template< typename T, typename... Ts >
auto make_v(size_t a, Ts... ts) {
  return vector< decltype(make_v< T >(ts...)) >(a, make_v< T >(ts...));
}

template< typename T, typename V >
typename enable_if< is_class< T >::value == 0 >::type fill_v(T &t, const V &v) {
  t = v;
}

template< typename T, typename V >
typename enable_if< is_class< T >::value != 0 >::type fill_v(T &t, const V &v) {
  for(auto &e : t) fill_v(e, v);
}

const int OR = 0;
const int AND = 1;
const int QUESTION = 3;

map< int, int > dp[2];
int latte = 2;

struct Node {
  int type;
  int id;
  vector< Node * > child;

  Node(int t) : type(t), id(latte++) {}


  int dfs(int v) {
    if(dp[v].count(id)) {
      return dp[v][id];
    }
    int ret = inf;

    if(type == OR) {
      if(v == 1) {
        int add = 0;
        for(auto &t : child) {
          chmin(ret, t->dfs(v) + add);
          add += min(t->dfs(0), t->dfs(1));
        }
      } else {
        ret = 0;
        for(auto &t : child) {
          ret += t->dfs(v);
        }
      }
    } else if(type == AND) {
      if(v == 1) {
        ret = 0;
        for(auto &t : child) {
          ret += t->dfs(v);
        }
      } else {
        int add = 0;
        for(auto &t : child) {
          chmin(ret, t->dfs(v) + add);
          add += min(t->dfs(0), t->dfs(1));
        }
      }
    } else if(type == QUESTION) {
      ret = 1;
    } else {
      assert(0);
    }
    return dp[v][id] = ret;
  }
};

string S;
int ptr;

Node *or_expr();

Node *term() {
  if(S[ptr] == '?') {
    Node *cur = new Node(QUESTION);
    ++ptr;
    return cur;
  } else if(S[ptr] == '(') {
    ++ptr;
    auto ret = or_expr();
    ++ptr;
    return ret;
  } else {
    assert(0);
  }
}

Node *and_expr() {
  Node *cur = new Node(AND);
  cur->child.emplace_back(term());
  while(S[ptr] == '&') {
    ++ptr;
    cur->child.emplace_back(term());
  }
  return cur;
}

Node *or_expr() {
  Node *cur = new Node(OR);
  cur->child.emplace_back(and_expr());
  while(S[ptr] == '|') {
    ++ptr;
    cur->child.emplace_back(and_expr());
  }
  return cur;
}


void ushitapunichiakun(string arg) {
  cin >> S;
  S += "$";
  auto root = or_expr();
  cout << root->dfs(0) << " " << root->dfs(1) << endl;
}

int main() {
  ushitapunichiakun("笑");
}
accuracy: 1
time_ms: 80
memory_kb: 28232
final_rank: 9

code_snippet: #include<bits/stdc++.h>
using namespace std;

struct X{
    int zero;
    int one;
};

const int INF=1e9;
X or_expr(int &p,string& s);
X and_expr(int &p,string& s);
X term(int &p,string& s);

X term(int& p,string& s){
    if(s[p]=='('){
        p++;
        X ret=or_expr(p,s);
        assert(s[p++]==')');
        return ret;
    }
    else{
        assert(s[p]=='?');
        p++;
        return X{1,1};
    }
}
X and_expr(int &p,string& s){
    vector<X> vec;
    while(p<s.size() && s[p]!=')' && s[p]!='|'){
        vec.push_back(term(p,s));
        if(s[p]=='&') p++;
    }
    int zero=INF;
    int sum=0;
    for(int i=0;i<vec.size();i++){
        zero=min(zero,sum+vec[i].zero);
        sum+=vec[i].one;
    }
    int one=0;
    for(int i=0;i<vec.size();i++){
        one+=vec[i].one;
    }
    return X{zero,one};
}

X or_expr(int &p,string& s){
    vector<X> vec;
    while(p<s.size() && s[p]!=')'){
        vec.push_back(and_expr(p,s));
        if(s[p]=='|') p++;
    }
    int one=INF;
    int sum=0;
    for(int i=0;i<vec.size();i++){
        one=min(one,sum+vec[i].one);
        sum+=vec[i].zero;
    }
    int zero=0;
    for(int i=0;i<vec.size();i++){
        zero+=vec[i].zero;
    }
    return X{zero,one};
}
int main(){
    string s;
    cin>>s;
    int p=0;
    auto ret=or_expr(p,s);
    cout<<ret.zero<<" "<<ret.one<<endl;
    return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 3336
final_rank: 3

code_snippet: #include <string>
#include <iostream>
#include <cstdio>
#include <vector>
#include <algorithm>
#include <cassert>
using namespace std;
const int INF = 1 << 28;

struct Parser {
    string s;
    vector<int> dp_f[2], dp_o[2], dp_a[2], dp_t[2];
    vector<int> nxt_f, nxt_o, nxt_a, nxt_t;
    Parser(string s_) : s(s_) {
        int N = s.size();
        dp_f[0] = dp_f[1] = vector<int>(N, -1);
        dp_o[0] = dp_o[1] = vector<int>(N, -1);
        dp_a[0] = dp_a[1] = vector<int>(N, -1);
        dp_t[0] = dp_t[1] = vector<int>(N, -1);
        nxt_f = nxt_o = nxt_a = nxt_t = vector<int>(N, -1);
    }

    int parse_formula(size_t &i, int mode) {
        vector<int> &dp = dp_f[mode], &nxt = nxt_f;
        // fprintf(stderr, "parse form: i = %d (%c), mode = %d\n", i, s[i], mode);
        if(dp[i] >= 0) {
            int v = dp[i];
            i = nxt[i];
            return v;
        }
        else {
            int r = i, v = parse_or_expr(i, mode);
            nxt[r] = i;
            dp[r] = v;
            return v;
        }
    }

    int parse_or_expr(size_t &i, int mode) {
        vector<int> &dp = dp_o[mode], &nxt = nxt_o;
        // fprintf(stderr, "parse or  : i = %d (%c), mode = %d\n", i, s[i], mode);
        if(dp[i] >= 0) {
            int v = dp[i];
            i = nxt[i];
            return v;
        }
        else {
            int res = INF, sum1 = 0, sum2 = 0, r = i;
            while(i < s.length()) {
                size_t k = i;
                int val1 = parse_and_expr(k, mode);
                k = i;
                int val2 = parse_and_expr(k, mode^1);
                i = k;

                // or して全体が mode になる
                // 0 の場合は全部 0 にしないとダメ
                // 1 の場合は 0, 0, ..., 0, 1 みたいになる
                if(mode == 1) {
                    res = min(res, sum2 + val1);
                }
                sum1 += val1;
                sum2 += val2;

                if(i < s.length()) {
                    if(s[i] == '|') i++;
                    else break;
                }
            }

            if(mode == 0) {
                res = min(res, sum1);
            }

            nxt[r] = i;
            dp[r] = res;
            return res;
        }
    }

    int parse_and_expr(size_t &i, int mode) {
        vector<int> &dp = dp_a[mode], &nxt = nxt_a;
        // fprintf(stderr, "parse and : i = %d (%c), mode = %d\n", i, s[i], mode);
        if(dp[i] >= 0) {
            int v = dp[i];
            i = nxt[i];
            return v;
        }
        else {
            int res = INF, sum1 = 0, sum2 = 0, r = i;
            while(i < s.length()) {
                size_t k = i;
                int val1 = parse_term(k, mode);
                k = i;
                int val2 = parse_term(k, mode^1);
                i = k;

                // and して全体が mode になる
                // 1 の場合は全部 1 にしないとダメ
                // 0 の場合は 1, 1, ..., 1, 0 みたいになる
                if(mode == 0) {
                    res = min(res, sum2 + val1);
                }
                sum1 += val1;
                sum2 += val2;

                if(i < s.length()) {
                    if(s[i] == '&') i++;
                    else break;
                }
            }

            if(mode == 1) {
                res = min(res, sum1);
            }
            
            nxt[r] = i;
            dp[r] = res;
            return res;
        }
    }

    int parse_term(size_t &i, int mode) {
        vector<int> &dp = dp_t[mode], &nxt = nxt_t;
        // fprintf(stderr, "parse term: i = %d (%c), mode = %d\n", i, s[i], mode);
        if(dp[i] >= 0) {
            int v = dp[i];
            i = nxt[i];
            return v;
        }
        else {
            int ans = 0, r = i;
            if(s[i] == '(') {
                i++;
                int v = parse_or_expr(i, mode);
                assert(s[i++] == ')');
                ans = v;
            }
            else {
                assert(s[i++] == '?');
                ans = 1;
            }

            nxt[r] = i;
            dp[r] = ans;
            return ans;
        }
    }

    int parse(int mode) {
        // fprintf(stderr, "# parse function (mode = %d)\n", mode);
        size_t begin_idx = 0;
        return parse_formula(begin_idx, mode);
    }

    void dump() {
        int N = s.size();
        for(int i=0; i<N; i++) {
            for(int m=0; m<2; m++) {
                fprintf(stderr, "[i = %d, m = %d] dp_f = %d, dp_o = %d, dp_a = %d, dp_t = %d\n", i, m, dp_f[m][i], dp_o[m][i], dp_a[m][i], dp_t[m][i]);
            }
        }
    }
};

int main() {
    string s; cin >> s;
    Parser p(s);
    int v0 = p.parse(0);
    int v1 = p.parse(1);
    // p.dump();
    printf("%d %d\n", v0, v1);
}
accuracy: 1
time_ms: 10
memory_kb: 12788
final_rank: 6