Problem:
E: Broccoli or Cauliflower
Problem
The input is a rooted tree
T = (V, E)
with
n
vertices. Note that
n
is odd and the vertex with index
1
is the root of
T
. In addition, we give a label
G
or
W
for each vertex. Let
T_v  = (U, F)
be a subtree of
T
such that
U
is defined as following.
U =
$\{$
u \in V \ \  | \ \  u
$\text{ is the descendant of }$
v
$\}$
We call
T_v
a subtree of
v
.
We consider the following operation and perform operations
q
times.
Let
v
be a vertex. If a vertex
u \in U
has the label
G
, then we change the label of
u
G
to
W
. Otherwise, we change the label of
u
W
to
G
.
After each operation, output “broccoli” if the number of vertices with the label
G
is greater than
W
. Otherwise, output “cauliflower”.
Input format
An input is the following format.
n
q
p_2
...
p_n
c_1
...
c_n
v_1
$\vdots$
v_q
In line
1
, there are two integers
n
and
q
, where
n
is the number of vertices in
T
and
q
is the number of queries. Note that
n
is odd.
In line
2
, there are
n - 1
integers
p_2
to
p_n
.
p_i
represents the parent of a vertex
v_i
.
In line
3
, there are
n
characters
c_1
to
c_n
.
c_i
represents the label of
v_i
. 
Finally, in line
j + 3
, there is an integer
v_j
. We perform the operation for
T_{v_j}
.
Constraints
1 \leq n \leq 100,000
(
n
is odd. )
1 \leq q \leq 100,000
1 \leq p_i < i
（
2 \leq i \leq n
）
c_j
is
G
or
W
.  (
1 \leq j \leq n
)
1 \leq v_i \leq n
（
1 \leq i \leq q
）
Output format
An output consists
q
lines and output “broccoli” or “cauliflower” in each line.
Input example 1
7 4
1 1 2 2 3 3
G G W W W G G 
2
1
3
4
Output example 1
broccoli
cauliflower
cauliflower
broccoli
Input example 2
17 18
1 1 1 3 1 4 2 4 3 6 10 9 3 4 5 15
W W W W W W W W G W G G W G W W W
6
7
1
9
14
6
4
5
3
7
8
13
9
6
14
12
9
13
Output example 2
cauliflower
cauliflower
broccoli
broccoli
broccoli
broccoli
broccoli
broccoli
broccoli
cauliflower
cauliflower
cauliflower
cauliflower
cauliflower
broccoli
cauliflower
cauliflower
cauliflower

Submitted solutions:

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

#define all(v) v.begin(),v.end()
using ll = long long;
using ull = unsigned long long;
using lll = __int128;
using vll=vector<ll>;
using vvll = vector<vector<ll>>;
using P = pair<ll,ll>;
using vp=vector<pair<ll, ll>>;
//using mint=modint1000000007;
//using mint=modint998244353;

const ll INF=1ll<<60;
ll mod10=1e9+7;
ll mod99=998244353;
const double PI = acos(-1);

#define rep(i,n) for (ll i=0;i<n;++i)
#define per(i,n) for(ll i=n-1;i>=0;--i)
#define rep2(i,a,n) for (ll i=a;i<n;++i)
#define per2(i,a,n) for (ll i=a;i>=n;--i)

template<class T>bool chmax(T &a, const T &b) { if (a<b) { a=b; return true; } return false; }
template<class T>bool chmin(T &a, const T &b) { if (b<a) { a=b; return true; } return false; }

template<typename Monoid, typename Operator, auto mapping>
struct SegTreeLazy {
    using MonoidType=typename Monoid::Type;
    using OperatorType=typename Operator::Type;
    SegTreeLazy()=default;

    /// @brief 要素数 n の遅延セグ木を構築する
    SegTreeLazy(int n) {
        this->n=n;
        dat=vector<MonoidType>(n<<1,Monoid::id());
        lazy=vector<OperatorType>(n<<1,Operator::id());
    }

    /// @brief 配列 v から遅延セグ木を構築する
    SegTreeLazy(const vector<MonoidType>& v) {
        this->n=v.size();
        dat=vector<MonoidType>(n<<1,Monoid::id());
        lazy=vector<OperatorType>(n<<1,Operator::id());
        for(int i=0; i<n; i++) dat[i+n]=v[i];
        for(int i=n-1; i>0; i--) dat[i]=Monoid::op(dat[i<<1],dat[i<<1|1]);
    }

    /// @brief i 番目の要素を x に更新する
    void set(int i, MonoidType x) {
        generate_indices(i,i+1);
        pushdown();
        i+=n;
        dat[i]=x;
        while(i>>=1) dat[i]=Monoid::op(dat[i<<1],dat[i<<1|1]);
    }

    /// @brief 区間 [l, r) に x を作用させる
    void apply(int l, int r, OperatorType x) {
        if(l==r) return;
        generate_indices(l,r);
        pushdown();
        l+=n; r+=n;
        while(l<r) {
            if(l&1) {
                lazy[l]=Operator::op(lazy[l],x);
                dat[l]=mapping(dat[l],x);
                l++;
            }
            if(r&1) {
                r--;
                lazy[r]=Operator::op(lazy[r],x);
                dat[r]=mapping(dat[r],x);
            }
            l>>=1; r>>=1;
        }
        pushup();
    }

    /// @brief 区間 [l, r) のモノイド積を返す
    MonoidType fold(int l, int r) {
        if(l==r) return Monoid::id();
        generate_indices(l,r);
        pushdown();
        MonoidType retl=Monoid::id(),retr=Monoid::id();
        l+=n; r+=n;
        while(l<r) {
            if(l&1) retl=Monoid::op(retl,dat[l++]);
            if(r&1) retr=Monoid::op(dat[--r],retr);
            l>>=1; r>>=1;
        }
        return Monoid::op(retl,retr);
    }

    /// @brief 区間 [l, x) のモノイド積が f を満たすような最大の x >= l を返す
    /// @attention `f(Monoid::id())=true` が成り立つ必要がある
    /// @note O(log(N))
    template<typename F>
    int find_right(int l, F f) {
        assert(f(Monoid::id()));
        if(l==n) return n;
        generate_indices(l,n);
        pushdown();
        l+=n;
        int r=n+n;
        vector<int> cand_l,cand_r;
        while(l<r) {
            if(l&1) cand_l.push_back(l++);
            if(r&1) cand_r.push_back(--r);
            l>>=1; r>>=1;
        }
        vector<int> cand=cand_l;
        reverse(cand_r.begin(),cand_r.end());
        cand.insert(cand.end(),cand_r.begin(),cand_r.end());
        MonoidType val=Monoid::id();
        for(int i:cand) {
            if(f(Monoid::op(val,dat[i]))) {
                val=Monoid::op(val,dat[i]);
            } else {
                while(i<n) {
                    propagate(i);
                    i<<=1;
                    if(f(Monoid::op(val,dat[i]))) {
                        val=Monoid::op(val,dat[i]);
                        i|=1;
                    }
                }
                return i-n;
            }
        }
        return n;
    }

    /// @brief 区間 [x, r) のモノイド積が f を満たすような最小の x<=r を返す
    /// @attention `f(Monoid::id())=true` が成り立つ必要がある
    /// @note O(log(N))
    template<typename F>
    int find_left(int r, F f) {
        assert(f(Monoid::id()));
        if(r==0) return 0;
        generate_indices(0,r);
        pushdown();
        r+=n;
        int l=n;
        vector<int> cand_l,cand_r;
        while(l<r) {
            if(l&1) cand_l.push_back(l++);
            if(r&1) cand_r.push_back(--r);
            l>>=1; r>>=1;
        }
        vector<int> cand=cand_r;
        reverse(cand_l.begin(),cand_l.end());
        cand.insert(cand.end(),cand_l.begin(),cand_l.end());
        MonoidType val=Monoid::id();
        for(int i:cand) {
            if(f(Monoid::op(dat[i],val))) {
                val=Monoid::op(dat[i],val);
            } else {
                while(i<n) {
                    propagate(i);
                    i=(i<<1)|1;
                    if(f(Monoid::op(dat[i],val))) {
                        val=Monoid::op(dat[i],val);
                        i^=1;
                    }
                }
                return i-n+1;
            }
        }
        return 0;
    }

    int size() { return n; }
    MonoidType operator[](int i) { return fold(i,i+1); }

private:
    int n;
    vector<MonoidType> dat;
    vector<OperatorType> lazy;
    vector<int> indices;
    void generate_indices(int l, int r) {
        indices.clear();
        l+=n; r+=n;
        int lm=(l/(l&-l))>>1,rm=(r/(r&-r))>>1;
        while(l<r) {
            if(l<=lm) indices.push_back(l);
            if(r<=rm) indices.push_back(r);
            l>>=1; r>>=1;
        }
        while(l) {
            indices.push_back(l);
            l>>=1;
        }
    }
    void propagate(int i) {
        if(i<n) {
            lazy[i<<1]=Operator::op(lazy[i<<1],lazy[i]);
            lazy[i<<1|1]=Operator::op(lazy[i<<1|1],lazy[i]);
            dat[i<<1]=mapping(dat[i<<1],lazy[i]);
            dat[i<<1|1]=mapping(dat[i<<1|1],lazy[i]);
        }
        lazy[i]=Operator::id();
    }
    void pushdown() {
        for(int j=(int)indices.size()-1; j>=0; j--) {
            int i=indices[j];
            propagate(i);
        }
    }
    void pushup() {
        for(int j=0; j<(int)indices.size(); j++) {
            int i=indices[j];
            dat[i]=Monoid::op(dat[i<<1],dat[i<<1|1]);
        }
    }
};


/// @brief モノイド
namespace Monoid {

 
    /// @brief （和，区間の長さ）
    template<typename T>
    struct SumPair {
        using Type=pair<T,int>;
        static Type id() { return make_pair(T(0),0); }
        static Type op(const Type& a, const Type& b) { return {(a.first+b.first),a.second+b.second}; }
    };
}


/// @brief 作用素
namespace Operator {
    /// @brief 更新
    template<typename T, T not_exist>
    struct Update {
        using Type=T;
        static Type id() { return not_exist; }
        static Type op(const Type& a, const Type& b) { return (a^b); }
    };

  
}


namespace RangeQuery {


    /// @brief 区間更新 / 区間和
    /// @tparam not_exist 存在しない値
    template<typename T, T not_exist>
    struct ApplyUpdate_GetSum {
        using S=typename Monoid::SumPair<T>::Type;
        static S mapping(const S& a, const T& b) { return b==0?a:S{a.second-a.first,a.second}; }
        using Type=struct SegTreeLazy<Monoid::SumPair<T>,Operator::Update<T,not_exist>,mapping>;
    };

 
   

  
}




//----------------------------------------------------------





struct HLD{
    int N;
    vector<int> si,par,head,dep;
    vector<int> hld;//ならべたやつ
    vector<int> idx;//hldの何番目にいるか
    vector<int> L,R;//[L[i],R[i])でiの部分木がとれる
    vector<vector<long long>>& ab;

    void dfs1(ll a,ll b){
        for(int i=0;i<ab[a].size();i++){
            int to=ab[a][i];
            if(to==b) continue;
            dep[to]=dep[a]+1;
            dfs1(to,a);
            si[a]+=si[to];
        }
        
        for(int i=0;i<ab[a].size();i++){
            if((ab[a][0]==b)||(ab[a][i]!=b&&si[ab[a][0]]<si[ab[a][i]])) swap(ab[a][0],ab[a][i]);
        }
    }

    void dfs2(ll a,ll b,ll h){
        idx[a]=hld.size();
        L[a]=hld.size();
        hld.emplace_back(a);
        head[a]=h;
        par[a]=b;
        for(int i=0;i<ab[a].size();i++){
            if(ab[a][i]==b) continue;
            if(i==0) dfs2(ab[a][i],a,h);
            else dfs2(ab[a][i],a,ab[a][i]);
        }
        R[a]=hld.size();
    }

    HLD(ll n,vector<vector<long long>>& ab2):N(n),ab(ab2){
        si.assign(N,1);
        par.assign(N,0);
        head.assign(N,0);
        dep.assign(N,0);
        idx.assign(N,0);
        L.assign(N,0);
        R.assign(N,0);
        dfs1(0,-1);   
        dfs2(0,-1,0);
    }

    int lca(int a,int b){
        while(head[a]!=head[b]){
            if(head[dep[a]]>head[dep[b]]) swap(a,b);
            b=par[head[b]];
        }
        return (dep[a]<dep[b]?a:b);
    }

    //a-bの辺をどのindexにsetすればいいかかえす 子から親に辺を張る
    int edgeid(ll a,ll b){
        if(dep[a]>dep[b]) swap(a,b);
        return idx[b];
    }
    //辺に対するクエリ　子から親に辺を張る
    void edgequery(ll a,ll b,vector<pair<ll,ll>>& R){
        while(head[a]!=head[b]){
            if(dep[head[a]]>dep[head[b]]) swap(a,b);
            R.emplace_back(idx[head[b]],idx[b]+1);
            b=par[head[b]];
        }
        if(dep[a]>dep[b]) swap(a,b);
        R.emplace_back(idx[a]+1,idx[b]+1);
    }

    //頂点をsetするときのindex
    int nodeid(ll a){
        return idx[a];
    }

    void nodequery(ll a,ll b,vector<pair<ll,ll>>& R){
        while(head[a]!=head[b]){
            if(dep[head[a]]>dep[head[b]]) swap(a,b);
            R.emplace_back(idx[head[b]],idx[b]+1);
            b=par[head[b]];
        }
        if(dep[a]>dep[b]) swap(a,b);
        R.emplace_back(idx[a],idx[b]+1);
    }

};


bool solve(){
    ll N,Q;cin>>N>>Q;
  
    vvll ab(N);
    rep(i,N-1){
        ll p;cin>>p;p--;
        ab[i+1].emplace_back(p);
        ab[p].emplace_back(i+1);
    }
    vll C(N);rep(i,N){
        char c;cin>>c;
        C[i]=(c=='G');
    }
    
    HLD hld(N,ab);
    vector<pair<ll,int>> init(N);rep(i,N) init[hld.nodeid(i)]={C[i],1};
    auto seg=RangeQuery::ApplyUpdate_GetSum<ll,0>::Type(init);
    rep(_,Q){
        ll v;cin>>v;v--;
        seg.apply(hld.L[v],hld.R[v],1);
        cout<<(seg.fold(0,N).first*2>N?"broccoli":"cauliflower")<<endl;
    }
    return 0;
}

int main(){
    cin.tie(0);
    ios::sync_with_stdio(false);
    ll T=1;//cin>>T;
    rep(i,T) solve();
}
accuracy: 1
time_ms: 130
memory_kb: 26600
final_rank: 17

code_snippet: #include <bits/stdc++.h>
#include <iostream>
#include <vector>
#include <string>
#include <stack>
#include <algorithm>
#include <iomanip>
#include <chrono>
#pragma GCC target ("avx")
#pragma GCC optimize("O3")
#pragma GCC optimize("unroll-loops")
#define rep(i,n) for (ll i = 0;i < (ll)(n);i++)
#define Yes cout << "Yes" << "\n"// YESの短縮
#define No cout << "No" << "\n"// NOの短縮
#define rtr0 return(0)//return(0)の短縮
#define gyakugen(x) modpow(x,mod - 2,mod);
#define agyakugen(x) modpow(x,amod - 2,amod);
#define st(A) sort(A.begin(),A.end());
#define rst(A) sort(A.rbegin(),A.rend());
using namespace std;
//using namespace ranges;
using ll = long long;//63bit型整数型
using ld = long double;//doubleよりも長い値を保存できるもの
using ull = unsigned long long;//符号がない64bit型整数
ll mod = 998244353;
ll amod = 1000000007;
ll MINF = -5000000000000000000;
ll INF = 5000000000000000000;
ll inf = 2000000000;
ll minf = -2000000000;
ll BAD = -1;
ll zero = 0;
ld EPS = 1e-10;
vector<ll>randomhash = {(ll)1e9 + 7,(ll)1e9 + 801,((ll)1e8 * 8) + 29,((ll)1e8 * 7) + 159,((ll)1e8 * 9) + 221};
vector<ll>tate = {0,-1,0,1};//グリッド上の全探索時の四方向の上下のチェック
vector<ll>yoko = {1,0,-1,0};//グリッド上の全探索時の四方向の右左のチェック
vector<ll>eightx = {0,-1,-1,-1,0,1,1,1};//グリッド上の全探索時の八方向の上下のチェック
vector<ll>eighty = {1,1,0,-1,-1,-1,0,1};//グリッド上の全探索時の八方向の右左のチェック
vector<ll>hexsax = {0,1,1,0,-1,-1};
vector<ll>hexsay = {1,1,0,-1,-1,0};
//返り値は素数のリスト。
vector < bool > isprime;
vector < ll > Era(int n){//書き方 vector<ll>[] = Era(x); とやるとxまでの素数が出てくる。
	isprime.resize(n, true);
	vector < ll > res;
	isprime[0] = false;
	isprime[1] = false;
	for(ll i = 2; i < n; ++i) isprime[i] = true;
	for(ll i = 2; i < n; ++i) {
		if(isprime[i]) {
			res.push_back(i);
			for(ll j = i * 2; j < n; j += i) isprime[j] = false;
		}
	}
	return res;
}
//　　　　　　素数判定 21~35
ull modmul(ull a,ull b,ull mod) {
    return (__uint128_t)a*b%mod;
}
ll modpow(ll a, ll n, ll mod) {
	ll res = 1;
	while (n > 0) {
		if (n & 1) res = res * a % mod;
		a = a * a % mod;
		n >>= 1;
	}
	return res;
}

long long npow(long long a, long long n){
    long long res = 1;
    while (n > 0) {
		if (n & 1) res = res * a;
		a = a * a;
		n >>= 1;
	}
	return res;
}
//     モッドを使った累乗
long long isqrt(long long num){
    return((long long)sqrtl(num));
}
ld get_theta(ld px,ld py,ld fx,ld fy,ld sx,ld sy){
    ld fxv = fx-px;
    ld fyv = fy-py;
    ld sxv = sx-px;
    ld syv = sy-py;
    ld fsv = fxv*sxv + fyv*syv;
    ld pfs = (ld)sqrt(fxv*fxv+fyv*fyv);
    ld pss = (ld)sqrt(sxv*sxv+syv*syv);
    return acos(fsv/(pfs*pss))*180/M_PI;
};
ld Euclidean_distance(ll x1,ll y1,ll x2,ll y2){
    ld x = abs((ld)x1 - (ld)x2);
    ld y = abs((ld)y1 - (ld)y2);
    return sqrt((x*x) + (y*y));
};
ll Manhattan_distance(ll x1,ll y1,ll x2,ll y2){
    return abs(x1-x2)+abs(y1-y2);
};
void change_bit(ll N,ll start,vector<ll>&X){
    for(ll i = start;i>=0;i--){
        ll a = npow(2,i);
        if(N/a==1){
            X[i]=1;
            N-=a;
        }
    }
}
template<class T>
struct rolling_hash{
    vector<ull>Power,hash,InvPower;
    ll B = 0;
    ll MOD = 0;
    void set_number(ll base,ll mod){
        B = base;
        MOD = mod;
    }
    void do_hash(const T &S) {
        ll N = S.size();
        Power.resize(N+1);
        InvPower.resize(N+1);
        hash.resize(N+1);
        Power[0] = 1;
        InvPower[0] = 1;
        for (ll i = 0;i<N;i++) {
            Power[i + 1] = modmul(Power[i],B,MOD);
            InvPower[i + 1] = modpow(Power[i+1],MOD-2,MOD);
            hash[i + 1] = (hash[i] + modmul(S[i], Power[i],MOD))%MOD;
        }
    }
    ll get_hash(ll l, ll r) {
        ull res = (hash[r]+MOD-hash[l])%MOD;
        res = modmul(res,InvPower[l],MOD);
        return res;
    }
};
template<class T>
struct combination{
  public:
    vector<T>factorial;
    ll MOD;
    ll N;
    void reset(T n,T mod){
        N = n+1;
        factorial.assign(N,1);
        MOD = mod;
    }
    void calu(){
        for(ll i = 1;i<N;i++){
            factorial[i] = (factorial[i-1]*(i))%MOD;
        }
    }
    T get(T n, T r){
        ll a = factorial[n];
        ll b = (factorial[r]*(factorial[n-r]))%MOD;
        b = modpow(b,MOD - 2,MOD);
        return (a*b)%MOD;
    }
};
template<class T>
struct dijkstra{
  public:
	vector<vector<pair<T,T>>>graph;
	vector<T>ans;
	priority_queue<pair<T,T>,vector<pair<T,T>>,greater<pair<T,T>>>pq;
    void do_dijkstra(T start){//頂点xからダイクストラを行う
		pq.push({0,start});
		ans[start] = 0;
		while(true){
			if(pq.empty())break;
			T cost = pq.top().first;
			T vertex = pq.top().second;
			pq.pop();
            if (cost > ans[vertex]) continue; 
			for(T i = 0;i<graph[vertex].size();i++){
				T nextvertex = graph[vertex][i].first;
				T nextcost = graph[vertex][i].second + cost;
				if(ans[nextvertex] <= nextcost)continue;
					ans[nextvertex] = nextcost;
					pq.push({nextcost,nextvertex});
			}
		}
	}
	void make_indirectedgraph(T u,T v,T cost){//無向辺のグラフ作成
		graph[u].push_back({v,cost});
		graph[v].push_back({u,cost});
	}
	void make_directedgraph(T u,T v,T cost){//有向辺のグラフ作成
		graph[u].push_back({v,cost});
	}
	T output(T end){//答えを出す
		return ans[end];
	} 
	void reset(T N){//リセット
		graph.assign(N, {});
        ans.assign(N, INF);
	}
};
template<class T>
struct unionfind {
public:
    vector<T> parent, rank;
    void reset(T N) { // 初期化
        parent.resize(N);
        rank.assign(N, 1); // 各集合のサイズを 1 にする
        for (T i = 0; i < N; i++) parent[i] = i;
    }
    T leader(T x) { // 経路圧縮による親の取得
        if (parent[x] == x) return x;
        return parent[x] = leader(parent[x]); // 経路圧縮
    }
    void marge(T x, T y) { // ランクによるマージ
        T a = leader(x), b = leader(y);
        if(a!=b){
            if (rank[a] < rank[b]) swap(a, b);
            parent[b] = a;
            rank[a] += rank[b]; // サイズを更新    
        }
    }
    bool same(T x, T y) { // 同じ集合か判定
        return leader(x) == leader(y);
    }
    T size(T x) { // 集合のサイズを取得
        return rank[leader(x)];
    }
    void check(T N) { // デバッグ用: 親の確認
        for (T i = 0; i < N; i++) cout << parent[i] << " ";
        cout << "\n";
    }
};
//セグ木
template <class S, S (*op)(S, S), S (*e)()> struct segtree {
    public:
        segtree() : segtree(0) {}
        segtree(int n) : segtree(std::vector<S>(n, e())) {}
        segtree(const std::vector<S>& v) : _n(int(v.size())){
            log = ceil_pow2(_n);
            size = 1 << log;
            d = std::vector<S>(2 * size, e());
            for (int i = 0; i < _n; i++) d[size + i] = v[i];
            for (int i = size - 1; i >= 1; i--) {
                update(i);
            }
        }
  
        void set(int p, S x) {
            assert(0 <= p && p < _n);
            p += size;
            d[p] = x;
            for (int i = 1; i <= log; i++) update(p >> i);
        }
  
        S get(int p) {
            assert(0 <= p && p < _n);
            return d[p + size];
        }
  
        S prod(int l, int r) {
            assert(0 <= l && l <= r && r <= _n);
            S sml = e(), smr = e();
            l += size;
            r += size;
  
            while (l < r) {
                if (l & 1) sml = op(sml, d[l++]);
                if (r & 1) smr = op(d[--r], smr);
                l >>= 1;
                r >>= 1;
            }
            return op(sml, smr);
        }
  
        S all_prod() { return d[1]; }
  
        template <bool (*f)(S)> int max_right(int l) {
            return max_right(l, [](S x) { return f(x); });
        }
        template <class F> int max_right(int l, F f) {
            assert(0 <= l && l <= _n);
            assert(f(e()));
            if (l == _n) return _n;
            l += size;
            S sm = e();
            do{
                while (l % 2 == 0) l >>= 1;
                if (!f(op(sm, d[l]))) {
                    while (l < size) {
                        l = (2 * l);
                        if (f(op(sm, d[l]))) {
                            sm = op(sm, d[l]);
                            l++;
                        }
                    }
                    return l - size;
                }
                sm = op(sm, d[l]);
                l++;
            }while ((l & -l) != l);
            return _n;
        }
  
        template <bool (*f)(S)> int min_left(int r) {
            return min_left(r, [](S x) { return f(x); });
        }
        template <class F> int min_left(int r, F f) {
            assert(0 <= r && r <= _n);
            assert(f(e()));
            if (r == 0) return 0;
            r += size;
            S sm = e();
            do{
                r--;
                while (r > 1 && (r % 2)) r >>= 1;
                if (!f(op(d[r], sm))) {
                    while (r < size) {
                        r = (2 * r + 1);
                        if (f(op(d[r], sm))) {
                            sm = op(d[r], sm);
                            r--;
                        }
                    }
                    return r + 1 - size;
                }
                sm = op(d[r], sm);
            }while ((r & -r) != r);
            return 0;
        }
  
    private:
        int _n, size, log;
        std::vector<S> d;
  
        void update(int k) { d[k] = op(d[2 * k], d[2 * k + 1]); }
        int ceil_pow2(int n) {
            int x = 0;
            while ((1U << x) < (unsigned int)(n)) x++;
            return x;
        }
};

//遅延セグ木
template <class S,S (*op)(S, S),S (*e)(),class F,S (*mapping)(F, S),F (*composition)(F, F),F (*id)()>
struct lazy_segtree {

    public:
        lazy_segtree() : lazy_segtree(0) {}
        lazy_segtree(int n) : lazy_segtree(std::vector<S>(n, e())) {}
        lazy_segtree(const std::vector<S>& v) : _n(int(v.size())) {
            log = ceil_pow2(_n);
            size = 1 << log;
            d = std::vector<S>(2 * size, e());
            lz = std::vector<F>(size, id());
            for (int i = 0; i < _n; i++) d[size + i] = v[i];
            for (int i = size - 1; i >= 1; i--) {
                update(i);
            }
        }

    void set(int p, S x) {
        assert(0 <= p && p < _n);
        p += size;
        for (int i = log; i >= 1; i--) push(p >> i);
        d[p] = x;
        for (int i = 1; i <= log; i++) update(p >> i);
    }

    S get(int p) {
        assert(0 <= p && p < _n);
        p += size;
        for (int i = log; i >= 1; i--) push(p >> i);
        return d[p];
    }

    S prod(int l, int r) {
        assert(0 <= l && l <= r && r <= _n);
        if (l == r) return e();

        l += size;
        r += size;

        for (int i = log; i >= 1; i--) {
            if (((l >> i) << i) != l) push(l >> i);
            if (((r >> i) << i) != r) push(r >> i);
        }

        S sml = e(), smr = e();
        while (l < r) {
            if (l & 1) sml = op(sml, d[l++]);
            if (r & 1) smr = op(d[--r], smr);
            l >>= 1;
            r >>= 1;
        }

        return op(sml, smr);
    }

    S all_prod() { return d[1]; }

    void apply(int p, F f) {
        assert(0 <= p && p < _n);
        p += size;
        for (int i = log; i >= 1; i--) push(p >> i);
        d[p] = mapping(f, d[p]);
        for (int i = 1; i <= log; i++) update(p >> i);
    }
    void apply(int l, int r, F f) {
        assert(0 <= l && l <= r && r <= _n);
        if (l == r) return;

        l += size;
        r += size;

        for (int i = log; i >= 1; i--) {
            if (((l >> i) << i) != l) push(l >> i);
            if (((r >> i) << i) != r) push((r - 1) >> i);
        }

        {
            int l2 = l, r2 = r;
            while (l < r) {
                if (l & 1) all_apply(l++, f);
                if (r & 1) all_apply(--r, f);
                l >>= 1;
                r >>= 1;
            }
            l = l2;
            r = r2;
        }

        for (int i = 1; i <= log; i++) {
            if (((l >> i) << i) != l) update(l >> i);
            if (((r >> i) << i) != r) update((r - 1) >> i);
        }
    }

    template <bool (*g)(S)> int max_right(int l) {
        return max_right(l, [](S x) { return g(x); });
    }
    template <class G> int max_right(int l, G g) {
        assert(0 <= l && l <= _n);
        assert(g(e()));
        if (l == _n) return _n;
        l += size;
        for (int i = log; i >= 1; i--) push(l >> i);
        S sm = e();
        do {
            while (l % 2 == 0) l >>= 1;
            if (!g(op(sm, d[l]))) {
                while (l < size) {
                    push(l);
                    l = (2 * l);
                    if (g(op(sm, d[l]))) {
                        sm = op(sm, d[l]);
                        l++;
                    }
                }
                return l - size;
            }
            sm = op(sm, d[l]);
            l++;
        } while ((l & -l) != l);
        return _n;
    }

    template <bool (*g)(S)> int min_left(int r) {
        return min_left(r, [](S x) { return g(x); });
    }
    template <class G> int min_left(int r, G g) {
        assert(0 <= r && r <= _n);
        assert(g(e()));
        if (r == 0) return 0;
        r += size;
        for (int i = log; i >= 1; i--) push((r - 1) >> i);
        S sm = e();
        do {
            r--;
            while (r > 1 && (r % 2)) r >>= 1;
            if (!g(op(d[r], sm))) {
                while (r < size) {
                    push(r);
                    r = (2 * r + 1);
                    if (g(op(d[r], sm))) {
                        sm = op(d[r], sm);
                        r--;
                    }
                }
                return r + 1 - size;
            }
            sm = op(d[r], sm);
        } while ((r & -r) != r);
        return 0;
    }

    private:
        int _n, size, log;
        std::vector<S> d;
        std::vector<F> lz;
        int ceil_pow2(int n) {
            int x = 0;
            while ((1U << x) < (unsigned int)(n)) x++;
            return x;
        }
        void update(int k) { d[k] = op(d[2 * k], d[2 * k + 1]); }
        void all_apply(int k, F f) {
            d[k] = mapping(f, d[k]);
            if (k < size) lz[k] = composition(f, lz[k]);
        }
        void push(int k) {
            all_apply(2 * k, lz[k]);
            all_apply(2 * k + 1, lz[k]);
            lz[k] = id();
        }
};
struct Euler_Tour{//最小共通祖先,部分木のコスト,通り道のコスト,のグラフを作る部分(オイラーツアー)
    //必要なもの集
    //セグ木は2*Nがベース
    //LCA(最小共通祖先)discovery,finish,visit,high
    //とある頂点xを根とする部分木の範囲 discovery,finish
    //頂点xを根とする部分木の辺と頂点のコストの総和 discovery,finish,vcost1,ecost1
    //頂点xを根とする頂点yまでの最短の辺と頂点のコストの総和 discovery,finish,vcost2,ecost2
    vector<int>discovery,finish,visit,high,vweight,vcost1,vcost2,ecost1,ecost2;
    vector<vector<pair<int,int>>>graph;
    int cnt;
    void reset(ll N){
        cnt = 0;
        discovery.assign(N,inf);
        finish.assign(N,minf);
        vweight.assign(N,0);
        graph.assign(N,vector<pair<int,int>>(0));
        visit.assign(2*N,0);
        high.assign(2*N,0);
        vcost1.assign(2*N,0);
        vcost2.assign(2*N,0);
        ecost1.assign(2*N,0);
        ecost2.assign(2*N,0);
    };
    void make_graph(ll u,ll v,ll cost){
        if(max(u,v)>graph.size()){
            cout << "not reset or out of range" << "\n";
            return;
        }
        graph[u].push_back({v,cost});
        graph[v].push_back({u,cost});
    }
    void set_vweight(ll vertex,ll cost){
        vweight[vertex]+=cost;
    }
    void DFS(ll vertex,ll nowdepth,ll cost){
        if(discovery[vertex]==inf){
            vcost1[cnt]=vweight[vertex];
            vcost2[cnt]=vweight[vertex];
        }
        else{
            vcost1[cnt]=0;
            vcost2[cnt]=0;
        }
        ecost1[cnt]=cost;
        ecost2[cnt]=cost;
        discovery[vertex]=min(discovery[vertex],cnt);
        visit[cnt]=vertex;
        high[cnt]=nowdepth;
        for(int i = 0;i<graph[vertex].size();i++){
            int x = graph[vertex][i].first;
            int nextcost = graph[vertex][i].second;
            if(discovery[x]==inf){
                cnt++;
                DFS(x,nowdepth+1,nextcost);
                cnt++;
                visit[cnt]=vertex;
                high[cnt]=nowdepth;
                vcost1[cnt]=0;
                ecost1[cnt]=0;
                vcost2[cnt]=vweight[x]*-1;
                ecost2[cnt]=nextcost*-1;
            }
        }
        finish[vertex]=cnt+1;
        return;
    }
    int get_size(){
        ll res = high.size()-1;
        return res;
    }
    int get_vcost1(ll i){
        return ecost1[i];
    }
    int get_vcost2(ll i){
        return vcost2[i];
    }
    int get_ecost1(ll i){
        return vcost1[i];
    }
    int get_ecost2(ll i){
        return ecost2[i];
    }
    int get_high(ll i){
        return high[i];
    }
    int get_visit(ll i){
        return visit[i];
    }
    int get_discovery(ll i){
        return discovery[i];
    }
    int get_finish(ll i){
        return finish[i];
    }
};
//遅延セグ木のベース
//型
/*struct segS{
    ll one = 0;
    ll two = 0;
};
segS op(segS a,segS b){
    segS res;
    res.one = a.one+b.one;
    res.two = a.two+b.two;
    return res;
}
segS e(){
    segS res;
    res.one = 0;
    res.two = 0;
    return res;
}*/

using lazyS = ll;
using lazyF = ll;
lazyS e(){ return 0;}//範囲外などを起こしてしまったときの返り値
lazyS op(lazyS a, lazyS b){ return a+b; }//操作したいこと
lazyS mapping(lazyF f, lazyS x){ return x *= f; }//下まで伝播させたいこと
lazyF composition(lazyF f, lazyF g){ return g *= f; }//まとめてやった場合おこしたいこと
lazyF id(){ return 1; }//遅延セグ木のベース


int main(){
//B以上は基本詳細を書いておくと便利　A ＝ ooの値とか　見直す時に便利
// この問題の本質
//cout << get_theta(0,0,0,0,0,1) << "\n";
//nCr = A+B+i C B
//nCr = C-i+D-1 C D-1
ll N,Q;
cin >> N>>Q;
Euler_Tour tour;
Euler_Tour stour;
tour.reset(N);
for(ll i = 1;i<N;i++){
    ll a;
    cin >> a;
    a--;
    tour.make_graph(a,i,0);
}
for(ll i = 0;i<N;i++){
    char S;
    cin >> S;
    ll a = 0;
    if(S=='G')a = 1;
    else a = 2;
    tour.set_vweight(i,a);
}
tour.DFS(0,0,0);
vector<int>discover = tour.discovery;
vector<int>finish = tour.finish;
vector<int>judge = tour.vcost1;
lazy_segtree<lazyS,op,e,lazyF,mapping,composition,id>seg(2*N);
for(ll i = 0;i<judge.size();i++){
    ll res = 0;
    if(judge[i]==1)res++;
    else if(judge[i]==2)res--;
    seg.set(i,res);
}
for(ll i = 0;i<Q;i++){
    ll a;
    cin >> a;
    a--;
    ll left = discover[a];
    ll right = finish[a];
    seg.apply(left,right,-1);
    ll x = seg.all_prod();
    if(x<=0)cout << "cauliflower"<<"\n";
    else cout << "broccoli" << "\n";
}
}
accuracy: 1
time_ms: 150
memory_kb: 31432
final_rank: 20

code_snippet: // AOJ #2871
// Broccoli or Cauliflower 2025.1.22

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

// 遅延セグメント木用のデータ構造
struct SegmentTree {
    int n;                      // 要素数
    vector<int> tree;          // 区間の 1 の個数を保持するセグメント木
    vector<int> lazy;          // lazy[i] = 1 のとき、そのノード担当区間を反転すべきフラグ

    // コンストラクタ
    SegmentTree(int n_) : n(n_) {
        tree.resize(4*n, 0);
        lazy.resize(4*n, 0);
    }

    // 区間 [start, end] を担当するノード idx の情報を子に伝搬
    void pushDown(int idx, int start, int end) {
        if (lazy[idx] == 0) return; // 反転指示がなければ何もしない

        int mid = (start + end) / 2;
        int leftSize = mid - start + 1;     // 左子担当区間の長さ
        int rightSize = end - mid;         // 右子担当区間の長さ

        // 左右の子ノードの sum を反転する
        // lazy[idx] が立っている => 左右の子に flip を伝搬させる (XOR で反転)
        tree[idx*2] = leftSize - tree[idx*2];
        tree[idx*2+1] = rightSize - tree[idx*2+1];
        lazy[idx*2] ^= 1;   // flip フラグを反転
        lazy[idx*2+1] ^= 1; // flip フラグを反転

        // 自分の反転指示は処理済みなので下ろす
        lazy[idx] = 0;
    }

    // 区間 [start, end] を担当するノード idx での区間 [l, r] 反転更新
    void update(int idx, int start, int end, int l, int r) {
        if (r < start || end < l) {
            // 範囲外
            return;
        }
        if (l <= start && end <= r) {
            // 完全被覆
            tree[idx] = (end - start + 1) - tree[idx]; // 反転
            lazy[idx] ^= 1;                           // flip フラグを反転
            return;
        }
        // 部分的に被っている場合は子に下ろす
        pushDown(idx, start, end);
        int mid = (start + end) / 2;
        update(idx*2,     start,     mid, l, r);
        update(idx*2 + 1, mid + 1, end, l, r);
        tree[idx] = tree[idx*2] + tree[idx*2 + 1];
    }

    // 木全体の build (オイラーツアー後の配列 vals の情報を構築)
    void build(const vector<int> &vals, int idx, int start, int end) {
        if (start == end) {
            tree[idx] = vals[start]; // 0 or 1
            return;
        }
        int mid = (start + end) / 2;
        build(vals, idx*2,     start,     mid);
        build(vals, idx*2 + 1, mid + 1, end);
        tree[idx] = tree[idx*2] + tree[idx*2 + 1];
    }

    // 外部から呼び出しやすいようにラップ
    void build(const vector<int> &vals) {
        build(vals, 1, 0, n-1);
    }

    void update(int l, int r) {
        update(1, 0, n-1, l, r);
    }

    // セグメント木のルートが管理している合計 (配列全体の 1 の個数)
    int getTotal() const {
        return tree[1];
    }
};

static const int MAXN = 100000;

// 木の隣接リスト (子のリストとして使う)
vector<int> children[MAXN];
int inTime[MAXN], outTime[MAXN]; 
int eulerOrder[MAXN]; // オイラーツアー順に頂点の "0 or 1" を並べるときの配列
int timer = 0;

// 再帰を使わない DFS（スタックを使った実装）でオイラーツアー
void eulerTour(int root, const vector<int> &initialLabel) {
    // stack の要素は (v, i) とし，v は現在処理中の頂点，i は子の処理位置
    // ただし i=-1 のとき「まだ inTime を記録していない状態」とする
    stack<pair<int,int>> st;
    st.push({root, -1});
    while (!st.empty()) {
        auto &top = st.top();
        int v = top.first;
        int &i = top.second;

        if (i == -1) {
            // はじめて訪問した
            inTime[v] = timer;
            eulerOrder[timer] = initialLabel[v];
            timer++;
            i = 0; // これから children[v] を走査
        }
        if (i < (int)children[v].size()) {
            int c = children[v][i++];
            st.push({c, -1});
        } else {
            outTime[v] = timer;
            st.pop();
        }
    }
}

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

    int n, q;
    cin >> n >> q;

    // 親配列 p: p[i] は i+1 番目頂点の親 (i=1 以降)
    // ただし頂点は 1-based 入力なので注意
    vector<int> parent(n, -1);
    for (int i=1; i<n; i++) {
        int p;
        cin >> p;
        --p; // 0-based に直す
        parent[i] = p;
        children[p].push_back(i);
    }

    // ラベル (G -> 1, W -> 0)
    vector<int> label(n);
    for (int i=0; i<n; i++) {
        char c;
        cin >> c;
        label[i] = (c == 'G' ? 1 : 0);
    }

    // オイラーツアーで inTime[v], outTime[v], eulerOrder[...] を構築
    // 根は頂点 0 (1 を 0-based に直した)
    eulerTour(0, label);

    // セグメント木の構築
    SegmentTree seg(n);
    seg.build(vector<int>(eulerOrder, eulerOrder+n));

    // クエリ処理
    // 全頂点数 n は奇数 => #G > #W かどうかの判定は #G > n/2 と同値
    int half = n / 2 + 1; // もし #G >= half なら broccoli

    while (q--) {
        int v;
        cin >> v;
        v--; // 0-based
        // 部分木の範囲 [inTime[v], outTime[v]) を反転
        seg.update(inTime[v], outTime[v]-1);

        // セグメント木のルートが管理している合計 = 全体の G の個数
        int totalG = seg.getTotal();
        if (totalG >= half) cout << "broccoli\n";
        else                cout << "cauliflower\n";
    }
    return 0;
}
accuracy: 1
time_ms: 30
memory_kb: 14412
final_rank: 1

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

namespace zawa {

using u32 = uint32_t;
using i32 = int32_t;
using usize = size_t;

template <class Structure>
struct LazySegmentTree {
    using VM = typename Structure::ValueMonoid;
    using OM = typename Structure::OperatorMonoid;
    using Value = typename VM::Element;
    using Operator = typename OM::Element;
    u32 parent(u32 v) {
       return v >> 1;
    }
    u32 left(u32 v) {
        return v << 1;
    }
    u32 right(u32 v) {
        return v << 1 | 1;
    }
    u32 depth(u32 v) {
        return 31u - __builtin_clz(v);
    }
    u32 trailingZeros(u32 v) {
        return __builtin_ctz(v);
    }
    
    struct Node {
        Value v_{VM::identity()};
        Operator o_{OM::identity()};
        Node() = default;
        Node(const Value& v, const Operator& o) : v_{v}, o_{o} {}
    };

    usize n_{};
    std::vector<Node> dat_;
    static Value action(const Node& node) {
        return Structure::mapping(node.v_, node.o_);
    }

    void propagate(u32 v) {
        dat_[left(v)].o_ = OM::operation(dat_[left(v)].o_, dat_[v].o_);
        dat_[right(v)].o_ = OM::operation(dat_[right(v)].o_, dat_[v].o_);
        dat_[v].o_ = OM::identity();
    }
    void propagateAncestor(u32 v) {
        u32 dep{depth(v)};
        u32 zeros{trailingZeros(v)};
        for (u32 d{dep} ; d != zeros ; d--) {
            propagate(v >> d);
        }
    }

    void recalc(u32 v) {
        dat_[v].v_ = VM::operation(action(dat_[left(v)]), action(dat_[right(v)]));
    }
    void recalcAncestor(u32 v) {
        v >>= trailingZeros(v);
        for (v = parent(v) ; v ; v = parent(v)) {
            recalc(v);
        }
    }

    template <class InputIterator>
    void datInit(InputIterator first) {
        auto it{first};
        for (u32 i{} ; i < n_ ; i++) {
            dat_[i + n_].v_ = *it;
            it++;
        }
        for (u32 i{static_cast<u32>(n_)} ; --i ; ) {
            dat_[i].v_ = VM::operation(dat_[left(i)].v_, dat_[right(i)].v_);
        }
    }

    LazySegmentTree() = default;
    LazySegmentTree(const std::vector<Value>& a) : n_{a.size()}, dat_((a.size() << 1)) {
        assert(!a.empty());
        datInit(a.begin());
    }
    usize size() const {
        return n_;
    }
    void operation(u32 L, u32 R, const Operator& o) {
        assert(L <= R and R <= n_);
        L += size();
        R += size();
        propagateAncestor(L);
        propagateAncestor(R);
        for (u32 l = L, r = R ; l < r ; l = parent(l), r = parent(r)) {
            if (l & 1) {
                dat_[l].o_ = OM::operation(dat_[l].o_, o);
                l++;
            }
            if (r & 1) {
                --r;
                dat_[r].o_ = OM::operation(dat_[r].o_, o);
            }
        }
        recalcAncestor(L);
        recalcAncestor(R);
    }

    Value product(u32 L, u32 R) {
        assert(L <= R and R <= n_);
        L += size();
        R += size();
        propagateAncestor(L);
        propagateAncestor(R);
        recalcAncestor(L);
        recalcAncestor(R);
        Value l{VM::identity()}, r{VM::identity()};
        for ( ; L < R ; L = parent(L), R = parent(R)) {
            if (L & 1) {
                l = VM::operation(l, action(dat_[L]));
                L++;
            }
            if (R & 1) {
                R--;
                r = VM::operation(action(dat_[R]), r);
            }
        }
        return VM::operation(l, r);
    }
};


} // namespace zawa

struct VM {
    using Element = std::pair<int, int>;
    static Element identity() {
        return std::pair<int, int>{0,0};
    }
    static Element operation(Element A, Element B) {
        A.first += B.first;
        A.second += B.second;
        return A;
    }
};

struct OM {
    using Element = int;
    static Element identity() {
        return 0;
    }
    static Element operation(Element A, Element B) {
        return A ^ B;
    }
};

struct Structure {
    using ValueMonoid = VM;
    using OperatorMonoid = OM;
    static VM::Element mapping(VM::Element A, OM::Element B) {
        if (B) std::swap(A.first, A.second);
        return A;
    }
};

int main() {
    int N, Q;
    std::cin >> N >> Q;
    std::vector<std::vector<int>> g(N);
    for (int i{1} ; i < N ; i++) {
        int P;
        std::cin >> P;
        P--;
        g[P].push_back(i);
    }
    std::vector<char> C(N);
    for (auto& x : C) std::cin >> x;

    std::vector<int> euler(N), left(N), right(N);
    int time{};
    auto dfs{[&](auto dfs, int v) -> void {
        euler[v] = time;
        left[v] = time;
        time++;
        for (auto x : g[v]) dfs(dfs, x);
        right[v] = time;
    }};
    dfs(dfs, 0);

    std::vector<VM::Element> init(N);
    for (int i{} ; i < N ; i++) {
        init[euler[i]] = (C[i] == 'G' ? std::pair<int, int>{ 1, 0 } : std::pair<int, int>{ 0, 1 });
    }
    zawa::LazySegmentTree<Structure> seg(init);
    while (Q--) {
        int v;
        std::cin >> v;
        v--;
        seg.operation(left[v], right[v], 1);
        auto [x, y]{seg.product(0, N)};
        if (x > y) {
            std::cout << "broccoli" << '\n';
        }
        else {
            std::cout << "cauliflower" << '\n';
        }
    }
}
accuracy: 1
time_ms: 150
memory_kb: 22304
final_rank: 16

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

template <class M>
struct SegTree {
    using T = typename M::T;
    using F = typename M::F;
    int n;
    int log;
    int size;
    std::vector<T> d;
    std::vector<F> lz;
    SegTree(std::vector<T> dat) {
        n = dat.size();
        log = 1;
        while (n > (1 << log)) log++;
        size = 1 << log;
        d = std::vector<T>(2 * size, M::e());
        lz = std::vector<F>(size, M::id());
        for (int i = 0; i < n; i++) d[size + i] = dat[i];
        for (int i = size - 1; i >= 1; i--) {
            update(i);
        }
    }

    T all_prod(){ return d[1]; }

    T prod(int l, int r) {
        assert(0 <= l && l <= r && r <= n);
        if (l == r) return M::e();

        l += size;
        r += size;

        for (int i = log; i >= 1; i--) {
            if (((l >> i) << i) != l) push(l >> i);
            if (((r >> i) << i) != r) push((r - 1) >> i);
        }

        T sml = M::e();
        T smr = M::e();
        while (l < r) {
            if (l & 1) sml = M::op(sml, d[l++]);
            if (r & 1) smr = M::op(d[--r], smr);
            l >>= 1;
            r >>= 1;
        }
        return M::op(sml, smr);
    }

    void apply(int l, int r, F f) {
        assert(0 <= l && l <= r && r <= n);
        if (l == r) return;
        l += size;
        r += size;
        for (int i = log; i >= 1; i--) {
            if (((l >> i) << i) != l) push(l >> i);
            if (((r >> i) << i) != r) push((r - 1) >> i);
        }

        {
            int l2 = l;
            int r2 = r;
            while (l < r) {
                if (l & 1) all_apply(l++, f);
                if (r & 1) all_apply(--r, f);
                l >>= 1;
                r >>= 1;
            }
            l = l2;
            r = r2;
        }

        for (int i = 1; i <= log; i++) {
            if (((l >> i) << i) != l) update(l >> i);
            if (((r >> i) << i) != r) update((r - 1) >> i);
        }
    }

    void update(int k) {
        d[k] = M::op(d[2 * k], d[2 * k + 1]);
    }
    void all_apply(int k, F f) {
        d[k] = M::mapping(f, d[k]);
        if (k < size) lz[k] = M::composition(f, lz[k]);
    }
    void push(int k) {
        all_apply(2 * k, lz[k]);
        all_apply(2 * k + 1, lz[k]);
        lz[k] = M::id();
    }
};

struct Monoid {
    using T = std::pair<int, int>;
    using F = int;
    static T op(T lhs, T rhs) {
        return {lhs.first + rhs.first, lhs.second + rhs.second};
    }
    static T e() {
        return {0, 0};
    }
    static T mapping(F f, T t) {
        if (f) return {t.second, t.first};
        return t;
    }
    static F composition(F lhs, F rhs) {
        return lhs ^ rhs;
    }
    static F id() {
        return 0;
    }
};

int main() {
    int n, q;
    std::cin >> n >> q;
    std::vector graph(n, std::vector<int>());
    for (int i = 1; i < n; i++) {
        int v;
        std::cin >> v;
        v--;
        graph[v].push_back(i);
        graph[i].push_back(v);
    }
    std::vector<std::pair<int, int>> c(n);

    std::vector<int> in(n), out(n);
    int now = 0;
    auto dfs = [&](auto self, int u, int p) -> void {
        in[u] = now++;
        for (int v: graph[u]) {
            if (v == p) continue;
            self(self, v, u);
        }
        out[u] = now;
    };
    dfs(dfs, 0, -1);
    for (int i = 0; i < n; i++) {
        char t;
        std::cin >> t;
        int lhs = t == 'G';
        int rhs = 1 ^ lhs;
        c[in[i]] = {lhs, rhs};
    }
    SegTree<Monoid> segtree(c);

    while (q--) {
        int v;
        std::cin >> v;
        v--;
        segtree.apply(in[v], out[v], 1);
        auto p = segtree.all_prod();
        assert(p.first + p.second == n);
        if (p.first > p.second) {
            std::cout << "broccoli" << '\n';
        } else {
            std::cout << "cauliflower" << '\n';
        }

        // for (int i = 0; i < n; i++) {
        //     auto p = segtree.prod(i, i + 1);
        //     char c = (p.first ? 'G' : 'W');
        //     std::cerr << c << ' ';
        // }
        // std::cerr << std::endl;
    }
}
accuracy: 1
time_ms: 140
memory_kb: 22908
final_rank: 14

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

template <class M>
struct SegTree {
    using T = typename M::T;
    using F = typename M::F;
    int n;
    int log;
    int size;
    std::vector<T> d;
    std::vector<F> lz;
    SegTree(std::vector<T> dat) {
        n = dat.size();
        log = 1;
        while (n > (1 << log)) log++;
        size = 1 << log;
        d = std::vector<T>(2 * size, M::e());
        lz = std::vector<F>(size, M::id());
        for (int i = 0; i < n; i++) d[size + i] = dat[i];
        for (int i = size - 1; i >= 1; i--) {
            update(i);
        }
    }

    T all_prod(){ return d[1]; }

    T prod(int l, int r) {
        assert(0 <= l && l <= r && r <= n);
        if (l == r) return M::e();

        l += size;
        r += size;

        for (int i = log; i >= 1; i--) {
            if (((l >> i) << i) != l) push(l >> i);
            if (((r >> i) << i) != r) push((r - 1) >> i);
        }

        T sml = M::e();
        T smr = M::e();
        while (l < r) {
            if (l & 1) sml = M::op(sml, d[l++]);
            if (r & 1) smr = M::op(d[--r], smr);
            l >>= 1;
            r >>= 1;
        }
        return M::op(sml, smr);
    }

    void apply(int l, int r, F f) {
        assert(0 <= l && l <= r && r <= n);
        if (l == r) return;
        l += size;
        r += size;
        for (int i = log; i >= 1; i--) {
            if (((l >> i) << i) != l) push(l >> i);
            if (((r >> i) << i) != r) push((r - 1) >> i);
        }

        {
            int l2 = l;
            int r2 = r;
            while (l < r) {
                if (l & 1) all_apply(l++, f);
                if (r & 1) all_apply(--r, f);
                l >>= 1;
                r >>= 1;
            }
            l = l2;
            r = r2;
        }

        for (int i = 1; i <= log; i++) {
            if (((l >> i) << i) != l) update(l >> i);
            if (((r >> i) << i) != r) update((r - 1) >> i);
        }
    }

    void update(int k) {
        d[k] = M::op(d[2 * k], d[2 * k + 1]);
    }
    void all_apply(int k, F f) {
        d[k] = M::mapping(f, d[k]);
        if (k < size) lz[k] = M::composition(f, lz[k]);
    }
    void push(int k) {
        all_apply(2 * k, lz[k]);
        all_apply(2 * k + 1, lz[k]);
        lz[k] = M::id();
    }
};

struct Monoid {
    using T = std::pair<int, int>;
    using F = int;
    static T op(T lhs, T rhs) {
        return {lhs.first + rhs.first, lhs.second + rhs.second};
    }
    static T e() {
        return {0, 0};
    }
    static T mapping(F f, T t) {
        if (f) return {t.second, t.first};
        return t;
    }
    static F composition(F lhs, F rhs) {
        return lhs ^ rhs;
    }
    static F id() {
        return 0;
    }
};

int main() {
    int n, q;
    std::cin >> n >> q;
    std::vector graph(n, std::vector<int>());
    for (int i = 1; i < n; i++) {
        int v;
        std::cin >> v;
        v--;
        graph[v].push_back(i);
        graph[i].push_back(v);
    }
    std::vector<std::pair<int, int>> c(n);

    std::vector<int> in(n), out(n);
    int now = 0;
    auto dfs = [&](auto self, int u, int p) -> void {
        in[u] = now++;
        for (int v: graph[u]) {
            if (v == p) continue;
            self(self, v, u);
        }
        out[u] = now;
    };
    dfs(dfs, 0, -1);
    for (int i = 0; i < n; i++) {
        char t;
        std::cin >> t;
        int lhs = t == 'G';
        int rhs = 1 ^ lhs;
        c[in[i]] = {lhs, rhs};
    }
    SegTree<Monoid> segtree(c);

    while (q--) {
        int v;
        std::cin >> v;
        v--;
        segtree.apply(in[v], out[v], 1);
        auto p = segtree.all_prod();
        assert(p.first + p.second == n);
        if (p.first > p.second) {
            std::cout << "broccoli" << '\n';
        } else {
            std::cout << "cauliflower" << '\n';
        }

        // for (int i = 0; i < n; i++) {
        //     auto p = segtree.prod(i, i + 1);
        //     char c = (p.first ? 'G' : 'W');
        //     std::cerr << c << ' ';
        // }
        // std::cerr << std::endl;
    }
}
accuracy: 1
time_ms: 130
memory_kb: 22832
final_rank: 13

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

namespace zawa {

using u32 = uint32_t;
using i32 = int32_t;
using usize = size_t;

template <class St>
class LazySegmentTree {
public:
    using VM = typename St::ValueMonoid;
    using OM = typename St::OperatorMonoid;
    using Value = typename VM::Element;
    using Operator = typename OM::Element;
private:
    u32 parent(u32 v) {
        return v >>= 1;
    }
    u32 left(u32 v) {
        return v << 1;
    }
    u32 right(u32 v) {
        return v << 1 | 1;
    }
    u32 depth(u32 v) {
        return 31u - __builtin_clz(v);
    }
    u32 trailingZeros(u32 v) {
        return __builtin_ctz(v);
    }

    struct Node {
        Value v_{VM::identity()};
        Operator o_{OM::identity()};
        Node() = default;
        Node(const Value& v, const Operator& o) : v_{v}, o_{o} {}
    };

    usize n_{};
    std::vector<Node> dat_;

    static Value action(const Node& node) {
        return St::mapping(node.v_, node.o_);
    }

    void propagate(u32 v) {
        dat_[left(v)].o_ = OM::operation(dat_[left(v)].o_, dat_[v].o_);
        dat_[right(v)].o_ = OM::operation(dat_[right(v)].o_, dat_[v].o_);
        dat_[v].o_ = OM::identity();
    }

    void propagateAncestor(u32 v) {
        u32 dep{depth(v)};
        u32 zeros{trailingZeros(v)};
        for (u32 d{dep} ; d != zeros ; d--) {
            propagate(v >> d);
        }
    }

    void recalc(u32 v) {
        dat_[v].v_ = VM::operation(action(dat_[left(v)]), action(dat_[right(v)]));
    }

    void recalcAncesotr(u32 v) {
        v >>= trailingZeros(v);
        for (v = parent(v) ; v ; v = parent(v)) {
            recalc(v);
        }
    }

    template <class InputIterator>
    void datInit(InputIterator first) {
        auto it{first};
        for (u32 i{} ; i < n_ ; i++) {
            dat_[i + n_].v_ = *it;
            it++;
        }
        for (u32 i{static_cast<u32>(n_)} ; --i ; ) {
            dat_[i].v_ = VM::operation(dat_[left(i)].v_, dat_[right(i)].v_);
        }
    }

public:

    LazySegmentTree() = default;
    LazySegmentTree(u32 n) : n_{n}, dat_((n << 1)) {
        assert(n_);
    }
    LazySegmentTree(const std::vector<Value>& a) : n_{a.size()}, dat_((a.size() << 1)) {
        assert(!a.empty());
        datInit(a.begin());
    }

    u32 size() const {
        return n_;
    }

    void operation(u32 i, const Operator& o) {
        assert(i < n_);
        i += size();
        propagateAncestor(i);
        dat_[i].o_ = OM::operation(dat_[i].o_, o);
        recalcAncesotr(i);
    }

    void operation(u32 L, u32 R, const Operator& o) {
        assert(L < n_);
        assert(L <= R and R <= n_);
        L += size();
        R += size();
        propagateAncestor(L);
        propagateAncestor(R);
        for (u32 l = L, r = R ; l < r ; l = parent(l), r = parent(r)) {
            if (l & 1) {
                dat_[l].o_ = OM::operation(dat_[l].o_, o);
                l++;
            }
            if (r & 1) {
                r--;
                dat_[r].o_ = OM::operation(dat_[r].o_, o);
            }
        }
        recalcAncesotr(L);
        recalcAncesotr(R);
    }

    Value product(u32 L, u32 R) {
        assert(L < n_);
        assert(L <= R and R <= n_);
        L += size();
        R += size();
        propagateAncestor(L);
        propagateAncestor(R);
        recalcAncesotr(L);
        recalcAncesotr(R);
        Value l{VM::identity()}, r{VM::identity()};
        for ( ; L < R ; L = parent(L), R = parent(R)) {
            if (L & 1) {
                l = VM::operation(l, action(dat_[L]));
                L++;
            }
            if (R & 1) {
                R--;
                r = VM::operation(action(dat_[R]), r);
            }
        }
        return VM::operation(l, r);
    }
};
    
} // namespace zawa

struct VM {
    using Element = std::pair<int, int>;
    static Element identity() {
        return Element{ 0, 0 };
    }
    static Element operation(Element L, Element R) {
        L.first += R.first;
        L.second += R.second;
        return L;
    }
};

struct OM {
    using Element = int;
    static Element identity() {
        return 0;
    }
    static Element operation(Element L, Element R) {
        return L ^ R;
    }
};

struct Structure {
    using ValueMonoid = VM;
    using OperatorMonoid = OM;
    static ValueMonoid::Element mapping(ValueMonoid::Element A, OperatorMonoid::Element B) {
        if (B) {
            std::swap(A.first, A.second);
        }
        return A;
    }
};

int main() {
    int N, Q;
    std::cin >> N >> Q;
    std::vector<std::vector<int>> g(N);
    for (int i{1} ; i < N ; i++) {
        int P;
        std::cin >> P;
        P--;
        g[P].push_back(i);
    }
    std::vector<char> C(N);
    for (auto& x : C) std::cin >> x;

    std::vector<int> euler(N), left(N), right(N);
    int time{};
    auto dfs{[&](auto dfs, int v) -> void {
        euler[v] = time;
        left[v] = time;
        time++;
        for (auto x : g[v]) dfs(dfs, x);
        right[v] = time;
    }};
    dfs(dfs, 0);

    std::vector<VM::Element> init(N);
    for (int i{} ; i < N ; i++) {
        init[euler[i]] = (C[i] == 'G' ? std::pair<int, int>{ 1, 0 } : std::pair<int, int>{ 0, 1 });
    }
    zawa::LazySegmentTree<Structure> seg(init);
    while (Q--) {
        int v;
        std::cin >> v;
        v--;
        seg.operation(left[v], right[v], 1);
        auto [x, y]{seg.product(0, N)};
        if (x > y) {
            std::cout << "broccoli" << '\n';
        }
        else {
            std::cout << "cauliflower" << '\n';
        }
    }
}
accuracy: 1
time_ms: 150
memory_kb: 22252
final_rank: 15

code_snippet: /*  -*- coding: utf-8 -*-
 *
 * 2871.cc: Broccoli or Cauliflower
 */

#include<cstdio>
#include<vector>
#include<algorithm>
 
using namespace std;

/* constant */

const int MAX_N = 100000;

/* typedef */

typedef vector<int> vi;

template <typename T>
struct SegTreeSumDelay {
  int e2;
  vector<T> nodes;
  T defv;
  vector<bool> dls;
  SegTreeSumDelay() {}

  void init(int n, T _defv) {
    defv = _defv;
    for (e2 = 1; e2 < n; e2 <<= 1);
    nodes.assign(e2 * 2, defv);
    dls.assign(e2 * 2, false);
  }

  T &geti(int i) { return nodes[e2 - 1 + i]; }
  void seti(int i, T v) { geti(i) = v; }

  void setall() {
    for (int j = e2 - 2; j >= 0; j--)
      nodes[j] = nodes[j * 2 + 1] + nodes[j * 2 + 2];
  }

  void __update(int k, int l) {
    if (dls[k]) {
      int k0 = k * 2 + 1, k1 = k0 + 1, hl = l / 2;
      nodes[k0] = hl - nodes[k0];
      nodes[k1] = hl - nodes[k1];
      dls[k0] = ! dls[k0], dls[k1] = ! dls[k1];
      dls[k] = false;
    }
  }

  void flip_range(int r0, int r1, int k, int i0, int i1) {
    if (r1 <= i0 || i1 <= r0) return;
    if (r0 <= i0 && i1 <= r1) {
      nodes[k] = (i1 - i0) - nodes[k];
      dls[k] = ! dls[k];
      return;
    }

    __update(k, i1 - i0);

    int im = (i0 + i1) / 2;
    int k0 = k * 2 + 1, k1 = k0 + 1;
    flip_range(r0, r1, k0, i0, im);
    flip_range(r0, r1, k1, im, i1);
    nodes[k] = nodes[k0] + nodes[k1];
  }
  void flip_range(int r0, int r1) { flip_range(r0, r1, 0, 0, e2); }

  T sum_range(int r0, int r1, int k, int i0, int i1) {
    if (r1 <= i0 || i1 <= r0) return defv;
    if (r0 <= i0 && i1 <= r1) return nodes[k];

    __update(k, i1 - i0);

    int im = (i0 + i1) / 2;
    T v0 = sum_range(r0, r1, k * 2 + 1, i0, im);
    T v1 = sum_range(r0, r1, k * 2 + 2, im, i1);
    return v0 + v1;
  }
  T sum_range(int r0, int r1) { return sum_range(r0, r1, 0, 0, e2); }
};

/* global variables */

int ps[MAX_N], cs[MAX_N], cis[MAX_N], ls[MAX_N], rs[MAX_N];
vi nbrs[MAX_N];
SegTreeSumDelay<int> st;

/* subroutines */

/* main */

int main() {
  int n, qn;
  scanf("%d%d", &n, &qn);

  ps[0] = -1;
  for (int i = 1; i < n; i++) {
    scanf("%d", ps + i), ps[i]--;
    nbrs[ps[i]].push_back(i);
  }

  for (int i = 0; i < n; i++) {
    char s[4];
    scanf("%s", s);
    cs[i] = (s[0] == 'G') ? 1 : 0;
  }

  for (int u = 0, k = 0; u >= 0;) {
    vi &nbru = nbrs[u];
    int up = ps[u];

    if (cis[u] == 0) ls[u] = k++;
    if (cis[u] < nbru.size()) {
      int v = nbru[cis[u]++];
      u = v;
    }
    else {
      rs[u] = k;
      u = up;
    }
  }

  st.init(n, 0);
  for (int i = 0; i < n; i++) st.seti(ls[i], cs[i]);
  st.setall();

  while (qn--) {
    int v;
    scanf("%d", &v), v--;

    st.flip_range(ls[v], rs[v]);
    int s = st.sum_range(0, n);
    if (s > n - s) puts("broccoli");
    else puts("cauliflower");
  }
  
  return 0;
}
accuracy: 1
time_ms: 50
memory_kb: 10984
final_rank: 2

code_snippet: #line 1 "a.cpp"
#define PROBLEM ""
#line 2 "/home/kuhaku/home/github/algo/lib/template/template.hpp"
#pragma GCC target("sse4.2,avx2,bmi2")
#pragma GCC optimize("O3")
#pragma GCC optimize("unroll-loops")
#include <bits/stdc++.h>
template <class T, class U>
constexpr bool chmax(T &a, const U &b) {
    return a < (T)b ? a = (T)b, true : false;
}
template <class T, class U>
constexpr bool chmin(T &a, const U &b) {
    return (T)b < a ? a = (T)b, true : false;
}
constexpr std::int64_t INF = 1000000000000000003;
constexpr int Inf = 1000000003;
constexpr double EPS = 1e-7;
constexpr double PI = M_PI;
#line 3 "/home/kuhaku/home/github/algo/lib/math/pow.hpp"

std::int64_t safe_mod(std::int64_t a, std::int64_t mod) {
    a %= mod;
    return a >= 0 ? a : a + mod;
}

std::int64_t pow_int(std::int64_t a, std::int64_t n) {
    assert(n >= 0);
    std::int64_t res = 1, mul = a;
    for (; n > 0; n >>= 1) {
        if (n & 1) res *= mul;
        mul *= mul;
    }
    return res;
}

std::int64_t inv_mod(std::int64_t a, std::int64_t mod) {
    std::int64_t b = mod, u = 1, v = 0, t;
    while (b > 0) {
        t = a / b;
        std::swap(a -= t * b, b);
        std::swap(u -= t * v, v);
    }
    return u >= 0 ? u % mod : (mod - (-u) % mod) % mod;
}

std::int64_t pow_mod(std::int64_t a, std::int64_t n, std::int64_t mod) {
    if (n < 0) return inv_mod(pow_mod(a, -n, mod), mod);
    std::int64_t res = 1, mul = safe_mod(a, mod);
    for (; n > 0; n >>= 1) {
        if (n & 1) (res *= mul) %= mod;
        (mul *= mul) %= mod;
    }
    return res;
}

int ceil_pow2(std::int64_t n) {
    int x = 0;
    while ((std::uint64_t(1) << x) < (std::uint64_t)(n)) ++x;
    return x;
}

int floor_pow2(std::int64_t n) {
    int x = 0;
    while ((std::uint64_t(1) << (x + 1)) <= (std::uint64_t)(n)) ++x;
    return x;
}
#line 3 "/home/kuhaku/home/github/algo/lib/segment_tree/monoid.hpp"

template <class T>
struct Add {
    using value_type = T;
    static constexpr T id = T(0);
    static constexpr T op(const T &lhs, const T &rhs) { return lhs + rhs; }

    template <class U>
    static constexpr U f(T lhs, U rhs) {
        return lhs + rhs;
    }
};

template <class T>
struct And {
    using value_type = T;
    static constexpr T id = std::numeric_limits<T>::max();
    static constexpr T op(const T &lhs, const T &rhs) { return lhs & rhs; }

    template <class U>
    static constexpr U f(T lhs, U rhs) {
        return lhs & rhs;
    }
};

template <class T>
struct Or {
    using value_type = T;
    static constexpr T id = T(0);
    static constexpr T op(const T &lhs, const T &rhs) { return lhs | rhs; }

    template <class U>
    static constexpr U f(T lhs, U rhs) {
        return lhs | rhs;
    }
};

template <class T>
struct Xor {
    using value_type = T;
    static constexpr T id = T(0);
    static constexpr T op(const T &lhs, const T &rhs) { return lhs ^ rhs; }

    template <class U>
    static constexpr U f(T lhs, U rhs) {
        return lhs ^ rhs;
    }
};

template <class T>
struct Min {
    using value_type = T;
    static constexpr T id = std::numeric_limits<T>::max();
    static constexpr T op(const T &lhs, const T &rhs) { return std::min(lhs, rhs); }

    template <class U>
    static constexpr U f(T lhs, U rhs) {
        return std::min((U)lhs, rhs);
    }
};

template <class T>
struct Max {
    using value_type = T;
    static constexpr T id = std::numeric_limits<T>::min();
    static constexpr T op(const T &lhs, const T &rhs) { return std::max(lhs, rhs); }

    template <class U>
    static constexpr U f(T lhs, U rhs) {
        return std::max((U)lhs, rhs);
    }
};

template <class T>
struct Update {
    using value_type = T;
    static constexpr T id = std::numeric_limits<T>::max();
    static constexpr T op(const T &lhs, const T &rhs) { return lhs == Update::id ? rhs : lhs; }

    template <class U>
    static constexpr U f(T lhs, U rhs) {
        return lhs == Update::id ? rhs : lhs;
    }
};

template <class T>
struct Affine {
    using value_type = std::pair<T, T>;
    static constexpr std::pair<T, T> id = std::pair<T, T>(1, 0);
    static constexpr std::pair<T, T> op(std::pair<T, T> lhs, std::pair<T, T> rhs) {
        return {lhs.first * rhs.first, lhs.first * rhs.second + lhs.second};
    }
};

template <class M>
struct Rev {
    using T = typename M::value_type;
    using value_type = T;
    static constexpr T id = M::id;
    static constexpr T op(T lhs, T rhs) { return M::op(rhs, lhs); }
};
#line 5 "/home/kuhaku/home/github/algo/lib/segment_tree/lazy_segment_tree.hpp"

/**
 * @brief 遅延評価セグメント木
 * @see https://github.com/atcoder/ac-library/blob/master/atcoder/lazysegtree.hpp
 *
 * @tparam S モノイド
 * @tparam F モノイド
 */
template <class S, class F>
struct lazy_segment_tree {
  private:
    using T = typename S::value_type;
    using U = typename F::value_type;

  public:
    lazy_segment_tree() : lazy_segment_tree(0) {}
    explicit lazy_segment_tree(int n, T e = S::id) : lazy_segment_tree(std::vector<T>(n, e)) {}
    explicit lazy_segment_tree(const std::vector<T> &v) : _n(int(v.size())) {
        this->_log = ceil_pow2(this->_n);
        this->_size = 1 << this->_log;
        this->data = std::vector<T>(2 * this->_size, S::id);
        this->lazy = std::vector<U>(this->_size, F::id);
        for (int i = 0; i < this->_n; i++) this->data[this->_size + i] = v[i];
        for (int i = this->_size - 1; i >= 1; --i) this->update(i);
    }

    void set(int p, T x) {
        assert(0 <= p && p < this->_n);
        p += this->_size;
        for (int i = this->_log; i >= 1; --i) this->push(p >> i);
        this->data[p] = x;
        for (int i = 1; i <= this->_log; ++i) this->update(p >> i);
    }

    T at(int p) { return this->get(p); }
    T get(int p) {
        assert(0 <= p && p < this->_n);
        p += this->_size;
        for (int i = this->_log; i >= 1; --i) this->push(p >> i);
        return this->data[p];
    }

    void apply(int p, U f) {
        assert(0 <= p && p < this->_n);
        p += this->_size;
        for (int i = this->_log; i >= 1; --i) this->push(p >> i);
        this->data[p] = F::f(f, this->data[p]);
        for (int i = 1; i <= this->_log; ++i) this->update(p >> i);
    }
    void apply(int l, int r, U f) {
        assert(0 <= l && l <= r && r <= this->_n);
        if (l == r) return;

        l += this->_size, r += this->_size;

        for (int i = this->_log; i >= 1; --i) {
            if (((l >> i) << i) != l) this->push(l >> i);
            if (((r >> i) << i) != r) this->push((r - 1) >> i);
        }

        int l2 = l, r2 = r;
        while (l < r) {
            if (l & 1) this->all_apply(l++, f);
            if (r & 1) this->all_apply(--r, f);
            l >>= 1, r >>= 1;
        }
        l = l2, r = r2;

        for (int i = 1; i <= this->_log; i++) {
            if (((l >> i) << i) != l) this->update(l >> i);
            if (((r >> i) << i) != r) this->update((r - 1) >> i);
        }
    }

    T prod(int l, int r) {
        assert(0 <= l && l <= r && r <= this->_n);
        if (l == r) return S::id;

        l += this->_size, r += this->_size;

        for (int i = this->_log; i >= 1; --i) {
            if (((l >> i) << i) != l) this->push(l >> i);
            if (((r >> i) << i) != r) this->push((r - 1) >> i);
        }

        T sml = S::id, smr = S::id;
        while (l < r) {
            if (l & 1) sml = S::op(sml, this->data[l++]);
            if (r & 1) smr = S::op(this->data[--r], smr);
            l >>= 1, r >>= 1;
        }

        return S::op(sml, smr);
    }

    T all_prod() const { return this->data[1]; }

  private:
    int _n, _size, _log;
    std::vector<T> data;
    std::vector<U> lazy;

    void update(int k) { this->data[k] = S::op(this->data[2 * k], this->data[2 * k + 1]); }
    void all_apply(int k, U f) {
        this->data[k] = F::f(f, this->data[k]);
        if (k < _size) this->lazy[k] = F::op(f, this->lazy[k]);
    }
    void push(int k) {
        this->all_apply(2 * k, this->lazy[k]);
        this->all_apply(2 * k + 1, this->lazy[k]);
        this->lazy[k] = F::id;
    }
};
#line 3 "/home/kuhaku/home/github/algo/lib/template/macro.hpp"
#define FOR(i, m, n) for (int i = (m); i < int(n); ++i)
#define FORR(i, m, n) for (int i = (m)-1; i >= int(n); --i)
#define FORL(i, m, n) for (int64_t i = (m); i < int64_t(n); ++i)
#define rep(i, n) FOR (i, 0, n)
#define repn(i, n) FOR (i, 1, n + 1)
#define repr(i, n) FORR (i, n, 0)
#define repnr(i, n) FORR (i, n + 1, 1)
#define all(s) (s).begin(), (s).end()
#line 3 "/home/kuhaku/home/github/algo/lib/template/sonic.hpp"
struct Sonic {
    Sonic() {
        std::ios::sync_with_stdio(false);
        std::cin.tie(nullptr);
        std::cout << std::fixed << std::setprecision(20);
    }

    constexpr void operator()() const {}
} sonic;
#line 5 "/home/kuhaku/home/github/algo/lib/template/atcoder.hpp"
using namespace std;
using ll = std::int64_t;
using ld = long double;
template <class T, class U>
std::istream &operator>>(std::istream &is, std::pair<T, U> &p) {
    return is >> p.first >> p.second;
}
template <class T>
std::istream &operator>>(std::istream &is, std::vector<T> &v) {
    for (T &i : v) is >> i;
    return is;
}
template <class T, class U>
std::ostream &operator<<(std::ostream &os, const std::pair<T, U> &p) {
    return os << '(' << p.first << ',' << p.second << ')';
}
template <class T>
std::ostream &operator<<(std::ostream &os, const std::vector<T> &v) {
    for (auto it = v.begin(); it != v.end(); ++it) {
        os << (it == v.begin() ? "" : " ") << *it;
    }
    return os;
}
template <class Head, class... Tail>
void co(Head &&head, Tail &&...tail) {
    if constexpr (sizeof...(tail) == 0) std::cout << head << '\n';
    else std::cout << head << ' ', co(std::forward<Tail>(tail)...);
}
template <class Head, class... Tail>
void ce(Head &&head, Tail &&...tail) {
    if constexpr (sizeof...(tail) == 0) std::cerr << head << '\n';
    else std::cerr << head << ' ', ce(std::forward<Tail>(tail)...);
}
template <typename T, typename... Args>
auto make_vector(T x, int arg, Args... args) {
    if constexpr (sizeof...(args) == 0) return std::vector<T>(arg, x);
    else return std::vector(arg, make_vector<T>(x, args...));
}
void Yes(bool is_correct = true) {
    std::cout << (is_correct ? "Yes" : "No") << '\n';
}
void No(bool is_not_correct = true) {
    Yes(!is_not_correct);
}
void YES(bool is_correct = true) {
    std::cout << (is_correct ? "YES" : "NO") << '\n';
}
void NO(bool is_not_correct = true) {
    YES(!is_not_correct);
}
void Takahashi(bool is_correct = true) {
    std::cout << (is_correct ? "Takahashi" : "Aoki") << '\n';
}
void Aoki(bool is_not_correct = true) {
    Takahashi(!is_not_correct);
}
#line 3 "/home/kuhaku/home/github/algo/lib/graph/graph.hpp"

/**
 * @brief 重み付きグラフ
 *
 * @tparam T 辺の重みの型
 */
template <class T>
struct Graph {
  private:
    struct _edge {
        constexpr _edge() : _from(), _to(), _weight() {}
        constexpr _edge(int from, int to, T weight) : _from(from), _to(to), _weight(weight) {}
        constexpr bool operator<(const _edge &rhs) const { return this->weight() < rhs.weight(); }
        constexpr bool operator>(const _edge &rhs) const { return rhs < *this; }

        constexpr int from() const { return this->_from; }
        constexpr int to() const { return this->_to; }
        constexpr T weight() const { return this->_weight; }

      private:
        int _from, _to;
        T _weight;
    };

  public:
    using edge_type = typename Graph<T>::_edge;

    Graph() : _size(), edges() {}
    Graph(int v) : _size(v), edges(v) {}

    const auto &operator[](int i) const { return this->edges[i]; }
    auto &operator[](int i) { return this->edges[i]; }
    const auto begin() const { return this->edges.begin(); }
    auto begin() { return this->edges.begin(); }
    const auto end() const { return this->edges.end(); }
    auto end() { return this->edges.end(); }
    constexpr int size() const { return this->_size; }

    void add_edge(const edge_type &e) { this->edges[e.from()].emplace_back(e); }
    void add_edge(int from, int to, T weight = T(1)) {
        this->edges[from].emplace_back(from, to, weight);
    }
    void add_edges(int from, int to, T weight = T(1)) {
        this->edges[from].emplace_back(from, to, weight);
        this->edges[to].emplace_back(to, from, weight);
    }

    void input_edge(int m, int base = 1) {
        for (int i = 0; i < m; ++i) {
            int from, to;
            T weight;
            std::cin >> from >> to >> weight;
            this->add_edge(from - base, to - base, weight);
        }
    }
    void input_edges(int m, int base = 1) {
        for (int i = 0; i < m; ++i) {
            int from, to;
            T weight;
            std::cin >> from >> to >> weight;
            this->add_edges(from - base, to - base, weight);
        }
    }

  private:
    int _size;
    std::vector<std::vector<edge_type>> edges;
};

template <>
struct Graph<void> {
  private:
    struct _edge {
        constexpr _edge() : _from(), _to() {}
        constexpr _edge(int from, int to) : _from(from), _to(to) {}

        constexpr int from() const { return this->_from; }
        constexpr int to() const { return this->_to; }
        constexpr int weight() const { return 1; }
        constexpr bool operator<(const _edge &rhs) const { return this->weight() < rhs.weight(); }
        constexpr bool operator>(const _edge &rhs) const { return rhs < *this; }

      private:
        int _from, _to;
    };

  public:
    using edge_type = typename Graph<void>::_edge;

    Graph() : _size(), edges() {}
    Graph(int v) : _size(v), edges(v) {}

    const auto &operator[](int i) const { return this->edges[i]; }
    auto &operator[](int i) { return this->edges[i]; }
    const auto begin() const { return this->edges.begin(); }
    auto begin() { return this->edges.begin(); }
    const auto end() const { return this->edges.end(); }
    auto end() { return this->edges.end(); }
    constexpr int size() const { return this->_size; }

    void add_edge(const edge_type &e) { this->edges[e.from()].emplace_back(e); }
    void add_edge(int from, int to) { this->edges[from].emplace_back(from, to); }
    void add_edges(int from, int to) {
        this->edges[from].emplace_back(from, to);
        this->edges[to].emplace_back(to, from);
    }

    void input_edge(int m, int base = 1) {
        for (int i = 0; i < m; ++i) {
            int from, to;
            std::cin >> from >> to;
            this->add_edge(from - base, to - base);
        }
    }
    void input_edges(int m, int base = 1) {
        for (int i = 0; i < m; ++i) {
            int from, to;
            std::cin >> from >> to;
            this->add_edges(from - base, to - base);
        }
    }

  private:
    int _size;
    std::vector<std::vector<edge_type>> edges;
};
#line 3 "/home/kuhaku/home/github/algo/lib/tree/eular_tour.hpp"

/**
 * @brief オイラーツアー
 * @details [参考](https://github.com/beet-aizu/library/blob/master/tree/eulertourforvertex.cpp)
 *
 * @tparam T 辺の重みの型
 */
template <class T>
struct eular_tour {
    eular_tour(const Graph<T> &_g, int r = 0) : g(_g), ls(_g.size()), rs(_g.size()), pos() {
        this->build(r);
    }

    std::pair<int, int> operator[](int i) const { return {this->ls[i], this->rs[i]}; }

    int size() const { return this->pos; }

    int get_l(int i) const { return this->ls[i]; }
    int get_r(int i) const { return this->rs[i]; }

    template <class F>
    void query(int v, const F &f) const {
        f(this->ls[v], this->rs[v]);
    }

  private:
    const Graph<T> &g;
    std::vector<int> ls, rs;
    int pos;

    void build(int r = 0) {
        this->pos = 0;
        this->dfs(r, -1);
    }

    void dfs(int v, int p) {
        this->ls[v] = this->pos++;
        for (auto &e : this->g[v]) {
            if (e.to() != p) this->dfs(e.to(), v);
        }
        this->rs[v] = this->pos;
    }
};
#line 5 "a.cpp"

struct S {
    int g, w;
};

struct M {
    using T = S;
    using value_type = S;
    static constexpr T id = S{0, 0};
    static constexpr T op(const T &lhs, const T &rhs) {
        return S{lhs.g + rhs.g, lhs.w + rhs.w};
    }
};

struct L {
    using value_type = int;
    static constexpr value_type id = 0;
    static constexpr value_type op(const value_type &lhs, const value_type &rhs) {
        return lhs ^ rhs;
    }

    static S f(const value_type &lhs, S rhs) {
        if (lhs == 0)
            return rhs;
        swap(rhs.g, rhs.w);
        return rhs;
    }
};

int main(void) {
    int n, q;
    cin >> n >> q;
    Graph<void> g(n);
    rep (i, n - 1) {
        int p;
        cin >> p;
        g.add_edges(p - 1, i + 1);
    }
    eular_tour et(g);
    vector<S> v(n);
    rep (i, n) {
        char c;
        cin >> c;
        if (c == 'G')
            v[et.get_l(i)] = S{1, 0};
        else
            v[et.get_l(i)] = S{0, 1};
    }
    lazy_segment_tree<M, L> lst(v);
    while (q--) {
        int x;
        cin >> x;
        --x;
        lst.apply(et.get_l(x), et.get_r(x), 1);
        auto [g, w] = lst.all_prod();
        if (g >= w)
            co("broccoli");
        else
            co("cauliflower");
    }

    return 0;
}
accuracy: 1
time_ms: 40
memory_kb: 18916
final_rank: 4

code_snippet: #include <bits/stdc++.h>
#pragma GCC optimize("Ofast")
using namespace std;
using std::cout;
using std::cin;
using std::endl;
using ll=long long;
using ld=long double;
ll ILL=2167167167167167167;
const int INF=2100000000;
const ll mod=1e9+7;
#define rep(i,a) for (ll i=0;i<a;i++)
#define all(p) p.begin(),p.end()
template<class T> using _pq = priority_queue<T, vector<T>, greater<T>>;
template<class T> ll LB(vector<T> &v,T a){return lower_bound(v.begin(),v.end(),a)-v.begin();}
template<class T> ll UB(vector<T> &v,T a){return upper_bound(v.begin(),v.end(),a)-v.begin();}
template<class T> bool chmin(T &a,const T &b){if(a>b){a=b;return 1;}else return 0;}
template<class T> bool chmax(T &a,const T &b){if(a<b){a=b;return 1;}else return 0;}
template<class T> void So(vector<T> &v) {sort(v.begin(),v.end());}
template<class T> void Sore(vector<T> &v) {sort(v.begin(),v.end(),[](T x,T y){return x>y;});}
void yneos(bool a){if(a) cout<<"Yes\n"; else cout<<"No\n";}
template<class T> void vec_out(vector<T> &p){for(int i=0;i<(int)(p.size());i++){if(i) cout<<" ";cout<<p[i];}cout<<"\n";}
template<class T> T min(vector<T> &a){assert(!a.empty());T ans=a[0];for(auto &x:a) chmin(ans,x);return ans;}
template<class T> T max(vector<T> &a){assert(!a.empty());T ans=a[0];for(auto &x:a) chmax(ans,x);return ans;}


namespace atcoder {

namespace internal {

// @param n `0 <= n`
// @return minimum non-negative `x` s.t. `n <= 2**x`
int ceil_pow2(int n) {
    int x = 0;
    while ((1U << x) < (unsigned int)(n)) x++;
    return x;
}

// @param n `1 <= n`
// @return minimum non-negative `x` s.t. `(n & (1 << x)) != 0`
int bsf(unsigned int n) {
#ifdef _MSC_VER
    unsigned long index;
    _BitScanForward(&index, n);
    return index;
#else
    return __builtin_ctz(n);
#endif
}

}  // namespace internal

template <class S,
          S (*op)(S, S),
          S (*e)(),
          class F,
          S (*mapping)(F, S),
          F (*composition)(F, F),
          F (*id)()>
struct lazy_segtree {
  public:
    lazy_segtree() : lazy_segtree(0) {}
    lazy_segtree(int n) : lazy_segtree(std::vector<S>(n, e())) {}
    lazy_segtree(const std::vector<S>& v) : _n(int(v.size())) {
        log = internal::ceil_pow2(_n);
        size = 1 << log;
        d = std::vector<S>(2 * size, e());
        lz = std::vector<F>(size, id());
        for (int i = 0; i < _n; i++) d[size + i] = v[i];
        for (int i = size - 1; i >= 1; i--) {
            update(i);
        }
    }

    void set(int p, S x) {
        assert(0 <= p && p < _n);
        p += size;
        for (int i = log; i >= 1; i--) push(p >> i);
        d[p] = x;
        for (int i = 1; i <= log; i++) update(p >> i);
    }

    S get(int p) {
        assert(0 <= p && p < _n);
        p += size;
        for (int i = log; i >= 1; i--) push(p >> i);
        return d[p];
    }

    S prod(int l, int r) {
        assert(0 <= l && l <= r && r <= _n);
        if (l == r) return e();

        l += size;
        r += size;

        for (int i = log; i >= 1; i--) {
            if (((l >> i) << i) != l) push(l >> i);
            if (((r >> i) << i) != r) push(r >> i);
        }

        S sml = e(), smr = e();
        while (l < r) {
            if (l & 1) sml = op(sml, d[l++]);
            if (r & 1) smr = op(d[--r], smr);
            l >>= 1;
            r >>= 1;
        }

        return op(sml, smr);
    }

    S all_prod() { return d[1]; }

    void apply(int p, F f) {
        assert(0 <= p && p < _n);
        p += size;
        for (int i = log; i >= 1; i--) push(p >> i);
        d[p] = mapping(f, d[p]);
        for (int i = 1; i <= log; i++) update(p >> i);
    }
    void apply(int l, int r, F f) {
        assert(0 <= l && l <= r && r <= _n);
        if (l == r) return;

        l += size;
        r += size;

        for (int i = log; i >= 1; i--) {
            if (((l >> i) << i) != l) push(l >> i);
            if (((r >> i) << i) != r) push((r - 1) >> i);
        }

        {
            int l2 = l, r2 = r;
            while (l < r) {
                if (l & 1) all_apply(l++, f);
                if (r & 1) all_apply(--r, f);
                l >>= 1;
                r >>= 1;
            }
            l = l2;
            r = r2;
        }

        for (int i = 1; i <= log; i++) {
            if (((l >> i) << i) != l) update(l >> i);
            if (((r >> i) << i) != r) update((r - 1) >> i);
        }
    }

    template <bool (*g)(S)> int max_right(int l) {
        return max_right(l, [](S x) { return g(x); });
    }
    template <class G> int max_right(int l, G g) {
        assert(0 <= l && l <= _n);
        assert(g(e()));
        if (l == _n) return _n;
        l += size;
        for (int i = log; i >= 1; i--) push(l >> i);
        S sm = e();
        do {
            while (l % 2 == 0) l >>= 1;
            if (!g(op(sm, d[l]))) {
                while (l < size) {
                    push(l);
                    l = (2 * l);
                    if (g(op(sm, d[l]))) {
                        sm = op(sm, d[l]);
                        l++;
                    }
                }
                return l - size;
            }
            sm = op(sm, d[l]);
            l++;
        } while ((l & -l) != l);
        return _n;
    }

    template <bool (*g)(S)> int min_left(int r) {
        return min_left(r, [](S x) { return g(x); });
    }
    template <class G> int min_left(int r, G g) {
        assert(0 <= r && r <= _n);
        assert(g(e()));
        if (r == 0) return 0;
        r += size;
        for (int i = log; i >= 1; i--) push((r - 1) >> i);
        S sm = e();
        do {
            r--;
            while (r > 1 && (r % 2)) r >>= 1;
            if (!g(op(d[r], sm))) {
                while (r < size) {
                    push(r);
                    r = (2 * r + 1);
                    if (g(op(d[r], sm))) {
                        sm = op(d[r], sm);
                        r--;
                    }
                }
                return r + 1 - size;
            }
            sm = op(d[r], sm);
        } while ((r & -r) != r);
        return 0;
    }

  private:
    int _n, size, log;
    std::vector<S> d;
    std::vector<F> lz;

    void update(int k) { d[k] = op(d[2 * k], d[2 * k + 1]); }
    void all_apply(int k, F f) {
        d[k] = mapping(f, d[k]);
        if (k < size) lz[k] = composition(f, lz[k]);
    }
    void push(int k) {
        all_apply(2 * k, lz[k]);
        all_apply(2 * k + 1, lz[k]);
        lz[k] = id();
    }
};

}  // namespace atcoder
using namespace atcoder;


struct lazy_S {
    ll B;
	ll W;	
};

using lazy_F = int;

lazy_S lazy_op(lazy_S l, lazy_S r) {
    return lazy_S{
		l.B+r.B,r.W+l.W
    };
}

lazy_S lazy_e() { return lazy_S{0, 0}; }

lazy_S mapping(lazy_F l, lazy_S r) {
    return lazy_S{
		r.W*l+(1-l)*r.B,r.W*(1-l)+l*r.B
	};
}

//l(r(x))
lazy_F composition(lazy_F l, lazy_F r) {
	return l^r;
}

lazy_F lazy_id(){return 0;}

#define lazy_calc lazy_S,lazy_op,lazy_e,lazy_F,mapping,composition,lazy_id

//in[i] -> p[i]
//out[i] -> p[i+N]
std::vector<int> Euler_Tour(std::vector<std::vector<int>> &G,int root){
	std::stack<int> s;
	int n=G.size();
	std::vector<int> p(n*2),seen(n);
	s.push(root);
	seen[root]=1;
	for(int i=0;i<2*n;i++){
		int a=s.top();
		p[a]=i;
		s.pop();
		if(a<n){
			s.push(a+n);
			for(auto x:G[a]){
				if(seen[x]==0){
					s.push(x);
					seen[x]=1;
				}
			}
		}
	}
	return p;
}


void solve();
// oddloop
int main() {
	ios::sync_with_stdio(false);
	cin.tie(nullptr);
	
	int t=1;
	//cin>>t;
	rep(i,t) solve();
}

void solve(){
	int N,Q;
	cin>>N>>Q;
	vector<vector<int>> G(N);
	rep(i,N-1){
		int a;
		cin>>a;
		G[a-1].push_back(i+1);
	}
	auto E=Euler_Tour(G,0);
	lazy_segtree<lazy_calc> seg(2*N);
	rep(i,N){
		char c;
		cin>>c;
		if(c=='G') seg.set(E[i],{1,0});
		else seg.set(E[i],{0,1});
	}
	rep(i,Q){
		int a;
		cin>>a;
		seg.apply(E[a-1],E[a-1+N],1);
		auto tmp=seg.all_prod();
		if(tmp.B<tmp.W) cout<<"cauliflower\n";
		else cout<<"broccoli\n";
	}
}
accuracy: 1
time_ms: 50
memory_kb: 21928
final_rank: 7

code_snippet: #include <algorithm>
#include <bitset>
#include <cassert>
#include <chrono>
#include <climits>
#include <cmath>
#include <cstddef>
#include <cstdint>
#include <cstdlib>
#include <functional>
#include <iomanip>
#include <iostream>
#include <limits>
#include <map>
#include <memory>
#include <numeric>
#include <optional>
#include <queue>
#include <random>
#include <set>
#include <stack>
#include <string>
#include <tuple>
#include <type_traits>
#include <unordered_map>
#include <unordered_set>
#include <utility>
#include <vector>

/* macro */

#define rep(i, a, n) for (int i = (int)(a); i < (int)(n); i++)
#define rrep(i, a, n) for (int i = ((int)(n - 1)); i >= (int)(a); i--)
#define Rep(i, a, n) for (i64 i = (i64)(a); i < (i64)(n); i++)
#define RRep(i, a, n) for (i64 i = ((i64)(n - i64(1))); i >= (i64)(a); i--)
#define all(v) (v).begin(), (v).end()
#define rall(v) (v).rbegin(), (v).rend()
#define Bit(n) (1LL << (n))

/* macro end */

/* template */

namespace ebi {

#ifdef LOCAL
#define debug(...)                                                      \
    std::cerr << "LINE: " << __LINE__ << "  [" << #__VA_ARGS__ << "]:", \
        debug_out(__VA_ARGS__)
#else
#define debug(...)
#endif

void debug_out() { std::cerr << std::endl; }

template <typename Head, typename... Tail>
void debug_out(Head h, Tail... t) {
    std::cerr << " " << h;
    if (sizeof...(t) > 0) std::cout << " :";
    debug_out(t...);
}

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

template <typename T1, typename T2>
std::istream &operator>>(std::istream &os, std::pair<T1, T2> &pa) {
    return os >> pa.first >> pa.second;
}

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

template <typename T>
std::istream &operator>>(std::istream &os, std::vector<T> &vec) {
    for (T &e : vec) std::cin >> e;
    return os;
}

template <typename T>
std::ostream &operator<<(std::ostream &os, const std::optional<T> &opt) {
    if (opt) {
        os << opt.value();
    } else {
        os << "invalid value";
    }
    return os;
}

using std::size_t;
using i32 = std::int32_t;
using u32 = std::uint32_t;
using i64 = std::int64_t;
using u64 = std::uint64_t;

template <class T, T init>
auto make_vector(int n) {
    return std::vector<T>(n, init);
}

template <class T, T init, typename Head, typename... Tail>
auto make_vector(Head n, Tail... ts) {
    return std::vector(n, make_vector<T, init>(ts...));
}

template <class T>
inline bool chmin(T &a, T b) {
    if (a > b) {
        a = b;
        return true;
    }
    return false;
}

template <class T>
inline bool chmax(T &a, T b) {
    if (a < b) {
        a = b;
        return true;
    }
    return false;
}

template <class T>
T pow(T x, i64 n) {
    T res = 1;
    while (n > 0) {
        if (n & 1) res = res * x;
        x = x * x;
        n >>= 1;
    }
    return res;
}

template <class T>
T mod_pow(T x, i64 n, i64 mod) {
    T res = 1;
    while (n > 0) {
        if (n & 1) res = (res * x) % mod;
        x = (x * x) % mod;
        n >>= 1;
    }
    return res;
}

template <class T>
T scan() {
    T val;
    std::cin >> val;
    return val;
}

template <class T>
struct Edge {
    int to;
    T cost;
    Edge(int _to, T _cost = 1) : to(_to), cost(_cost) {}
};

template <class T>
struct Graph : std::vector<std::vector<Edge<T>>> {
    using std::vector<std::vector<Edge<T>>>::vector;
    void add_edge(int u, int v, T w, bool directed = false) {
        (*this)[u].emplace_back(v, w);
        if (directed) return;
        (*this)[v].emplace_back(u, w);
    }
};

struct graph : std::vector<std::vector<int>> {
    using std::vector<std::vector<int>>::vector;
    void add_edge(int u, int v, bool directed = false) {
        (*this)[u].emplace_back(v);
        if (directed) return;
        (*this)[v].emplace_back(u);
    }
};

constexpr i64 LNF = std::numeric_limits<i64>::max() / 4;

constexpr int INF = std::numeric_limits<int>::max() / 2;

const std::vector<int> dy = {1, 0, -1, 0, 1, 1, -1, -1};
const std::vector<int> dx = {0, 1, 0, -1, 1, -1, 1, -1};

}  // namespace ebi


#include <algorithm>
#include <cassert>
#include <iostream>
#include <vector>


#ifdef _MSC_VER
#include <intrin.h>
#endif

namespace atcoder {

namespace internal {

int ceil_pow2(int n) {
    int x = 0;
    while ((1U << x) < (unsigned int)(n)) x++;
    return x;
}

constexpr int bsf_constexpr(unsigned int n) {
    int x = 0;
    while (!(n & (1 << x))) x++;
    return x;
}

int bsf(unsigned int n) {
#ifdef _MSC_VER
    unsigned long index;
    _BitScanForward(&index, n);
    return index;
#else
    return __builtin_ctz(n);
#endif
}

}  // namespace internal

}  // namespace atcoder


namespace atcoder {

template <class S,
          S (*op)(S, S),
          S (*e)(),
          class F,
          S (*mapping)(F, S),
          F (*composition)(F, F),
          F (*id)()>
struct lazy_segtree {
  public:
    lazy_segtree() : lazy_segtree(0) {}
    explicit lazy_segtree(int n) : lazy_segtree(std::vector<S>(n, e())) {}
    explicit lazy_segtree(const std::vector<S>& v) : _n(int(v.size())) {
        log = internal::ceil_pow2(_n);
        size = 1 << log;
        d = std::vector<S>(2 * size, e());
        lz = std::vector<F>(size, id());
        for (int i = 0; i < _n; i++) d[size + i] = v[i];
        for (int i = size - 1; i >= 1; i--) {
            update(i);
        }
    }

    void set(int p, S x) {
        assert(0 <= p && p < _n);
        p += size;
        for (int i = log; i >= 1; i--) push(p >> i);
        d[p] = x;
        for (int i = 1; i <= log; i++) update(p >> i);
    }

    S get(int p) {
        assert(0 <= p && p < _n);
        p += size;
        for (int i = log; i >= 1; i--) push(p >> i);
        return d[p];
    }

    S prod(int l, int r) {
        assert(0 <= l && l <= r && r <= _n);
        if (l == r) return e();

        l += size;
        r += size;

        for (int i = log; i >= 1; i--) {
            if (((l >> i) << i) != l) push(l >> i);
            if (((r >> i) << i) != r) push((r - 1) >> i);
        }

        S sml = e(), smr = e();
        while (l < r) {
            if (l & 1) sml = op(sml, d[l++]);
            if (r & 1) smr = op(d[--r], smr);
            l >>= 1;
            r >>= 1;
        }

        return op(sml, smr);
    }

    S all_prod() { return d[1]; }

    void apply(int p, F f) {
        assert(0 <= p && p < _n);
        p += size;
        for (int i = log; i >= 1; i--) push(p >> i);
        d[p] = mapping(f, d[p]);
        for (int i = 1; i <= log; i++) update(p >> i);
    }
    void apply(int l, int r, F f) {
        assert(0 <= l && l <= r && r <= _n);
        if (l == r) return;

        l += size;
        r += size;

        for (int i = log; i >= 1; i--) {
            if (((l >> i) << i) != l) push(l >> i);
            if (((r >> i) << i) != r) push((r - 1) >> i);
        }

        {
            int l2 = l, r2 = r;
            while (l < r) {
                if (l & 1) all_apply(l++, f);
                if (r & 1) all_apply(--r, f);
                l >>= 1;
                r >>= 1;
            }
            l = l2;
            r = r2;
        }

        for (int i = 1; i <= log; i++) {
            if (((l >> i) << i) != l) update(l >> i);
            if (((r >> i) << i) != r) update((r - 1) >> i);
        }
    }

    template <bool (*g)(S)> int max_right(int l) {
        return max_right(l, [](S x) { return g(x); });
    }
    template <class G> int max_right(int l, G g) {
        assert(0 <= l && l <= _n);
        assert(g(e()));
        if (l == _n) return _n;
        l += size;
        for (int i = log; i >= 1; i--) push(l >> i);
        S sm = e();
        do {
            while (l % 2 == 0) l >>= 1;
            if (!g(op(sm, d[l]))) {
                while (l < size) {
                    push(l);
                    l = (2 * l);
                    if (g(op(sm, d[l]))) {
                        sm = op(sm, d[l]);
                        l++;
                    }
                }
                return l - size;
            }
            sm = op(sm, d[l]);
            l++;
        } while ((l & -l) != l);
        return _n;
    }

    template <bool (*g)(S)> int min_left(int r) {
        return min_left(r, [](S x) { return g(x); });
    }
    template <class G> int min_left(int r, G g) {
        assert(0 <= r && r <= _n);
        assert(g(e()));
        if (r == 0) return 0;
        r += size;
        for (int i = log; i >= 1; i--) push((r - 1) >> i);
        S sm = e();
        do {
            r--;
            while (r > 1 && (r % 2)) r >>= 1;
            if (!g(op(d[r], sm))) {
                while (r < size) {
                    push(r);
                    r = (2 * r + 1);
                    if (g(op(d[r], sm))) {
                        sm = op(d[r], sm);
                        r--;
                    }
                }
                return r + 1 - size;
            }
            sm = op(d[r], sm);
        } while ((r & -r) != r);
        return 0;
    }

  private:
    int _n, size, log;
    std::vector<S> d;
    std::vector<F> lz;

    void update(int k) { d[k] = op(d[2 * k], d[2 * k + 1]); }
    void all_apply(int k, F f) {
        d[k] = mapping(f, d[k]);
        if (k < size) lz[k] = composition(f, lz[k]);
    }
    void push(int k) {
        all_apply(2 * k, lz[k]);
        all_apply(2 * k + 1, lz[k]);
        lz[k] = id();
    }
};

}  // namespace atcoder


namespace ebi {

struct S {
    int b, w;
};

S op(S a, S b) {
    return {a.b + b.b, a.w + b.w};
}

S e() {
    return {0, 0};
}

using F = int;

S mapping(F f, S x) {
    if (f == 0) return x;
    else return {x.w, x.b};
}

F composition(F f, F g) {
    return (f + g) % 2;
}

F id() {
    return 0;
}

void main_() {
    int n,q;
    std::cin >> n >> q;
    graph g(n);
    rep(i,1,n) {
        int p;
        std::cin >> p;
        p--;
        g.add_edge(i, p);
    }
    std::vector<int> c(n);
    rep(i,0,n) {
        char ch;
        std::cin >> ch;
        if(ch == 'G') {
            c[i] = 0;
        }
        else {
            c[i] = 1;
        }
    }
    std::vector<int> in(n, -1), out(n, -1);
    int cnt = 0;
    auto euler_tour = [&](auto &&self, int v, int par = -1) -> void {
        in[v] = cnt++;
        for(auto nv: g[v]) if(nv != par) {
            self(self, nv, v);
        }
        out[v] = cnt;
    };
    euler_tour(euler_tour, 0);
    atcoder::lazy_segtree<S, op, e, F, mapping, composition, id> seg(n);
    rep(i,0,n) {
        S s = e();
        if(c[i] == 0) s.b = 1;
        else s.w = 1;
        seg.set(in[i], s);
    }
    while(q--) {
        int v;
        std::cin >> v;
        v--;
        seg.apply(in[v], out[v], 1);
        auto [b, w] = seg.all_prod();
        if(b > w) {
            std::cout << "broccoli\n";
        }
        else {
            std::cout << "cauliflower\n";
        }

    }
}

}  // namespace ebi

int main() {
    std::cout << std::fixed << std::setprecision(15);
    std::cin.tie(nullptr);
    std::ios::sync_with_stdio(false);
    int t = 1;
    // std::cin >> t;
    while (t--) {
        ebi::main_();
    }
    return 0;
}
accuracy: 1
time_ms: 50
memory_kb: 21028
final_rank: 6

code_snippet: #define LOCAL
#include <bits/stdc++.h>
using namespace std;
#pragma region Macros
typedef long long ll;
typedef __int128_t i128;
typedef unsigned int uint;
typedef unsigned long long ull;
#define ALL(x) (x).begin(), (x).end()

template <typename T> istream& operator>>(istream& is, vector<T>& v) {
    for (T& x : v) is >> x;
    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 == (int)v.size() ? "" : " ");
    }
    return os;
}
template <typename T, typename U> ostream& operator<<(ostream& os, const pair<T, U>& p) {
    os << '(' << p.first << ',' << p.second << ')';
    return os;
}
template <typename T, typename U> ostream& operator<<(ostream& os, const map<T, U>& m) {
    os << '{';
    for (auto itr = m.begin(); itr != m.end();) {
        os << '(' << itr->first << ',' << itr->second << ')';
        if (++itr != m.end()) os << ',';
    }
    os << '}';
    return os;
}
template <typename T, typename U> ostream& operator<<(ostream& os, const unordered_map<T, U>& m) {
    os << '{';
    for (auto itr = m.begin(); itr != m.end();) {
        os << '(' << itr->first << ',' << itr->second << ')';
        if (++itr != m.end()) os << ',';
    }
    os << '}';
    return os;
}
template <typename T> ostream& operator<<(ostream& os, const set<T>& s) {
    os << '{';
    for (auto itr = s.begin(); itr != s.end();) {
        os << *itr;
        if (++itr != s.end()) os << ',';
    }
    os << '}';
    return os;
}
template <typename T> ostream& operator<<(ostream& os, const multiset<T>& s) {
    os << '{';
    for (auto itr = s.begin(); itr != s.end();) {
        os << *itr;
        if (++itr != s.end()) os << ',';
    }
    os << '}';
    return os;
}
template <typename T> ostream& operator<<(ostream& os, const unordered_set<T>& s) {
    os << '{';
    for (auto itr = s.begin(); itr != s.end();) {
        os << *itr;
        if (++itr != s.end()) os << ',';
    }
    os << '}';
    return os;
}
template <typename T> ostream& operator<<(ostream& os, const deque<T>& v) {
    for (int i = 0; i < (int)v.size(); i++) {
        os << v[i] << (i + 1 == (int)v.size() ? "" : " ");
    }
    return os;
}

template <int i, typename T> void print_tuple(ostream&, const T&) {}
template <int i, typename T, typename H, class... Args> void print_tuple(ostream& os, const T& t) {
    if (i) os << ',';
    os << get<i>(t);
    print_tuple<i + 1, T, Args...>(os, t);
}
template <typename... Args> ostream& operator<<(ostream& os, const tuple<Args...>& t) {
    os << '{';
    print_tuple<0, tuple<Args...>, Args...>(os, t);
    return os << '}';
}

void debug_out() { cerr << '\n'; }
template <class Head, class... Tail> void debug_out(Head&& head, Tail&&... tail) {
    cerr << head;
    if (sizeof...(Tail) > 0) cerr << ", ";
    debug_out(move(tail)...);
}
#ifdef LOCAL
#define debug(...)                                                                   \
    cerr << " ";                                                                     \
    cerr << #__VA_ARGS__ << " :[" << __LINE__ << ":" << __FUNCTION__ << "]" << '\n'; \
    cerr << " ";                                                                     \
    debug_out(__VA_ARGS__)
#else
#define debug(...) 42
#endif

template <typename T> T gcd(T x, T y) { return y != 0 ? gcd(y, x % y) : x; }
template <typename T> T lcm(T x, T y) { return x / gcd(x, y) * y; }

int topbit(signed t) { return t == 0 ? -1 : 31 - __builtin_clz(t); }
int topbit(long long t) { return t == 0 ? -1 : 63 - __builtin_clzll(t); }
int botbit(signed a) { return a == 0 ? 32 : __builtin_ctz(a); }
int botbit(long long a) { return a == 0 ? 64 : __builtin_ctzll(a); }
int popcount(signed t) { return __builtin_popcount(t); }
int popcount(long long t) { return __builtin_popcountll(t); }
bool ispow2(int i) { return i && (i & -i) == i; }

template <class T> T ceil(T x, T y) {
    assert(y >= 1);
    return (x > 0 ? (x + y - 1) / y : x / y);
}
template <class T> T floor(T x, T y) {
    assert(y >= 1);
    return (x > 0 ? x / y : (x - y + 1) / y);
}

template <class T1, class T2> inline bool chmin(T1& a, T2 b) {
    if (a > b) {
        a = b;
        return true;
    }
    return false;
}
template <class T1, class T2> inline bool chmax(T1& a, T2 b) {
    if (a < b) {
        a = b;
        return true;
    }
    return false;
}
#pragma endregion

#include <cassert>
#include <vector>

template <typename Monoid, typename OperatorMonoid, typename F, typename G, typename H> struct LazySegmentTree {
    LazySegmentTree(int n, const F f, const G g, const H h, const Monoid& e, const OperatorMonoid& id)
        : n(n), f(f), g(g), h(h), e(e), id(id) {
        size = 1;
        height = 0;
        while (size < n) size <<= 1, height++;
        data.assign(size << 1, e);
        lazy.assign(size << 1, id);
    }

    void set(int k, Monoid x) {
        assert(0 <= k && k < n);
        data[k + size] = x;
    }

    void build() {
        for (int k = size - 1; k > 0; k--) {
            data[k] = f(data[k << 1 | 0], data[k << 1 | 1]);
        }
    }

    void update(int a, int b, const OperatorMonoid& x) {
        assert(0 <= a && a <= b && b <= n);
        if (a == b) return;
        thrust(a += size);
        thrust(b += size - 1);
        for (int l = a, r = b + 1; l < r; l >>= 1, r >>= 1) {
            if (l & 1) lazy[l] = h(lazy[l], x), ++l;
            if (r & 1) --r, lazy[r] = h(lazy[r], x);
        }
        recalc(a);
        recalc(b);
    }

    void set_val(int k, Monoid x) {
        assert(0 <= k && k < n);
        thrust(k += size);
        data[k] = x;
        lazy[k] = id;
        recalc(k);
    }

    Monoid query(int a, int b) {
        assert(0 <= a && a <= b && b <= n);
        if (a == b) return e;
        thrust(a += size);
        thrust(b += size - 1);
        Monoid L = e, R = e;
        for (int l = a, r = b + 1; l < r; l >>= 1, r >>= 1) {
            if (l & 1) L = f(L, apply(l++));
            if (r & 1) R = f(apply(--r), R);
        }
        return f(L, R);
    }

    Monoid operator[](int k) {
        thrust(k += size);
        return apply(k);
    }

    template <typename C> int find_first(int l, const C& check) {
        assert(0 <= l && l <= n);
        assert(!check(e));
        if (l == n) return n;
        Monoid L = e;
        if (l == 0) {
            if (check(f(L, apply(1)))) return find_subtree(1, check, L, false);
            return n;
        }
        thrust(l + size);
        int r = size;
        for (l += size, r += size; l < r; l >>= 1, r >>= 1) {
            if (l & 1) {
                Monoid nxt = f(L, apply(l));
                if (check(nxt)) return find_subtree(l, check, L, false);
                L = nxt;
                l++;
            }
        }
        return n;
    }

    template <typename C> int find_last(int r, const C& check) {
        assert(0 <= r && r <= n);
        assert(!check(e));
        if (r == 0) return 0;
        Monoid R = e;
        if (r == n) {
            if (check(f(apply(1), R))) return find_subtree(1, check, R, true);
            return -1;
        }
        thrust(r + size - 1);
        int l = size;
        for (r += size; l < r; l >>= 1, r >>= 1) {
            if (r & 1) {
                Monoid nxt = f(apply(--r), R);
                if (check(nxt)) return find_subtree(r, check, R, true);
                R = nxt;
            }
        }
        return -1;
    }

private:
    int n, size, height;
    std::vector<Monoid> data;
    std::vector<OperatorMonoid> lazy;
    const F f;
    const G g;
    const H h;
    const Monoid e;
    const OperatorMonoid id;

    inline Monoid apply(int k) { return lazy[k] == id ? data[k] : g(data[k], lazy[k]); }

    inline void propagate(int k) {
        if (lazy[k] == id) return;
        lazy[k << 1 | 0] = h(lazy[k << 1 | 0], lazy[k]);
        lazy[k << 1 | 1] = h(lazy[k << 1 | 1], lazy[k]);
        data[k] = apply(k);
        lazy[k] = id;
    }

    inline void thrust(int k) {
        for (int i = height; i > 0; i--) propagate(k >> i);
    }

    inline void recalc(int k) {
        while (k >>= 1) data[k] = f(apply(k << 1 | 0), apply(k << 1 | 1));
    }

    template <typename C> int find_subtree(int a, const C& check, Monoid& M, bool type) {
        while (a < size) {
            propagate(a);
            Monoid nxt = type ? f(apply(1 << a | type), M) : f(M, apply(1 << a | type));
            if (check(nxt))
                a = 1 << a | type;
            else
                M = nxt, a = (a << 1 | 1) - type;
        }
        return a - size;
    }
};

/**
 * @brief Lazy Segment Tree
 * @docs docs/datastructure/LazySegmentTree.md
 */

/**
 * @brief Euler Tour (部分木に対する操作)
 * @docs docs/tree/EulerTourforVertex.md
 */
class EulerTourforVertex {
    vector<int> ls, rs;
    int time;
    void dfs(int v, int p) {
        ls[v] = time++;
        for (int u : G[v]) {
            if (u != p) dfs(u, v);
        }
        rs[v] = time;
    }

public:
    vector<vector<int>> G;
    EulerTourforVertex(int n) : ls(n), rs(n), G(n) {}
    void add_edge(int u, int v) {
        G[u].emplace_back(v);
        G[v].emplace_back(u);
    }
    void build(int r = 0) {
        time = 0;
        dfs(r, -1);
    }
    int idx(int v) { return ls[v]; }
    template <typename F> void exec(int v, F f) { f(ls[v], rs[v]); }
};

const int INF = 1e9;
const long long IINF = 1e18;
const int dx[4] = {1, 0, -1, 0}, dy[4] = {0, 1, 0, -1};
const char dir[4] = {'D', 'R', 'U', 'L'};
const long long MOD = 1000000007;
// const long long MOD = 998244353;

int main() {
    cin.tie(0);
    ios::sync_with_stdio(false);
    int n, q;
    cin >> n >> q;

    EulerTourforVertex ET(n);
    for (int i = 1; i < n; i++) {
        int p;
        cin >> p;
        ET.add_edge(--p, i);
    }
    vector<char> c(n);
    for (int i = 0; i < n; i++) cin >> c[i];

    ET.build();
    struct node {
        int G, W;
        node(int G, int W) : G(G), W(W) {}
    };
    auto f = [](node a, node b) { return node(a.G + b.G, a.W + b.W); };
    auto g = [](node a, int x) { return x ? node(a.W, a.G) : a; };
    auto h = [](int a, int b) { return a ^ b; };
    LazySegmentTree<node, int, decltype(f), decltype(g), decltype(h)> seg(n, f, g, h, node(0, 0), 0);
    for (int i = 0; i < n; i++) seg.set(ET.idx(i), c[i] == 'G' ? node(1, 0) : node(0, 1));
    seg.build();
    auto F = [&](int l, int r) { seg.update(l, r, 1); };

    for (; q--;) {
        int v;
        cin >> v;
        ET.exec(--v, F);
        auto ans = seg.query(0, n);
        cout << (ans.G > ans.W ? "broccoli" : "cauliflower") << '\n';
    }
    return 0;
}
accuracy: 1
time_ms: 50
memory_kb: 18772
final_rank: 5

code_snippet: #include<bits/stdc++.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define HUGE_NUM 4000000000000000000 //オーバーフローに注意
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;


#define SIZE 100005

enum Type{
	Black,
	White,
};

int N,IND = 0;
ll table[2][6*SIZE];
int LEFT[SIZE],RIGHT[SIZE];
bool is_black[SIZE],is_rev[6*SIZE];
vector<int> G[SIZE];


void init(int first_N){
	N = 1;
	while(N < first_N)N *= 2;
}

void update(int loc,Type type,ll value){
	loc += N-1;

	table[type][loc] = value;

	if(N == 1)return;

	int parent = (loc-1)/2;

	while(true){
		table[type][parent] = table[type][2*parent+1]+table[type][2*parent+2];

		if(parent == 0)break;
		else{
			parent = (parent-1)/2;
		}
	}
}


void range_update(int search_left,int search_right,int node_id,int node_left,int node_right){

	//今回のノードが検索区間をカバーしていない場合
	if(search_right < node_left || search_left > node_right){

		return;
	}

	//今回のノードの区間が、検索区間の部分区間である場合
	if(search_left <= node_left && search_right >= node_right){
		is_rev[node_id] = not is_rev[node_id];

		swap(table[Black][node_id],table[White][node_id]);
		return;
	}

	if(is_rev[node_id]){ //★反転区間の部分区間に、反転命令が下った場合★

		//子を反転する
		range_update(node_left,node_right,2*node_id+1,node_left,(node_left+node_right)/2);
		range_update(node_left,node_right,2*node_id+2,(node_left+node_right)/2+1,node_right);
		is_rev[node_id] = false;
	}

	//今回のノードの区間に、一部検索区間と重なっている区間がある場合
	range_update(search_left,search_right,2*node_id+1,node_left,(node_left+node_right)/2);
	range_update(search_left,search_right,2*node_id+2,(node_left+node_right)/2+1,node_right);

	table[Black][node_id] = table[Black][2*node_id+1]+table[Black][2*node_id+2];
	table[White][node_id] = table[White][2*node_id+1]+table[White][2*node_id+2];
}

void euler_tour(int node_id,int pre){

	LEFT[node_id] = IND++;

	for(int i = 0; i < G[node_id].size(); i++){

		int child = G[node_id][i];
		if(child == pre)continue;

		euler_tour(child,node_id);
	}

	RIGHT[node_id] = IND++;
}

int main(){

	int first_N,num_Q;
	scanf("%d %d",&first_N,&num_Q);

	int p;
	for(int i = 1; i <= first_N-1; i++){

		scanf("%d",&p);
		p--;

		G[p].push_back(i);
	}

	char buf[2];

	for(int i = 0; i < first_N; i++){

		scanf("%s",buf);

		is_black[i] = (buf[0]=='G');
	}

	euler_tour(0,-1);

	init(RIGHT[0]); //★★★セグ木を初期化する際の要素数に注意!!!★★★


	//0～N-2が上位構造のアドレス、N-1～2*N-2が最小要素のアドレス
	for(int i = 0; i <= 2*N-2; i++){

		is_rev[i] = false;
		table[Black][i] = 0;
		table[White][i] = 0;
	}

	for(int i = 0; i < first_N; i++){
		if(is_black[i]){

			update(LEFT[i],Black,1); //LEFTのみに足す
		}else{

			update(LEFT[i],White,1);
		}
	}

	int node;

	for(int loop = 0; loop < num_Q; loop++){

		scanf("%d",&node);
		node--;

		range_update(LEFT[node],RIGHT[node],0,0,N-1);

		ll tmp = table[Black][0]-table[White][0];

		if(tmp > 0){

			printf("broccoli\n");

		}else{

			printf("cauliflower\n");
		}
	}

	return 0;
}
accuracy: 1
time_ms: 80
memory_kb: 22872
final_rank: 10

code_snippet: #include<bits/stdc++.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define HUGE_NUM 4000000000000000000 //オーバーフローに注意
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;


#define SIZE 100005

enum Type{
	Black,
	White,
};

int N,IND = 0;
ll table[2][6*SIZE];
int LEFT[SIZE],RIGHT[SIZE];
bool is_black[SIZE],is_rev[6*SIZE];
vector<int> G[SIZE];


void init(int first_N){
	N = 1;
	while(N < first_N)N *= 2;
}

void update(int loc,Type type,ll value){
	loc += N-1;

	table[type][loc] = value;

	if(N == 1)return;

	int parent = (loc-1)/2;

	while(true){
		table[type][parent] = table[type][2*parent+1]+table[type][2*parent+2];

		if(parent == 0)break;
		else{
			parent = (parent-1)/2;
		}
	}
}


void range_update(int search_left,int search_right,int node_id,int node_left,int node_right){

	//今回のノードが検索区間をカバーしていない場合
	if(search_right < node_left || search_left > node_right){

		return;
	}

	//今回のノードの区間が、検索区間の部分区間である場合
	if(search_left <= node_left && search_right >= node_right){
		is_rev[node_id] = not is_rev[node_id];

		//printf("node:%d 反転前 黒:%lld 白:%lld\n",node_id,table[Black][node_id],table[White][node_id]);
		swap(table[Black][node_id],table[White][node_id]);
		return;
	}

	if(is_rev[node_id]){ //反転区間の部分区間に、反転命令が下った場合

		//子を反転する
		range_update(node_left,node_right,2*node_id+1,node_left,(node_left+node_right)/2);
		range_update(node_left,node_right,2*node_id+2,(node_left+node_right)/2+1,node_right);
		is_rev[node_id] = false;
	}

	//今回のノードの区間に、一部検索区間と重なっている区間がある場合
	range_update(search_left,search_right,2*node_id+1,node_left,(node_left+node_right)/2);
	range_update(search_left,search_right,2*node_id+2,(node_left+node_right)/2+1,node_right);

	table[Black][node_id] = table[Black][2*node_id+1]+table[Black][2*node_id+2];
	table[White][node_id] = table[White][2*node_id+1]+table[White][2*node_id+2];

	/*printf("\nnode_id:%d\n",node_id);
	printf("黒 %lld 左:%lld 右:%lld\n",table[Black][node_id],table[Black][2*node_id+1],table[Black][2*node_id+2]);
	printf("白 %lld 左:%lld 右:%lld\n",table[White][node_id],table[White][2*node_id+1],table[White][2*node_id+2]);*/
}

void euler_tour(int node_id,int pre){

	LEFT[node_id] = IND++;

	for(int i = 0; i < G[node_id].size(); i++){

		int child = G[node_id][i];
		if(child == pre)continue;

		euler_tour(child,node_id);
	}

	RIGHT[node_id] = IND++;
}

int main(){

	int first_N,num_Q;
	scanf("%d %d",&first_N,&num_Q);

	int p;
	for(int i = 1; i <= first_N-1; i++){

		scanf("%d",&p);
		p--;

		G[p].push_back(i);
	}

	char buf[2];

	for(int i = 0; i < first_N; i++){

		scanf("%s",buf);

		is_black[i] = (buf[0]=='G');
	}

	euler_tour(0,-1);

	init(RIGHT[0]);

	//printf("N:%d\n",N);

	//0～N-2が上位構造のアドレス、N-1～2*N-2が最小要素のアドレス
	for(int i = 0; i <= 2*N-2; i++){

		is_rev[i] = false;
		table[Black][i] = 0;
		table[White][i] = 0;
	}

	for(int i = 0; i < first_N; i++){

		//printf("i:%d LEFT:%d RIGHT:%d\n",i,LEFT[i],RIGHT[i]);
		if(is_black[i]){

			update(LEFT[i],Black,1);
		}else{

			update(LEFT[i],White,1);
		}
	}

	int node;

	for(int loop = 0; loop < num_Q; loop++){

		scanf("%d",&node);
		node--;

		//printf("LEFT:%d RIGHT:%d\n",LEFT[node],RIGHT[node]);

		range_update(LEFT[node],RIGHT[node],0,0,N-1);

		ll tmp = table[Black][0]-table[White][0];

		//printf("黒:%lld 白:%lld\n",table[Black][0],table[White][0]);

		if(tmp > 0){

			printf("broccoli\n");

		}else{

			printf("cauliflower\n");
		}
	}

	return 0;
}
accuracy: 1
time_ms: 80
memory_kb: 22884
final_rank: 11

code_snippet: #ifdef LOCAL
#define _GLIBCXX_DEBUG
#endif

#include <bits/stdc++.h>

#include <algorithm>
#include <cassert>
#include <iostream>
#include <vector>


#ifdef _MSC_VER
#include <intrin.h>
#endif

namespace atcoder {

namespace internal {

int ceil_pow2(int n) {
    int x = 0;
    while ((1U << x) < (unsigned int)(n)) x++;
    return x;
}

int bsf(unsigned int n) {
#ifdef _MSC_VER
    unsigned long index;
    _BitScanForward(&index, n);
    return index;
#else
    return __builtin_ctz(n);
#endif
}

}  // namespace internal

}  // namespace atcoder


namespace atcoder {

template <class S,
          S (*op)(S, S),
          S (*e)(),
          class F,
          S (*mapping)(F, S),
          F (*composition)(F, F),
          F (*id)()>
struct lazy_segtree {
  public:
    lazy_segtree() : lazy_segtree(0) {}
    explicit lazy_segtree(int n) : lazy_segtree(std::vector<S>(n, e())) {}
    explicit lazy_segtree(const std::vector<S>& v) : _n(int(v.size())) {
        log = internal::ceil_pow2(_n);
        size = 1 << log;
        d = std::vector<S>(2 * size, e());
        lz = std::vector<F>(size, id());
        for (int i = 0; i < _n; i++) d[size + i] = v[i];
        for (int i = size - 1; i >= 1; i--) {
            update(i);
        }
    }

    void set(int p, S x) {
        assert(0 <= p && p < _n);
        p += size;
        for (int i = log; i >= 1; i--) push(p >> i);
        d[p] = x;
        for (int i = 1; i <= log; i++) update(p >> i);
    }

    S get(int p) {
        assert(0 <= p && p < _n);
        p += size;
        for (int i = log; i >= 1; i--) push(p >> i);
        return d[p];
    }

    S prod(int l, int r) {
        assert(0 <= l && l <= r && r <= _n);
        if (l == r) return e();

        l += size;
        r += size;

        for (int i = log; i >= 1; i--) {
            if (((l >> i) << i) != l) push(l >> i);
            if (((r >> i) << i) != r) push((r - 1) >> i);
        }

        S sml = e(), smr = e();
        while (l < r) {
            if (l & 1) sml = op(sml, d[l++]);
            if (r & 1) smr = op(d[--r], smr);
            l >>= 1;
            r >>= 1;
        }

        return op(sml, smr);
    }

    S all_prod() { return d[1]; }

    void apply(int p, F f) {
        assert(0 <= p && p < _n);
        p += size;
        for (int i = log; i >= 1; i--) push(p >> i);
        d[p] = mapping(f, d[p]);
        for (int i = 1; i <= log; i++) update(p >> i);
    }
    void apply(int l, int r, F f) {
        assert(0 <= l && l <= r && r <= _n);
        if (l == r) return;

        l += size;
        r += size;

        for (int i = log; i >= 1; i--) {
            if (((l >> i) << i) != l) push(l >> i);
            if (((r >> i) << i) != r) push((r - 1) >> i);
        }

        {
            int l2 = l, r2 = r;
            while (l < r) {
                if (l & 1) all_apply(l++, f);
                if (r & 1) all_apply(--r, f);
                l >>= 1;
                r >>= 1;
            }
            l = l2;
            r = r2;
        }

        for (int i = 1; i <= log; i++) {
            if (((l >> i) << i) != l) update(l >> i);
            if (((r >> i) << i) != r) update((r - 1) >> i);
        }
    }

    template <bool (*g)(S)> int max_right(int l) {
        return max_right(l, [](S x) { return g(x); });
    }
    template <class G> int max_right(int l, G g) {
        assert(0 <= l && l <= _n);
        assert(g(e()));
        if (l == _n) return _n;
        l += size;
        for (int i = log; i >= 1; i--) push(l >> i);
        S sm = e();
        do {
            while (l % 2 == 0) l >>= 1;
            if (!g(op(sm, d[l]))) {
                while (l < size) {
                    push(l);
                    l = (2 * l);
                    if (g(op(sm, d[l]))) {
                        sm = op(sm, d[l]);
                        l++;
                    }
                }
                return l - size;
            }
            sm = op(sm, d[l]);
            l++;
        } while ((l & -l) != l);
        return _n;
    }

    template <bool (*g)(S)> int min_left(int r) {
        return min_left(r, [](S x) { return g(x); });
    }
    template <class G> int min_left(int r, G g) {
        assert(0 <= r && r <= _n);
        assert(g(e()));
        if (r == 0) return 0;
        r += size;
        for (int i = log; i >= 1; i--) push((r - 1) >> i);
        S sm = e();
        do {
            r--;
            while (r > 1 && (r % 2)) r >>= 1;
            if (!g(op(d[r], sm))) {
                while (r < size) {
                    push(r);
                    r = (2 * r + 1);
                    if (g(op(d[r], sm))) {
                        sm = op(d[r], sm);
                        r--;
                    }
                }
                return r + 1 - size;
            }
            sm = op(d[r], sm);
        } while ((r & -r) != r);
        return 0;
    }

  private:
    int _n, size, log;
    std::vector<S> d;
    std::vector<F> lz;

    void update(int k) { d[k] = op(d[2 * k], d[2 * k + 1]); }
    void all_apply(int k, F f) {
        d[k] = mapping(f, d[k]);
        if (k < size) lz[k] = composition(f, lz[k]);
    }
    void push(int k) {
        all_apply(2 * k, lz[k]);
        all_apply(2 * k + 1, lz[k]);
        lz[k] = id();
    }
};

}  // namespace atcoder

using namespace std;
#if __has_include(<atcoder/all>)
using namespace atcoder;
#endif

template<class T> 
struct matrix{
  std::valarray <T> value;
  size_t  N;
  matrix(size_t size,T init):value(init,size*size),N(size){}
  matrix(size_t size):value(size*size),N(size){}
  matrix(matrix *M):value(M->value),N(M->N){}
  matrix(valarray<T> v,size_t  size):value(v),N(size){}

public:
  matrix& operator = (const matrix &B){
    this->value = std::valarray<T>(B.value);
    return *this;
  }
  /*const std::valarray<T>& operator [](const size_t i)const{

    return *std::valarray<T>(value[std::slice(N*i,N,1)]);
  }
  std::valarray<T>& operator [](const size_t i){
    //書き込み用
    return *(value[std::slice(N*i,N,1)]);
  }*/
  const matrix operator + (const matrix &B)const{
    return matrix(value+B.value,N);
  }
  const matrix operator - (const matrix &B)const{
    return matrix(value-B.value,N);
  }
  const matrix operator * (const matrix &B)const{
    std::valarray<T> ret(N*N);
    for(size_t i=0;i<N;i++){
      for (size_t j=0;j<N;j++){
        ret[N*i+j]=(T)(value[std::slice(N*i,N,1)]*(B.value[std::slice(j,N,N)])).sum();
      }
    }
    return matrix(ret,N);
  }

  matrix& operator += (const matrix &B){
    value+=B.value;
    return *this;
  }
  matrix& operator -= (const matrix &B){
    value-=B.value;
    return *this;
  }
  matrix& operator *= (const matrix &B){
    *this=(*this)*B;
    return *this;
  }


  matrix& operator = (const T &v){
    std::valarray<T> ret(N*N);
    for(size_t i=0;i<N*N;i+=N+1)ret[i]=v;
    value=ret;
    return *this;
  }
  const matrix operator + (const T &v)const{
    std::valarray<T> delta(N*N);
    for(size_t i=0;i<N*N;i+=N+1)delta[i]=v;
    return matrix(value+delta,N);
  }
  const matrix operator - (const T &v)const{
    std::valarray<T> delta(N*N);
    for(size_t i=0;i<N*N;i+=N+1)delta[i]=v;
    return matrix(value-delta,N);
  }
  const matrix operator * (const T &v)const{
    return matrix(value*v,N);
  }
  const matrix operator / (const T &v)const{
    return matrix(value/v,N);
  }
  const matrix operator ^ (long long n)const{
    assert(n>=0);
    matrix<T> a(N), ret(N);ret =(T)1;a.value=this->value;
    while(n) {
      if(n & 1) ret *= a;
      a *= a;
      n >>= 1;
    }
    return matrix(ret.value,N);}
  matrix& operator ^= (long long  n){
    *(this)=*(this)^n;
    return *this;
  }
  const matrix Transpose ()const{
    std::valarray<T> ret(N*N);
    for(size_t i=0;i<N;i++)
      for(size_t j=0;j<N;j++)
        ret[N*i+j]=value[j*N+i];
    return matrix(ret,N);
  }

};


#pragma region Macros

// rep macro
#define overload4(_1, _2, _3, _4, name, ...) name
#define overload3(_1, _2, _3, name, ...) name
#define rep1(i, n) for (ll i = 0; i < n; ++i)
#define rep2(i, a, b) for (ll i = a; i < b; ++i)
#define rep3(i, a, b, c) for (ll i = a, _bb = b; (a <= i && i < _bb) or (a >= i && i > _bb); i += c)
#define rep(...) overload4(__VA_ARGS__, rep3, rep2, rep1)(__VA_ARGS__)
#define each1(i, a) for (auto &&i : a)
#define each2(x, y, a) for (auto &&[x, y] : a)
#define each3(x, y, z, a) for (auto &&[x, y, z] : a)
#define each(...) overload4(__VA_ARGS__, each3, each2, each1)(__VA_ARGS__)
#define extrep(v,...) for(auto v:__MAKE_MAT__({__VA_ARGS__}))
vector<vector<long long>> __MAKE_MAT__(vector<long long> v){
  if(v.empty())return vector<vector<long long>>(1,vector<long long>());
  long long n=v.back();
  v.pop_back();
  vector<vector<long long>> ret;
  vector<vector<long long>> tmp=__MAKE_MAT__(v);
  for(auto e:tmp)for(long long i=0;i<n;++i){
    ret.push_back(e);
    ret.back().push_back(i);
  }
  return ret;
} //extrep(v,3,4,5)->v=[0,3)x[0,4)x[0,5)
#define vep(i,v) for(auto (i)=std::begin(v);std::distance(std::begin(i),(std::end(v)))>0;++(i))

// name macro
#define all(v) std::begin(v), std::end(v)
#define rall(v) std::rbegin(v), std::rend(v)
template <class T = int> using V = std::vector<T>;
template <class T = int> using VV = std::vector<std::vector<T>>;
template <class T> using pqup = std::priority_queue<T, std::vector<T>, std::greater<T>>;
using ld = long double;
using int128 = __int128_t;
using pii = std::pair<int, int>;
using pll = std::pair<long long, long long>;
using ll = long long ;
using Int = long long;
#define eb emplace_back
#define pb push_back

//py macro
#define elif else if
#define Sum(...) accumulate(all(__VA_ARGS__), 0LL)
template <class T>int bisect_left(const std::vector<T> &a, const T x) { return std::distance(std::begin(a), std::lower_bound(std::begin(a), std::end(a), (x))); }
template <class T>int bl(const std::vector<T> &a, const T x) { return std::distance(std::begin(a), std::lower_bound(std::begin(a), std::end(a), (x))); }
template <class T>int bisect_right(const std::vector<T> &a, const T x) { return std::distance(std::begin(a), std::upper_bound(std::begin(a), std::end(a), (x))); }
template <class T>int br(const std::vector<T> &a, const T x) { return std::distance(std::begin(a), std::upper_bound(std::begin(a), std::end(a), (x))); }
#define Sort(x) sort(std::begin(x), std::end(x))
#define Reverse(x) reverse(std::begin(x), std::end(x))
#define len(x) (ll) x.size()
#define popcnt(x) __builtin_popcountll(x)


// input macro
template <class T, class U>std::istream &operator>>(std::istream &is, std::pair<T, U> &p) {
  is >> p.first >> p.second;
  return is;
}
template <class T>std::istream &operator>>(std::istream &is, std::vector<T> &v) {
  for(T &i : v) is >> i;
  return is;
}
template <class T>std::istream &operator>>(std::istream &is, std::valarray<T> &v) {
  for(T &i : v) is >> i;
  return is;
}
template <class T>std::istream &operator>>(std::istream &is, matrix<T> &v) {
  for(T &i : v.value) is >> i;
  return is;
}
std::istream &operator>>(std::istream &is, __int128_t &a) {
  std::string s;
  is >> s;
  __int128_t ret = 0;
  for(int i = 0; i < s.length(); i++)
    if('0' <= s[i] and s[i] <= '9')
      ret = 10 * ret + s[i] - '0';
  a = ret * (s[0] == '-' ? -1 : 1);
  return is;
}
#if __has_include(<atcoder/all>)
std::istream &operator>>(std::istream &is, atcoder::modint998244353 &a) {
  long long v;
  is >> v;
  a = v;
  return is;
}
std::istream &operator>>(std::istream &is, atcoder::modint1000000007 &a) {
  long long v;
  is >> v;
  a = v;
  return is;
}
template <int m>std::istream &operator>>(std::istream &is, atcoder::static_modint<m> &a) {
  long long v;
  is >> v;
  a = v;
  return is;
}
template <int m>std::istream &operator>>(std::istream &is, atcoder::dynamic_modint<m> &a) {
  long long v;
  is >> v;
  a = v;
  return is;
}
#endif
namespace scanner {
  void scan(int &a) { std::cin >> a; }
  void scan(long long &a) { std::cin >> a; }
  void scan(std::string &a) { std::cin >> a; }
  void scan(char &a) { std::cin >> a; }
  void scan(char a[]) { std::scanf("%s", a); }
  void scan(double &a) { std::cin >> a; }
  void scan(long double &a) { std::cin >> a; }
  template <class T, class U>void scan(std::pair<T, U> &p) { std::cin >> p; }
  template <class T> void scan(std::vector<T> &a) { std::cin >> a; }
  template <class T> void scan(std::valarray<T> &a) { std::cin >> a; }
  template <class T> void scan(matrix<T> &a) { std::cin >> a; }
  void INPUT() {}
  template <class Head, class... Tail>
  void INPUT(Head &head, Tail &... tail) {scan(head);INPUT(tail...);}
}  // namespace scanner
#define VEC(type, name, size)	 \
  std::vector<type> name(size); \
  scanner::INPUT(name)
#define VAL(type, name, size)	 \
  std::valarray<type> name(size); \
  scanner::INPUT(name)
#define VVEC(type, name, h, w)									\
  std::vector<std::vector<type>> name(h, std::vector<type>(w)); \
  scanner::INPUT(name)
#define MAT(type, name, n)									\
  matrix<type> name(n); \
  scanner::INPUT(name)
#define INT(...)	 \
  int __VA_ARGS__; \
  scanner::INPUT(__VA_ARGS__)
#define LL(...)			\
  long long __VA_ARGS__; \
  scanner::INPUT(__VA_ARGS__)
#define STR(...)			 \
  std::string __VA_ARGS__; \
  scanner::INPUT(__VA_ARGS__)
#define CHAR(...)	 \
  char __VA_ARGS__; \
  scanner::INPUT(__VA_ARGS__)
#define DOUBLE(...)	 \
  double __VA_ARGS__; \
  scanner::INPUT(__VA_ARGS__)
#define LD(...)			  \
  long double __VA_ARGS__; \
  scanner::INPUT(__VA_ARGS__)

struct input {
  input(){};
  template <class T> operator T() {
    T t;cin >> t;
    return t;}
    };

// output-macro

template <class T, class U> std::ostream &operator<<(std::ostream &os, const std::pair<T, U> &p) {
  os << p.first << " " << p.second;
  return os;
}
template <class T> std::ostream &operator<<(std::ostream &os, const std::vector<T> &a) {
  for(int i = 0; i < int(a.size()); ++i) {
    if(i) os << " ";
    os << a[i];
  }
  return os;
}
template <class T> std::ostream &operator<<(std::ostream &os, const std::valarray<T> &a) {
  for(int i = 0; i < int(a.size()); ++i) {
    if(i) os << " ";
    os << a[i];
  }
  return os;
}
std::ostream &operator<<(std::ostream &dest, __int128_t &value) {
  std::ostream::sentry s(dest);
  if(s) {
    __uint128_t tmp = value < 0 ? -value : value;
    char buffer[128];
    char *d = std::end(buffer);
    do {
      --d;
      *d = "0123456789"[tmp % 10];
      tmp /= 10;
    } while(tmp != 0);
    if(value < 0) {
      --d;
      *d = '-';
    }
    int len = std::end(buffer) - d;
    if(dest.rdbuf()->sputn(d, len) != len) {
      dest.setstate(std::ios_base::badbit);
    }
  }
  return dest;
}
#if __has_include(<atcoder/all>)
std::ostream &operator<<(std::ostream &os, const atcoder::modint998244353 &a) { return os << a.val(); }
std::ostream &operator<<(std::ostream &os, const atcoder::modint1000000007 &a) { return os << a.val(); }
template <int m>
std::ostream &operator<<(std::ostream &os, const atcoder::static_modint<m> &a) { return os << a.val(); }
template <int m>
std::ostream &operator<<(std::ostream &os, const atcoder::dynamic_modint<m> &a) { return os << a.val(); }
#endif

template <class T> void print(const T a) { std::cout << a << '\n'; }
template <class Head, class... Tail> void print(Head H, Tail... T) {std::cout << H << ' ';print(T...);}
template <class T> void printel(const T a) { std::cout << a << '\n'; }
template <class T>void printel(const std::vector<T> &a) {for(const auto &v : a)std::cout << v << '\n';}
template <class Head, class... Tail>void printel(Head H, Tail... T) {std::cout << H << '\n';	printel(T...);}
inline void Yes(const bool b = true) { std::cout << (b ? "Yes\n" : "No\n"); }
inline void No() { std::cout << "No\n"; }
inline void YES(const bool b = true) { std::cout << (b ? "YES\n" : "NO\n"); }
inline void NO() { std::cout << "NO\n"; }
inline void err(const bool b = true) {if(b) std::cout << "-1\n", exit(0);}
inline void First(const bool b = true){std::cout << (b ? "First\n" : "Second\n"); }
inline void first(const bool b = true){std::cout << (b ? "first\n" : "second\n"); }
template<class T> inline void Case(const long long &number,T ans){printf("Case #%d: ",number);cout<<ans<<"\n";}


//debug macro
namespace debugger {
template <class T>
void view(const std::vector<T> &a) {
  std::cerr << "{ ";
  for(const auto &v : a) {
    std::cerr << v << ", ";
  }
  std::cerr << "\b\b }";
}
template <class T>
void view(const std::valarray<T> &a) {
  std::cerr << "{ ";
  for(const auto &v : a) {
    std::cerr << v << ", ";
  }
  std::cerr << "\b\b }";
}
template <class T>
void view(const std::vector<std::vector<T>> &a) {
  std::cerr << "{\n";
  for(const auto &v : a) {
    std::cerr << "\t";
    view(v);
    std::cerr << "\n";
  }
  std::cerr << "}";
}
template<class T>
void view( const matrix<T> &a){
  std::cerr << "{\n";
  for(int i=0;i<a.N;i++){
    std::cerr << "\t";
    valarray<T> inner= a.value[std::slice(i*a.N,a.N,1)];
    view(inner);
    std::cerr << "\n";
  }
  std::cerr << "}";
}
template <class T, class U>
void view(const std::vector<std::pair<T, U>> &a) {
  std::cerr << "{\n";
  for(const auto &p : a) std::cerr << "\t(" << p.first << ", " << p.second << ")\n";
  std::cerr << "}";
}
template <class T, class U>
void view(const std::map<T, U> &m) {
  std::cerr << "{\n";
  for(const auto &p : m) std::cerr << "\t[" << p.first << "] : " << p.second << "\n";
  std::cerr << "}";
}
template <class T, class U>
void view(const std::pair<T, U> &p) { std::cerr << "(" << p.first << ", " << p.second << ")"; }
template <class T>
void view(const std::set<T> &s) {
  std::cerr << "{ ";
  for(auto &v : s) {
    view(v);
    std::cerr << ", ";
  }
  std::cerr << "\b\b }";
}

template <class T>
void view(const T &e) { std::cerr << e; }
}  // namespace debugger
#ifdef LOCAL
void debug_out() {}
template <typename Head, typename... Tail>
void debug_out(Head H, Tail... T) {
  debugger::view(H);
  std::cerr << ", ";
  debug_out(T...);
}
#define debug(...)												\
  do {														  \
    std::cerr << __LINE__ << " [" << #__VA_ARGS__ << "] : ["; \
    debug_out(__VA_ARGS__);								   \
    std::cerr << "\b\b]\n";								   \
  } while(false)
#else
#define debug(...) (void(0))
#endif

// vector macro

template <class T> void uniq(std::vector<T> &a) {
  std::sort(std::begin(a), std::end(a));
  a.erase(std::unique(std::begin(a), std::end(a)), std::end(a));
}
template <class T> std::vector<T> press(std::vector<T> &a) {
  auto res = a;
  UNIQUE(res);
  for(auto &v : a)
    v = lb(res, v);
  return res;
}
#define SORTname(a, b, c, ...) c
#define SORT(...) SORTname(__VA_ARGS__, SORT1, SORT0, ...)(__VA_ARGS__)
#define SORT0(a) std::sort(std::begin(a), std::end(a))
#define SORT1(a, c) std::sort(std::begin(a), std::end(a), [](const auto x, const auto y) { return x c y; })

// math macro
template<class T> inline T GCD(T a, T b) { return b?GCD(b,a%b):a;}
template<class T> inline T LCM(T a, T b) { return a/GCD(a,b)*b;}
template<class T> inline T modinv(T a, T M) { return (1-M*modinv(M%a,a))/a+M;}
template <class T, class U> inline bool chmin(T &a, const U &b) { return a > b ? a = b, true : false; }
template <class T, class U> inline bool chmax(T &a, const U &b) { return a < b ? a = b, true : false; }
template <class T> inline T ceildiv(T x, T y) { return (x + y - 1) / y; }

template <class T> T POW(T a, long long n) {
  T ret =1;
  while(n) {
    if(n & 1) ret *= a;
    a *= a;
    n >>= 1;
  }
  return ret;}

// modpow
long long POW(long long a, long long n, const int mod) {
  long long ret = 1;
  while(n) {
    if(n & 1) (ret *= a) %= mod;
    (a *= a) %= mod;
    n >>= 1;
  }
  return ret;
}
// find integer x s.t. x^2<=n<(x+1)^2 
template<class T>T isqrt(T n){
  if(n==0)return 0;
  if(n<0)return -1;
  unsigned long long int  m=n;
  m|=m>>1;m|=m>>2;m|=m>>4;m|=m>>8;m|=m>>16;
  T x=1<<((__builtin_popcount(m)+1)/2);
  T y=(x+n/x)/2;
  while (y<x){
    x=y;y=(x+n/x)/2;
  }
  return x;}
//部分集合の列挙
std::vector<unsigned int> subset(unsigned int S){
  unsigned int cnt=__builtin_popcount(S);
  std::vector<unsigned int> ret(1<<cnt,0);
  int head=(1<<cnt)-1;
  for(unsigned int T=S;T!=0;T=S&(T-1),head--){
    ret[head]=T;
  }
  return ret;
}

//N桁の二進数のうち丁度Kbitだけ立っている数の列挙
std::vector<unsigned long long > bits(long long N,long long K){
  unsigned long long v=(1<<K)-1,MAX=1<<N;
  std::vector<unsigned long long> ret(0);
  unsigned long long x,y;
  while(v<MAX){
    ret.emplace_back(v);
    x = v & (-v) ;
    y = v + x ;
    v = (v & ~y) / x >> 1 | y;
  }
  return ret;
}
int bit_length(unsigned long long x){
  x|=x>>1;x|=x>>2;x|=x>>4;x|=x>>8;x|=x>>16;x|=x>>32;
  return __builtin_popcountll(x);
}
// others
struct fast_io {
  fast_io() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    cout << fixed << setprecision(15);
  }
} fast_io_;

inline std::vector<std::pair<long long,long long>> NEXT(long long x,long long y){return {{x-1,y},{x,y-1},{x,y+1},{x+1,y}};}
inline std::vector<std::pair<long long,long long>> NEXT8(long long x,long long y){return {{x-1,y-1},{x-1,y},{x-1,y+1},{x,y-1},{x,y+1},{x+1,y-1},{x+1,y},{x+1,y+1}};}

constexpr const int inf = 1e9;
constexpr const long long linf = 10e17;
//int |x|<=2*10**9	 long |x|<= 9*10**18
//constexpr const long long mod2 = 998244353;
//constexpr const long long mod = 1000000007;
//using mint = modint1000000007;

int head=0;
const int MAXN=100100;
vector<int> edges[MAXN];
int lefts[MAXN],rights[MAXN];
void dfs(int now=0){
  lefts[now]=head++;
  for (auto to:edges[now])dfs(to);
  rights[now]=head;
}
int op(int a,int b){
  return a+b;
}
int e(){return 0;}
int mapping(int f,int x){return f*x;}
int compo(int f,int g){return f*g;}
int id(){return 1;}
int main(){
  fast_io();
  INT(N,Q);
  VEC(int,par,N-1);
  for (auto &p:par)p--;
  V<int> Label(N);
  rep(i,N){
    char c;cin>>c;
    if (c=='G')Label[i]=1;
    else Label[i]=-1;

  }
  rep(i,N-1){
    edges[par[i]].pb(i+1);
  }
  dfs();
  V<int> label(N);
  rep(i,N){label[lefts[i]]=Label[i];}
  atcoder::lazy_segtree<int,op,e,int,mapping,compo,id> seg(label);
  rep(_,Q){
    INT(v);
    v--;
    seg.apply(lefts[v],rights[v],-1);
    if(seg.all_prod()>0 )print("broccoli");
    else print("cauliflower");
  }
}
accuracy: 1
time_ms: 40
memory_kb: 15120
final_rank: 3

code_snippet: #include <iostream>
#include <algorithm>
#include <utility>
#include <string>
#include <vector>
#include <set>
#include <stack>
#include <queue>
#include <map>
#include <math.h>
#include <string.h>
#include <iomanip>
#include <numeric>
#include <cstdlib>
#include <cstdint>
#include <cmath>
#include <functional>
#include <limits>
#include <cassert>
#include <bitset>
#include <chrono>
#include <random>
#include <memory>
 
/* macro */
 
#define rep(i, a, n) for (int i = (int)(a); i < (int)(n); i++)
#define rrep(i, a, n) for (int i = ((int)(n-1)); i >= (int)(a); i--)
#define Rep(i, a, n) for (i64 i = (i64)(a); i< (i64)(n); i++)
#define RRep(i, a, n) for (i64 i = ((i64)(n-i64(1))); i>=(i64)(a); i--)
#define all(v) (v).begin(),(v).end()
#define rall(v) (v).rbegin(),(v).rend()
 
/* macro end */
 
/* template */
 
namespace ebi {
 
#ifdef LOCAL
#define debug(...)                                                    \
    std::cerr << "LINE: " << __LINE__ << "  [" << #__VA_ARGS__ << "]:", \
        debug_out(__VA_ARGS__)
#else
#define debug(...)
#endif
 
void debug_out() { std::cerr << std::endl; }
 
template <typename Head, typename... Tail>
void debug_out(Head h, Tail... t) {
    std::cerr << " " << h;
    if (sizeof...(t) > 0) std::cout << " :";
    debug_out(t...);
}
 
template <typename T1, typename T2>
std::ostream& operator<<(std::ostream& os, std::pair<T1, T2> pa) {
    return os << pa.first << " " << pa.second;
}
 
template <typename T>
std::ostream& operator<<(std::ostream& os, std::vector<T> vec) {
    for (std::size_t i = 0; i < vec.size(); i++) os << vec[i] << (i + 1 == vec.size() ? "" : " ");
    return os;
}
 
using size_t = std::size_t;
using i64 = long long;
using u64 = unsigned long long;
 
template<class T> void fill(std::vector<T> &v) { for(T &e: v) std::cin >> e; }
 
template<class T>
struct Edge {
    int to;
    T cost;
    Edge(int to, T cost) : to(to), cost(cost) { }
};
 
template<class T>
using Graph = std::vector<std::vector<Edge<T>>>;
 
using graph = std::vector<std::vector<int>>;
 
template <class T>
inline bool chmin(T &a, T b) {
    if (a > b){
        a = b;
        return true;
    }
    return false;
}
 
template <class T>
inline bool chmax(T &a, T b) {
    if (a < b){
        a = b;
        return true;
    }
    return false;
}
 
template <class T>
T gcd(T a, T b){
    if( b==0 ) return a;
    else return gcd(b, a%b);
}
 
template <class T>
T lcm(T a, T b) {
    return (a*b)/gcd(a,b);
}
 
template<class T>
T Pow(T x, i64 n) {
    T res = 1;
    while(n>0){
        if(n&1) res = res *x;
        x = x*x;
        n>>=1;
    }
    return res;
}
 
template<class T>
T scan() {
    T val;
    std::cin >> val;
    return val;
}
 
constexpr i64 LNF = std::numeric_limits<i64>::max()/4;
 
constexpr int INF = std::numeric_limits<int>::max()/4;
 
const long double PI = acos(-1);
 
const std::vector<int> dy = {1,0,-1,0,1,1,-1,-1};
const std::vector<int> dx = {0,1,0,-1,1,-1,1,-1};
 
}
 
/* template end */

/*
    author: noshi91
    reference: https://noshi91.hatenablog.com/entry/2019/03/31/174006
    noshi91のブログで公開されているmodintを元にinv(), pow()を追加したものです
*/

#include <cstdint>
#include <iostream>

namespace ebi {

template<std::uint_fast64_t Modulus>
class modint {
  using u64 = std::uint_fast64_t;

public:
    u64 a;

    constexpr modint(const u64 x = 0) noexcept : a(x % Modulus) {}
    constexpr u64 &value() noexcept { return a; }
    constexpr u64 &val() noexcept { return a; }
    constexpr const u64 &value() const noexcept { return a; }
    constexpr modint operator+(const modint rhs) const noexcept {
        return modint(*this) += rhs;
    }
    constexpr modint operator-(const modint rhs) const noexcept {
        return modint(*this) -= rhs;
    }
    constexpr modint operator*(const modint rhs) const noexcept {
        return modint(*this) *= rhs;
    }
    constexpr modint operator/(const modint rhs) const noexcept {
        return modint(*this) /= rhs;
    }
    constexpr modint &operator+=(const modint rhs) noexcept {
        a += rhs.a;
        if (a >= Modulus) {
            a -= Modulus;
        }
        return *this;
    }
    constexpr modint &operator-=(const modint rhs) noexcept {
        if (a < rhs.a) {
        a += Modulus;
        }
        a -= rhs.a;
        return *this;
    }
    constexpr modint &operator*=(const modint rhs) noexcept {
        a = a * rhs.a % Modulus;
        return *this;
    }
    constexpr modint &operator/=(modint rhs) noexcept {
        u64 exp = Modulus - 2;
        while (exp) {
        if (exp % 2) {
            *this *= rhs;
        }
        rhs *= rhs;
        exp /= 2;
        }
        return *this;
    }
    constexpr modint operator-() const { return modint() - *this; }
    bool operator==(const u64 rhs) {
        return a == rhs;
    }
    bool operator!=(const u64 rhs) {
        return a != rhs;
    }
    constexpr modint& operator++() {
        a++;
        if( a == mod() ) a = 0;
        return *this;
    }
    constexpr modint& operator--() {
        if( a == 0 ) a = mod();
        a--;
        return *this;
    }

    modint pow(u64 n) const noexcept {
        modint res = 1;
        modint x = a;
        while(n>0){
            if(n&1) res *= x;
            x *= x;
            n >>=1;
        }
        return res;
    }
    modint inv() const {
        return pow(Modulus-2);
    }

    static u64 mod() {
        return Modulus;
    }
};

using modint998244353 = modint<998244353>;
using modint1000000007 = modint<1000000007>;

template<std::uint_fast64_t Modulus>
std::ostream& operator<<(std::ostream& os, modint<Modulus> a){
    return os << a.val();
}

} // namespace ebi


#line 2 "data_structure/heavy_light_decomposition.hpp"

#line 2 "data_structure/Segtree.hpp"

#include <vector>

namespace ebi {

template<class Monoid, Monoid (*op)(Monoid, Monoid), Monoid (*e)()>
struct Segtree {
private:
    std::vector<Monoid> data;
    int n;
public:
    Segtree(int _n) : n(1) {
        while(n<_n){
            n <<= 1;
        }
        data.assign(2*n-1, e());
    }

    Segtree(std::vector<Monoid> v) : n(1) {
        int _n = v.size();
        while(n<_n){
            n <<= 1;
        }
        data.assign(2*n-1, e());
        for(int i = 0; i<_n; i++){
            data[n+i-1] = v[i];
        }
        for(int i = n-2; i>=0; i--){
            data[i] = op(data[2*i+1], data[2*i+2]);
        }
    }

    void set(int p, Monoid x){
        int k = n+p-1;
        data[k] = x;
        while(k>0){
            k = (k-1)/2;
            data[k] = op(data[2*k+1], data[2*k+2]);
        }
    }

    Monoid prod(int tl, int tr, int l=0, int r=-1, int index=0){
        if(r<0) r = n;
        if(tr<=l || r<=tl){
            return e();
        }
        if(tl<=l && r<=tr){
            return data[index];
        }
        return op(prod(tl, tr, l, (l+r)/2, 2*index+1), prod(tl, tr, (l+r)/2, r, 2*index+2));
    }

    Monoid all_prod() { return data[0]; }

    Monoid get(int p) { return data[n+p-1]; }

    Monoid operator [] (int p) { return data[n+p-1]; }
};

} // namespace ebi

/*
    reference: https://beet-aizu.hatenablog.com/entry/2017/12/01/225955
               https://atcoder.github.io/ac-library/master/document_ja/lazysegtree.html
*/

#include <vector>
#include <cassert>

namespace ebi {

template<
    class S,
    S (*op)(S, S),
    S (*e)(),
    class F,
    S (*mapping)(F, S),
    F (*merge)(F, F),
    F (*id)()>
struct LazySegtree {
private:
    std::vector<S> data;
    std::vector<F> lazy;
    int n;

    void eval(int index, int l, int r) {
        data[index] = mapping(lazy[index], data[index]);
        if(r-l>1) {
            lazy[2*index+1] = merge(lazy[index] ,lazy[2*index+1]);
            lazy[2*index+2] = merge(lazy[index] ,lazy[2*index+2]);
        }
        lazy[index] = id();
    }

    S _prod(int l, int r, int nl = 0, int nr = -1, int index = 0) {
        if(nr < 0) nr = n;
        if(nr<=l || r<=nl) {
            return e();
        }
        eval(index, nl, nr);
        if(l<=nl && nr<=r) {
            return data[index];
        }
        return op(_prod(l, r, nl, (nl+nr)/2, 2*index+1), _prod(l, r, (nl+nr)/2, nr, 2*index+2));
    }

    void _apply(int l, int r, F f, int nl = 0, int nr = -1, int index = 0) {
        if(nr<0) nr = n;
        eval(index, nl, nr);
        if(nr<=l || r<=nl) return;
        if(l<=nl && nr<=r) {
            lazy[index] = merge(f, lazy[index]);
            eval(index, nl, nr);
            return;
        }
        _apply(l, r, f, nl, (nl+nr)/2, 2*index+1);
        _apply(l, r, f, (nl+nr)/2, nr, 2*index+2);
        data[index] = op(data[2*index+1], data[2*index+2]);
        return;
    }

public:
    LazySegtree(int _n) : n(1) {
        while(n<_n) {
            n <<= 1;
        }
        data.assign(2*n-1, e());
        lazy.assign(2*n-1, id());
    }

    LazySegtree(std::vector<S> v) : n(1) {
        int _n = v.size();
        while(n<_n) {
            n <<= 1;
        }
        data.assign(2*n-1, e());
        lazy.assign(2*n-1, id());
        for(int i = 0; i<_n; i++) {
            data[i+n-1] = v[i];
        }
        for(int i = n-2; i>=0; i--) {
            data[i] = op(data[2*i+1], data[2*i+2]);
        }
    }

    S prod(int l, int r) {
        return _prod(l, r);
    }

    S all_prod() {
        eval(0,0,n);
        return data[0];
    }

    void apply(int l, int r, F f) {
        _apply(l, r, f);
    }

    S get(int i) {
        int l = 0, r = n;
        int k = 0;
        while(r-l>1) {
            eval(k, l, r);
            int mid = (l+r)/2;
            if(i<mid) {
                k = 2*k+1;
                r = mid;
            }
            else {
                k = 2*k+2;
                l = mid;
            }
        }
        eval(k, l, r);
        return data[k];
    }
};

} // namespace ebi

namespace ebi {

using mint = modint998244353;

using ld = long double;

struct S{
    long long value;
    int size;
};
using F = long long;

const F ID = 1e18;

S op(S a, S b) {
    return {a.value + b.value, a.size + b.size};
}

S e() {
    return {0, 0};
}

S mapping(F f, S x) {
    if(f != ID) {
        x.value = x.size - x.value;
    }
    return x;
}

F merge(F f, F g) {
    if(f == ID && g == ID) return f;
    else if(f != ID && g != ID) return ID;
    else return 1;
}

F id() { return ID; }

void main_() {
    int n,q;
    std::cin >> n >> q;
    graph g(n);
    std::vector<int> c(n);
    rep(i,1,n) {
        int p;
        std::cin >> p;
        p--;
        g[i].emplace_back(p);
        g[p].emplace_back(i);
    }
    rep(i,0,n) {
        char x;
        std::cin >> x;
        if(x == 'G') c[i] = 1;
    }
    std::vector<int> in(n);
    std::vector<int> out(n);
    LazySegtree<S, op, e, F, mapping, merge, id> seg(std::vector<S>(n, {0, 1}));
    int time = 0;
    auto dfs = [&](auto dfs, int v, int par = -1) -> void {
        in[v] = time;
        if(c[v] > 0) seg.apply(time, time+1, 1);
        for(auto nv: g[v]) {
            if(nv == par) continue;
            time++;
            dfs(dfs, nv, v);
        }
        out[v] = time+1;
    };
    dfs(dfs, 0);
    while(q--) {
        int v;
        std::cin >> v;
        v--;
        seg.apply(in[v], out[v], 1);
        int ans = seg.prod(0, n).value;
        if((n+1)/2 <= ans) {
            std::cout << "broccoli\n";
        }
        else {
            std::cout << "cauliflower\n";
        }
    }
}
 
}

 
int main() {
    std::cout << std::fixed << std::setprecision(15);
    std::cin.tie(nullptr);
    std::ios::sync_with_stdio(false);
    int t = 1;
    while(t--) {
        ebi::main_();
    }
    return 0;
}
accuracy: 1
time_ms: 100
memory_kb: 36124
final_rank: 19

code_snippet: #line 1 "solve/main.cpp"
#include <algorithm>
#include <array>
#include <bitset>
#include <cassert>
#include <cctype>
#include <chrono>
#include <cmath>
#include <complex>
#include <cstdint>
#include <cstdlib>
#include <deque>
#include <functional>
#include <iomanip>
#include <iostream>
#include <limits>
#include <list>
#include <map>
#include <memory>
#include <numeric>
#include <queue>
#include <random>
#include <set>
#include <stack>
#include <string>
#include <type_traits>
#include <unordered_map>
#include <utility>
#include <vector>

/* template start */

#line 2 "lib/utility/type_alias.hpp"

#line 4 "lib/utility/type_alias.hpp"

using u64 = std::uint64_t;
using u32 = std::uint32_t;
using u16 = std::uint16_t;
using u8 = std::uint8_t;

using i64 = std::int64_t;
using i32 = std::int32_t;
using i16 = std::int16_t;
using i8 = std::int8_t;

using usize = std::size_t;
using isize = std::ptrdiff_t;

constexpr i64 operator"" _i64(unsigned long long num) { return i64(num); }

constexpr u64 operator"" _u64(unsigned long long num) { return u64(num); }
#line 33 "solve/main.cpp"

#define rep(i, a, b) for (i64 i = (a); (i) < (b); (i)++)
#define all(i) i.begin(), i.end()

#ifdef LOCAL
#define debug(...)                                                    \
  std::cerr << "LINE: " << __LINE__ << "  [" << #__VA_ARGS__ << "]:", \
      debug_out(__VA_ARGS__)
#else
#define debug(...)
#endif

void debug_out() { std::cerr << std::endl; }

template <typename Head, typename... Tail>
void debug_out(Head h, Tail... t) {
  std::cerr << " " << h;
  if (sizeof...(t) > 0) std::cerr << " :";
  debug_out(t...);
}

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

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

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 Num, typename Func = std::multiplies<Num>>
constexpr Num mypow(Num a, u64 b, Num id = 1, Func mul = Func()) {
  if (b == 0) return id;
  Num x = id;
  while (b > 0) {
    if (b & 1) x = mul(x, a);
    a = mul(a, a);
    b >>= 1;
  }
  return x;
}

/* template end */

#line 2 "lib/SegmentTree/LazySegmentTree.hpp"

#line 5 "lib/SegmentTree/LazySegmentTree.hpp"

// Lazy
// type value_t
// type lazy_t
// static value_t id_val
// static value_t id_lazy
// static (value_t,value_t) -> value_t f
// static (value_t,lazy_t) -> value_t g
// static (lazy_t,lazy_t) -> lazy_t h
// static (lazy_t,size_t) -> lazy_t p

/* Lazy template

struct Lazy{
  using value_t= ~~ ;
  using lazy_t= ~~ ;
  static constexpr value_t id_val= ~~ ;
  static constexpr lazy_t id_lazy= ~~ ;
  static value_t f(value_t a,value_t b){
    return ~~ ;
  }
  static value_t g(value_t a,lazy_t b){
    return ~~ ;
  }
  static lazy_t h(lazy_t a,lazy_t b){
    return ~~ ;
  }
  static lazy_t p(lazy_t a,std::size_t n){
    return ~~ ;
  }
};

*/

template <typename Lazy>
class LazySegmentTree {
 public:
  using value_t = typename Lazy::value_t;
  using lazy_t = typename Lazy::lazy_t;
  using size_t = std::size_t;

 private:
  size_t n, n0;
  std::vector<value_t> val;
  std::vector<lazy_t> lazy;

  value_t update(size_t a, size_t b, lazy_t laz, size_t l, size_t r, size_t k) {
    if (lazy[k] != Lazy::id_lazy) {
      if (k < n0 - 1) {
        lazy[2 * k + 1] = Lazy::h(lazy[2 * k + 1], lazy[k]);
        lazy[2 * k + 2] = Lazy::h(lazy[2 * k + 2], lazy[k]);
      }
      val[k] = Lazy::g(val[k], Lazy::p(lazy[k], r - l));
      lazy[k] = Lazy::id_lazy;
    }

    if (r <= a || b <= l) return val[k];
    if (a <= l && r <= b) {
      lazy[k] = Lazy::h(lazy[k], laz);
      return Lazy::g(val[k], Lazy::p(lazy[k], r - l));
    }
    return val[k] = Lazy::f(update(a, b, laz, l, l + (r - l) / 2, 2 * k + 1),
                            update(a, b, laz, l + (r - l) / 2, r, 2 * k + 2));
  }

  value_t fold(size_t a, size_t b, size_t l, size_t r, size_t k) {
    if (lazy[k] != Lazy::id_lazy) {
      if (k < n0 - 1) {
        lazy[2 * k + 1] = Lazy::h(lazy[2 * k + 1], lazy[k]);
        lazy[2 * k + 2] = Lazy::h(lazy[2 * k + 2], lazy[k]);
      }
      val[k] = Lazy::g(val[k], Lazy::p(lazy[k], r - l));
      lazy[k] = Lazy::id_lazy;
    }

    if (r <= a || b <= l) return Lazy::id_val;
    if (a <= l && r <= b) return val[k];
    return Lazy::f(fold(a, b, l, l + (r - l) / 2, 2 * k + 1),
                   fold(a, b, l + (r - l) / 2, r, 2 * k + 2));
  }

  inline size_t beki(size_t n_) {
    size_t ret = 1;
    while (ret < n_) ret <<= 1;
    return ret;
  }

 public:
  LazySegmentTree(size_t n_)
      : n(n_),
        n0(beki(n)),
        val(2 * n0 - 1, Lazy::id_val),
        lazy(2 * n0 - 1, Lazy::id_lazy) {}

  LazySegmentTree(std::vector<value_t> val_)
      : n(val_.size()),
        n0(beki(n)),
        val(2 * n0 - 1, Lazy::id_val),
        lazy(2 * n0 - 1, Lazy::id_lazy) {
    for (size_t i = 0; i < n; i++) val[i + n0 - 1] = val_[i];
    for (long long i = n0 - 2; i >= 0; i--)
      val[i] = Lazy::f(val[2 * i + 1], val[2 * i + 2]);
  }

  void update(size_t a, size_t b, lazy_t laz) { update(a, b, laz, 0, n0, 0); }

  value_t fold(size_t a, size_t b) { return fold(a, b, 0, n0, 0); }
};
#line 91 "solve/main.cpp"

struct Lazy{
  using value_t=i64;
  using lazy_t=i64;
  static constexpr value_t id_val=0;
  static constexpr lazy_t id_lazy=1;
  static value_t f(value_t a,value_t b){
    return a+b;
  }
  static value_t g(value_t a,lazy_t b){
    return a*b;
  }
  static lazy_t h(lazy_t a,lazy_t b){
    return a*b;
  }
  static lazy_t p(lazy_t a,std::size_t n){
    return a;
  }
};

int main() {
  std::cin.tie(nullptr);
  std::ios::sync_with_stdio(false);

  i64 n,q;
  std::cin>>n>>q;

  std::vector<std::vector<i64>> graph(n);

  rep(i,1,n){
    i64 p;
    std::cin>>p;

    graph[p-1].emplace_back(i);
  }

  std::vector<i64> in(n),out(n);

  i64 itr = 0;

  auto dfs = [&](auto f, i64 now)->void{
    in[now]=itr;
    itr++;
    for(const auto& next:graph[now]){
      f(f,next);
    }
    out[now] = itr;
  };

  dfs(dfs,0);

  std::vector<i64> a(n);
  rep(i,0,n){
    char t;
    std::cin>>t;
    if(t=='G')a[in[i]]=1;
    else a[in[i]]=-1;
  }

  LazySegmentTree<Lazy> seg(a);

  while(q--){
    i64 p;
    std::cin>>p;
    p--;

    seg.update(in[p],out[p],-1);

    if(seg.fold(in[0],out[0])>0)std::cout<<"broccoli\n";
    else std::cout<<"cauliflower\n";
  }

  return 0;
}
accuracy: 1
time_ms: 60
memory_kb: 23688
final_rank: 9

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll = long long;
using ld = long double;
using ull = unsigned long long;
using uint = unsigned;
using pcc = pair<char, char>;
using pii = pair<int, int>;
using pll = pair<ll, ll>;
using pdd = pair<ld, ld>;
using tuplis = array<ll, 3>;
template<class T> using pq = priority_queue<T, vector<T>, greater<T>>;
const ll LINF=0x1fffffffffffffff;
const ll MINF=0x7fffffffffff;
const int INF=0x3fffffff;
const int MOD=1000000007;
const int MODD=998244353;
const ld DINF=numeric_limits<ld>::infinity();
const ld EPS=1e-9;
const ld PI=3.1415926535897932;
const ll dx[] = {0, 1, 0, -1, 1, -1, 1, -1};
const ll dy[] = {1, 0, -1, 0, 1, 1, -1, -1};
#define overload4(_1,_2,_3,_4,name,...) name
#define overload3(_1,_2,_3,name,...) name
#define rep1(n) for(ll i=0;i<n;++i)
#define rep2(i,n) for(ll i=0;i<n;++i)
#define rep3(i,a,b) for(ll i=a;i<b;++i)
#define rep4(i,a,b,c) for(ll i=a;i<b;i+=c)
#define rep(...) overload4(__VA_ARGS__,rep4,rep3,rep2,rep1)(__VA_ARGS__)
#define rrep1(n) for(ll i=n;i--;)
#define rrep2(i,n) for(ll i=n;i--;)
#define rrep3(i,a,b) for(ll i=b;i-->(a);)
#define rrep4(i,a,b,c) for(ll i=(a)+((b)-(a)-1)/(c)*(c);i>=(a);i-=c)
#define rrep(...) overload4(__VA_ARGS__,rrep4,rrep3,rrep2,rrep1)(__VA_ARGS__)
#define each1(i,a) for(auto&&i:a)
#define each2(x,y,a) for(auto&&[x,y]:a)
#define each3(x,y,z,a) for(auto&&[x,y,z]:a)
#define each(...) overload4(__VA_ARGS__,each3,each2,each1)(__VA_ARGS__)
#define all1(i) begin(i),end(i)
#define all2(i,a) begin(i),begin(i)+a
#define all3(i,a,b) begin(i)+a,begin(i)+b
#define all(...) overload3(__VA_ARGS__,all3,all2,all1)(__VA_ARGS__)
#define rall1(i) (i).rbegin(),(i).rend()
#define rall2(i,k) (i).rbegin(),(i).rbegin()+k
#define rall3(i,a,b) (i).rbegin()+a,(i).rbegin()+b
#define rall(...) overload3(__VA_ARGS__,rall3,rall2,rall1)(__VA_ARGS__)
#define sum(...) accumulate(all(__VA_ARGS__),0LL)
#define dsum(...) accumulate(all(__VA_ARGS__),0.0L)
#define Msum(...) accumulate(all(__VA_ARGS__),0_M)
#define elif else if
#define unless(a) if(!(a))
#define INT(...) int __VA_ARGS__;in(__VA_ARGS__)
#define LL(...) ll __VA_ARGS__;in(__VA_ARGS__)
#define ULL(...) ull __VA_ARGS__;in(__VA_ARGS__)
#define STR(...) string __VA_ARGS__;in(__VA_ARGS__)
#define CHR(...) char __VA_ARGS__;in(__VA_ARGS__)
#define DBL(...) double __VA_ARGS__;in(__VA_ARGS__)
#define LD(...) ld __VA_ARGS__;in(__VA_ARGS__)
#define Sort(a) sort(all(a))
#define Rev(a) reverse(all(a))
#define Uniq(a) sort(all(a));a.erase(unique(all(a)),end(a))
#define vec(type,name,...) vector<type>name(__VA_ARGS__)
#define VEC(type,name,size) vector<type>name(size);in(name)
#define vv(type,name,h,...) vector<vector<type>>name(h,vector<type>(__VA_ARGS__))
#define VV(type,name,h,w) vector<vector<type>>name(h,vector<type>(w));in(name)
#define vvv(type,name,h,w,...) vector<vector<vector<type>>>name(h,vector<vector<type>>(w,vector<type>(__VA_ARGS__)))
template<class T> auto min(const T& a){ return *min_element(all(a)); }
template<class T> auto max(const T& a){ return *max_element(all(a)); }
inline ll popcnt(ull a){ return __builtin_popcountll(a); }
ll intpow(ll a, ll b){ ll ans = 1; while(b){ if(b & 1) ans *= a; a *= a; b /= 2; } return ans; }
ll modpow(ll a, ll b, ll p){ ll ans = 1; while(b){ if(b & 1) (ans *= a) %= p; (a *= a) %= p; b /= 2; } return ans; }
template<class T> bool chmin(T& a, const T& b){ if(a > b){ a = b; return 1; } return 0; }
template<class T> bool chmax(T& a, const T& b){ if(a < b){ a = b; return 1; } return 0; }
template<class T, class U> bool chmin(T& a, const U& b){ if(a > T(b)){ a = b; return 1; } return 0; }
template<class T, class U> bool chmax(T& a, const U& b){ if(a < T(b)){ a = b; return 1; } return 0; }
vector<ll> iota(ll n, ll begin = 0){ vector<ll> a(n); iota(a.begin(), a.end(), begin); return a; }
vector<pll> factor(ull x){ vector<pll> ans; for(ull i = 2; i * i <= x; i++) if(x % i == 0){ ans.push_back({i, 1}); while((x /= i) % i == 0) ans.back().second++; } if(x != 1) ans.push_back({x, 1}); return ans; }
map<ll,ll> factor_map(ull x){ map<ll,ll> ans; for(ull i = 2; i * i <= x; i++) if(x % i == 0){ ans[i] = 1; while((x /= i) % i == 0) ans[i]++; } if(x != 1) ans[x] = 1; return ans; }
vector<ll> divisor(ull x){ vector<ll> ans; for(ull i = 1; i * i <= x; i++) if(x % i == 0) ans.push_back(i); rrep(ans.size() - (ans.back() * ans.back() == x)) ans.push_back(x / ans[i]); return ans; }
template<class T> unordered_map<T, ll> press(vector<T> a){ Uniq(a); unordered_map<T, ll> ans; rep(a.size()) ans[a[i]] = i; return ans; }
template<class T> map<T, ll> press_map(vector<T> a){ Uniq(a); map<T, ll> ans; rep(a.size()) ans[a[i]] = i; return ans; }
int scan(){ return getchar(); }
void scan(int& a){ scanf("%d", &a); }
void scan(unsigned& a){ scanf("%u", &a); }
void scan(long& a){ scanf("%ld", &a); }
void scan(long long& a){ scanf("%lld", &a); }
void scan(unsigned long long& a){ scanf("%llu", &a); }
void scan(char& a){ do{ a = getchar(); }while(a == ' ' || a == '\n'); }
void scan(float& a){ scanf("%f", &a); }
void scan(double& a){ scanf("%lf", &a); }
void scan(long double& a){ scanf("%Lf", &a); }
void scan(vector<bool>& a){ for(unsigned i = 0; i < a.size(); i++){ int b; scan(b); a[i] = b; } }
void scan(char a[]){ scanf("%s", a); }
void scan(string& a){ cin >> a; }
template<class T> void scan(vector<T>&);
template<class T, size_t size> void scan(array<T, size>&);
template<class T, class L> void scan(pair<T, L>&);
template<class T, size_t size> void scan(T(&)[size]);
template<class T> void scan(vector<T>& a){ for(auto&& i : a) scan(i); }
template<class T> void scan(deque<T>& a){ for(auto&& i : a) scan(i); }
template<class T, size_t size> void scan(array<T, size>& a){ for(auto&& i : a) scan(i); }
template<class T, class L> void scan(pair<T, L>& p){ scan(p.first); scan(p.second); }
template<class T, size_t size> void scan(T (&a)[size]){ for(auto&& i : a) scan(i); }
template<class T> void scan(T& a){ cin >> a; }
void in(){}
template <class... T> void in(T&... a){ (void)initializer_list<int>{ (scan(a), 0)... }; }
void print(){ putchar(' '); }
void print(bool a){ printf("%d", a); }
void print(int a){ printf("%d", a); }
void print(unsigned a){ printf("%u", a); }
void print(long a){ printf("%ld", a); }
void print(long long a){ printf("%lld", a); }
void print(unsigned long long a){ printf("%llu", a); }
void print(char a){ printf("%c", a); }
void print(char a[]){ printf("%s", a); }
void print(const char a[]){ printf("%s", a); }
void print(float a){ printf("%.15f", a); }
void print(double a){ printf("%.15f", a); }
void print(long double a){ printf("%.15Lf", a); }
void print(const string& a){ for(auto&& i : a) print(i); }
template<class T> void print(const complex<T>& a){ if(a.real() >= 0) print('+'); print(a.real()); if(a.imag() >= 0) print('+'); print(a.imag()); print('i'); }
template<class T> void print(const vector<T>&);
template<class T, size_t size> void print(const array<T, size>&);
template<class T, class L> void print(const pair<T, L>& p);
template<class T, size_t size> void print(const T (&)[size]);
template<class T> void print(const vector<T>& a){ if(a.empty()) return; print(a[0]); for(auto i = a.begin(); ++i != a.end(); ){ putchar(' '); print(*i); } }
template<class T> void print(const deque<T>& a){ if(a.empty()) return; print(a[0]); for(auto i = a.begin(); ++i != a.end(); ){ putchar(' '); print(*i); } }
template<class T, size_t size> void print(const array<T, size>& a){ print(a[0]); for(auto i = a.begin(); ++i != a.end(); ){ putchar(' '); print(*i); } }
template<class T, class L> void print(const pair<T, L>& p){ print(p.first); putchar(' '); print(p.second); }
template<class T, size_t size> void print(const T (&a)[size]){ print(a[0]); for(auto i = a; ++i != end(a); ){ putchar(' '); print(*i); } }
template<class T> void print(const T& a){ cout << a; }
int out(){ putchar('\n'); return 0; }
template<class T> int out(const T& t){ print(t); putchar('\n'); return 0; }
template<class Head, class... Tail> int out(const Head& head, const Tail&... tail){ print(head); putchar(' '); out(tail...); return 0; }
#ifdef DEBUG
inline ll __lg(ull x){ return 63 - __builtin_clzll(x); }
#define debug(...) { print(#__VA_ARGS__); print(":"); out(__VA_ARGS__); }
#else
#define debug(...) void(0)
#endif
int first(bool i = true){ return out(i?"first":"second"); }
int First(bool i = true){ return out(i?"First":"Second"); }
int yes(bool i = true){ return out(i?"yes":"no"); }
int Yes(bool i = true){ return out(i?"Yes":"No"); }
int No(){ return out("No"); }
int YES(bool i = true){ return out(i?"YES":"NO"); }
int NO(){ return out("NO"); }
int Yay(bool i = true){ return out(i?"Yay!":":("); }
int possible(bool i = true){ return out(i?"possible":"impossible"); }
int Possible(bool i = true){ return out(i?"Possible":"Impossible"); }
int POSSIBLE(bool i = true){ return out(i?"POSSIBLE":"IMPOSSIBLE"); }
void Case(ll i){ printf("Case #%lld: ", i); }



struct UnWeightedEdge{
    ll to;
    static constexpr ll cost = 1;
    UnWeightedEdge(){}
    UnWeightedEdge(ll to): to(to){}
    operator ll() const { return to; }
};
struct UnWeightedGraph{
    using E = UnWeightedEdge;
    vector<vector<E>> g;
    UnWeightedGraph(){}
    UnWeightedGraph(ll n): g(n){}
    vector<E>& operator[](ll at){ return g[at]; }
    operator vector<vector<E>>&(){ return g; }
    auto begin(){ return g.begin(); }
    auto end(){ return g.end(); }
    auto begin() const { return g.cbegin(); }
    auto end() const { return g.cend(); }
    ll size() const { return g.size(); }
    void resize(ll n){ g.resize(n); }
    const vector<E>& operator[](ll at) const { return g[at]; }
    operator const vector<vector<E>>&() const { return g; }
    void add_edge(ll a, ll b){
        g[a].emplace_back(b);
        g[b].emplace_back(a);
    }
    void add_directed_edge(ll from, ll to){
        g[from].emplace_back(to);
    }
    template<ll start_index = 1> void input_graph(ll m){
        while(m--){
            ll a, b;
            scanf("%lld%lld", &a, &b);
            a -= start_index;
            b -= start_index;
            g[a].emplace_back(b);
            g[b].emplace_back(a);
        }
    }
    template<ll start_index = 1> void input_directed_graph(ll m){
        while(m--){
            ll a, b;
            scanf("%lld%lld", &a, &b);
            a -= start_index;
            b -= start_index;
            g[a].emplace_back(b);
        }
    }
    template<ll start_index = 1> void input_tree(ll n = -1){ if(n == -1) n = g.size(); input_graph<start_index>(n - 1); }
};
struct HLDecomposition{
    ll n;
    const UnWeightedGraph& g;
    vector<ll> index, invex, light_root, heavy_root, siz;
    HLDecomposition(const UnWeightedGraph& g, ll root = 0): n(g.size()), g(g), index(n), invex(n), light_root(n), heavy_root(n), siz(n, 1){
        dfs(-1, root);
        n = 0;
        dfs2(-1, root, -1, 0);
        vector<ll> siz2(n);
        for(ll i = 0; i < n; i++) siz2[index[i]] = siz[i];
        swap(siz, siz2);
    }
    void dfs(ll from, ll at){
        for(auto& i : g[at]) if(i != from){
            dfs(at, i);
            siz[at] += siz[i];
        }
    }
    void dfs2(ll from, ll at, ll light, ll heavy){
        invex[n] = at;
        light_root[n] = light;
        heavy_root[n] = heavy;
        index[at] = n++;
        ll max = -1, maxdex = -1;
        for(auto& i : g[at]) if(i != from && chmax(max, siz[i])) maxdex = i;
        if(maxdex == -1) return;
        dfs2(at, maxdex, light, heavy);
        for(auto& i : g[at]) if(i != from && i != maxdex) dfs2(at, i, index[at], n);
    }
    ll lca(ll a, ll b){
        a = index[a]; b = index[b];
        while(true){
            if(a > b) swap(a, b);
            if(heavy_root[a] == heavy_root[b]) return invex[a];
            b = light_root[b];
        }
    }
    template<class T> void path_node(ll a, ll b, const T& f){
        a = index[a]; b = index[b];
        while(true){
            if(a > b) swap(a, b);
            if(heavy_root[a] == heavy_root[b]){
                f(a, b + 1);
                return;
            }
            f(heavy_root[b], b + 1);
            b = light_root[b];
        }
    }
    template<class T> void path_edge(ll a, ll b, const T& f){
        a = index[a]; b = index[b];
        while(true){
            if(a > b) swap(a, b);
            if(heavy_root[a] == heavy_root[b]){
                if(a != b) f(a, b);
                return;
            }
            f(heavy_root[b] - 1, b);
            b = light_root[b];
        }
    }
    template<class T> void subtree_node(ll a, const T& f){
        a = index[a];
        f(a, a + siz[a]);
    }
    template<class T> void subtree_edge(ll a, const T& f){
        a = index[a];
        f(a, a + siz[a] - 1);
    }
};
template<class T, class U>
struct LazySegmentTree{
    virtual T f(const T&, const T&) = 0;
    virtual void m(ll, T&, const U&) = 0;
    virtual void c(U&, const U&) = 0;
    ll size = 1, rank = 0;
    vector<T> data;
    vector<U> lazy;
    const T def_value;
    const U def_lazy;
    LazySegmentTree(ll n, const T& def_value, const U& def_lazy): def_value(def_value), def_lazy(def_lazy){
        while(size < n){
            size *= 2;
            rank++;
        }
        data.assign(size * 2, def_value);
        lazy.assign(size * 2, def_lazy);
    }
    LazySegmentTree(const vector<T>& v, const T& def_value, const U& def_lazy): def_value(def_value), def_lazy(def_lazy){
        while(size < v.size()){
            size *= 2;
            rank++;
        }
        data.assign(size * 2, def_value);
        lazy.assign(size * 2, def_lazy);
        for(ll i = 0; i < v.size(); i++) data[size + i] = v[i];
    }
    void push(ll at){
        if(!at) return;
        ll r = 31 - __builtin_clz(at);
        for(ll i = r; i > 0; i--){
            ll a = at >> i;
            if(lazy[a] != def_lazy){
                m(rank + i - r - 1, data[a * 2], lazy[a]);
                m(rank + i - r - 1, data[a * 2 + 1], lazy[a]);
                c(lazy[a * 2], lazy[a]);
                c(lazy[a * 2 + 1], lazy[a]);
                lazy[a] = def_lazy;
            }
        }
    }
    void update(ll at){
        while(at /= 2){
            data[at] = f(data[at * 2], data[at * 2 + 1]);
        }
    }
    T operator[](ll at){
        at += size;
        push(at);
        return data[at];
    }
    void set(ll at, const T& val){
        at += size;
        push(at);
        data[at] = val;
        update(at);
    }
    void query(ll l, ll r, const U& val){
        if(l >= r) return;
        l += size;
        r += size;
        ll L = l >> __builtin_ctz(l), R = (r >> __builtin_ctz(r)) - 1;
        push(L);
        push(R);
        for(ll rank = 0; l < r; l /= 2, r /= 2, rank++){
            if(l & 1){
                m(rank, data[l], val);
                c(lazy[l++], val);
            }
            if(r & 1){
                m(rank, data[--r], val);
                c(lazy[r], val);
            }
        }
        update(L);
        update(R);
    }
    T get(ll l, ll r){
        if(l >= r) return def_value;
        T L = def_value, R = def_value;
        l += size; r += size;
        push(l);
        push(r - 1);
        for(; l < r; l /= 2, r /= 2){
            if(l & 1) L = f(L, data[l++]);
            if(r & 1) R = f(data[--r], R);
        }
        return f(L, R);
    }
    void clear(){
        for(auto& i : data) i = def_value;
    }
};
using T = pll;
struct S : LazySegmentTree<T, char>{
    using Base = LazySegmentTree<T, char>;
    T f(const T& a, const T& b){ return {a.first + b.first, a.second + b.second}; }
    void m(ll rank, T& x, const char& val){ if(val) swap(x.first, x.second); }
    void c(char& a, const char& b){ a ^= b; }
    S(const vector<T>& v, const T& def_value = T()) : Base(v, def_value, 0){
        for(ll i = Base::size; --i;) Base::data[i] = f(Base::data[i * 2], Base::data[i * 2 + 1]);
    }
};
int main(){
    LL(n,q);
    VEC(ll,p,n-1);
    p.insert(p.begin(),-1);
    VEC(char,c,n);
    UnWeightedGraph g(n);
    rep(i,1,n)g.add_edge(--p[i],i);
    HLDecomposition hld(g);
    vector<T>a(n);
    rep(n)(c[i]=='G'?a[hld.index[i]].first:a[hld.index[i]].second)=1;
    S seg(a);
    rep(q){
        LL(x);
        x--;
        hld.subtree_node(x,[&](ll l,ll r){seg.query(l,r,1);});
        out(seg.data[1].first>seg.data[1].second?"broccoli":"cauliflower");
    }
}
accuracy: 1
time_ms: 40
memory_kb: 27636
final_rank: 8

code_snippet: #include <iostream>
#include <algorithm>
#include <utility>
#include <string>
#include <vector>
#include <set>
#include <stack>
#include <queue>
#include <map>
#include <math.h>
#include <string.h>
#include <iomanip>
#include <numeric>
#include <cstdlib>
#include <cstdint>
#include <cmath>
#include <functional>
#include <limits>
#include <cassert>
#include <bitset>
#include <chrono>
#include <random>
#include <memory>
 
/* macro */
 
#define rep(i, a, n) for (int i = (int)(a); i < (int)(n); i++)
#define rrep(i, a, n) for (int i = ((int)(n-1)); i >= (int)(a); i--)
#define Rep(i, a, n) for (i64 i = (i64)(a); i< (i64)(n); i++)
#define RRep(i, a, n) for (i64 i = ((i64)(n-i64(1))); i>=(i64)(a); i--)
#define all(v) (v).begin(),(v).end()
#define rall(v) (v).rbegin(),(v).rend()
 
/* macro end */
 
/* template */
 
namespace ebi {
 
#ifdef LOCAL
#define debug(...)                                                    \
    std::cerr << "LINE: " << __LINE__ << "  [" << #__VA_ARGS__ << "]:", \
        debug_out(__VA_ARGS__)
#else
#define debug(...)
#endif
 
void debug_out() { std::cerr << std::endl; }
 
template <typename Head, typename... Tail>
void debug_out(Head h, Tail... t) {
    std::cerr << " " << h;
    if (sizeof...(t) > 0) std::cout << " :";
    debug_out(t...);
}
 
template <typename T1, typename T2>
std::ostream& operator<<(std::ostream& os, std::pair<T1, T2> pa) {
    return os << pa.first << " " << pa.second;
}
 
template <typename T>
std::ostream& operator<<(std::ostream& os, std::vector<T> vec) {
    for (std::size_t i = 0; i < vec.size(); i++) os << vec[i] << (i + 1 == vec.size() ? "" : " ");
    return os;
}
 
using size_t = std::size_t;
using i64 = long long;
using u64 = unsigned long long;
 
template<class T> void fill(std::vector<T> &v) { for(T &e: v) std::cin >> e; }
 
template<class T>
struct Edge {
    int to;
    T cost;
    Edge(int to, T cost) : to(to), cost(cost) { }
};
 
template<class T>
using Graph = std::vector<std::vector<Edge<T>>>;
 
using graph = std::vector<std::vector<int>>;
 
template <class T>
inline bool chmin(T &a, T b) {
    if (a > b){
        a = b;
        return true;
    }
    return false;
}
 
template <class T>
inline bool chmax(T &a, T b) {
    if (a < b){
        a = b;
        return true;
    }
    return false;
}
 
template <class T>
T gcd(T a, T b){
    if( b==0 ) return a;
    else return gcd(b, a%b);
}
 
template <class T>
T lcm(T a, T b) {
    return (a*b)/gcd(a,b);
}
 
template<class T>
T Pow(T x, i64 n) {
    T res = 1;
    while(n>0){
        if(n&1) res = res *x;
        x = x*x;
        n>>=1;
    }
    return res;
}
 
template<class T>
T scan() {
    T val;
    std::cin >> val;
    return val;
}
 
constexpr i64 LNF = std::numeric_limits<i64>::max()/4;
 
constexpr int INF = std::numeric_limits<int>::max()/4;
 
const long double PI = acos(-1);
 
const std::vector<int> dy = {1,0,-1,0,1,1,-1,-1};
const std::vector<int> dx = {0,1,0,-1,1,-1,1,-1};
 
}
 
/* template end */

/*
    author: noshi91
    reference: https://noshi91.hatenablog.com/entry/2019/03/31/174006
    noshi91のブログで公開されているmodintを元にinv(), pow()を追加したものです
*/

#include <cstdint>
#include <iostream>

namespace ebi {

template<std::uint_fast64_t Modulus>
class modint {
  using u64 = std::uint_fast64_t;

public:
    u64 a;

    constexpr modint(const u64 x = 0) noexcept : a(x % Modulus) {}
    constexpr u64 &value() noexcept { return a; }
    constexpr u64 &val() noexcept { return a; }
    constexpr const u64 &value() const noexcept { return a; }
    constexpr modint operator+(const modint rhs) const noexcept {
        return modint(*this) += rhs;
    }
    constexpr modint operator-(const modint rhs) const noexcept {
        return modint(*this) -= rhs;
    }
    constexpr modint operator*(const modint rhs) const noexcept {
        return modint(*this) *= rhs;
    }
    constexpr modint operator/(const modint rhs) const noexcept {
        return modint(*this) /= rhs;
    }
    constexpr modint &operator+=(const modint rhs) noexcept {
        a += rhs.a;
        if (a >= Modulus) {
            a -= Modulus;
        }
        return *this;
    }
    constexpr modint &operator-=(const modint rhs) noexcept {
        if (a < rhs.a) {
        a += Modulus;
        }
        a -= rhs.a;
        return *this;
    }
    constexpr modint &operator*=(const modint rhs) noexcept {
        a = a * rhs.a % Modulus;
        return *this;
    }
    constexpr modint &operator/=(modint rhs) noexcept {
        u64 exp = Modulus - 2;
        while (exp) {
        if (exp % 2) {
            *this *= rhs;
        }
        rhs *= rhs;
        exp /= 2;
        }
        return *this;
    }
    constexpr modint operator-() const { return modint() - *this; }
    bool operator==(const u64 rhs) {
        return a == rhs;
    }
    bool operator!=(const u64 rhs) {
        return a != rhs;
    }
    constexpr modint& operator++() {
        a++;
        if( a == mod() ) a = 0;
        return *this;
    }
    constexpr modint& operator--() {
        if( a == 0 ) a = mod();
        a--;
        return *this;
    }

    modint pow(u64 n) const noexcept {
        modint res = 1;
        modint x = a;
        while(n>0){
            if(n&1) res *= x;
            x *= x;
            n >>=1;
        }
        return res;
    }
    modint inv() const {
        return pow(Modulus-2);
    }

    static u64 mod() {
        return Modulus;
    }
};

using modint998244353 = modint<998244353>;
using modint1000000007 = modint<1000000007>;

template<std::uint_fast64_t Modulus>
std::ostream& operator<<(std::ostream& os, modint<Modulus> a){
    return os << a.val();
}

} // namespace ebi


#line 2 "data_structure/heavy_light_decomposition.hpp"

#line 2 "data_structure/Segtree.hpp"

#include <vector>

namespace ebi {

template<class Monoid, Monoid (*op)(Monoid, Monoid), Monoid (*e)()>
struct Segtree {
private:
    std::vector<Monoid> data;
    int n;
public:
    Segtree(int _n) : n(1) {
        while(n<_n){
            n <<= 1;
        }
        data.assign(2*n-1, e());
    }

    Segtree(std::vector<Monoid> v) : n(1) {
        int _n = v.size();
        while(n<_n){
            n <<= 1;
        }
        data.assign(2*n-1, e());
        for(int i = 0; i<_n; i++){
            data[n+i-1] = v[i];
        }
        for(int i = n-2; i>=0; i--){
            data[i] = op(data[2*i+1], data[2*i+2]);
        }
    }

    void set(int p, Monoid x){
        int k = n+p-1;
        data[k] = x;
        while(k>0){
            k = (k-1)/2;
            data[k] = op(data[2*k+1], data[2*k+2]);
        }
    }

    Monoid prod(int tl, int tr, int l=0, int r=-1, int index=0){
        if(r<0) r = n;
        if(tr<=l || r<=tl){
            return e();
        }
        if(tl<=l && r<=tr){
            return data[index];
        }
        return op(prod(tl, tr, l, (l+r)/2, 2*index+1), prod(tl, tr, (l+r)/2, r, 2*index+2));
    }

    Monoid all_prod() { return data[0]; }

    Monoid get(int p) { return data[n+p-1]; }

    Monoid operator [] (int p) { return data[n+p-1]; }
};

} // namespace ebi

/*
    reference: https://beet-aizu.hatenablog.com/entry/2017/12/01/225955
               https://atcoder.github.io/ac-library/master/document_ja/lazysegtree.html
*/

#include <vector>
#include <cassert>

namespace ebi {

template<
    class S,
    S (*op)(S, S),
    S (*e)(),
    class F,
    S (*mapping)(F, S),
    F (*merge)(F, F),
    F (*id)()>
struct LazySegtree {
private:
    std::vector<S> data;
    std::vector<F> lazy;
    int n;

    void eval(int index, int l, int r) {
        data[index] = mapping(lazy[index], data[index]);
        if(r-l>1) {
            lazy[2*index+1] = merge(lazy[index] ,lazy[2*index+1]);
            lazy[2*index+2] = merge(lazy[index] ,lazy[2*index+2]);
        }
        lazy[index] = id();
    }

    S _prod(int l, int r, int nl = 0, int nr = -1, int index = 0) {
        if(nr < 0) nr = n;
        if(nr<=l || r<=nl) {
            return e();
        }
        eval(index, nl, nr);
        if(l<=nl && nr<=r) {
            return data[index];
        }
        return op(_prod(l, r, nl, (nl+nr)/2, 2*index+1), _prod(l, r, (nl+nr)/2, nr, 2*index+2));
    }

    void _apply(int l, int r, F f, int nl = 0, int nr = -1, int index = 0) {
        if(nr<0) nr = n;
        eval(index, nl, nr);
        if(nr<=l || r<=nl) return;
        if(l<=nl && nr<=r) {
            lazy[index] = merge(f, lazy[index]);
            eval(index, nl, nr);
            return;
        }
        _apply(l, r, f, nl, (nl+nr)/2, 2*index+1);
        _apply(l, r, f, (nl+nr)/2, nr, 2*index+2);
        data[index] = op(data[2*index+1], data[2*index+2]);
        return;
    }

public:
    LazySegtree(int _n) : n(1) {
        while(n<_n) {
            n <<= 1;
        }
        data.assign(2*n-1, e());
        lazy.assign(2*n-1, id());
    }

    LazySegtree(std::vector<S> v) : n(1) {
        int _n = v.size();
        while(n<_n) {
            n <<= 1;
        }
        data.assign(2*n-1, e());
        lazy.assign(2*n-1, id());
        for(int i = 0; i<_n; i++) {
            data[i+n-1] = v[i];
        }
        for(int i = n-2; i>=0; i--) {
            data[i] = op(data[2*i+1], data[2*i+2]);
        }
    }

    S prod(int l, int r) {
        return _prod(l, r);
    }

    S all_prod() {
        eval(0,0,n);
        return data[0];
    }

    void apply(int l, int r, F f) {
        _apply(l, r, f);
    }

    S get(int i) {
        int l = 0, r = n;
        int k = 0;
        while(r-l>1) {
            eval(k, l, r);
            int mid = (l+r)/2;
            if(i<mid) {
                k = 2*k+1;
                r = mid;
            }
            else {
                k = 2*k+2;
                l = mid;
            }
        }
        eval(k, l, r);
        return data[k];
    }
};

} // namespace ebi

namespace ebi {

using mint = modint998244353;

using ld = long double;

struct S{
    long long value;
    int size;
};
using F = long long;

const F ID = 1e18;

S op(S a, S b) {
    return {a.value + b.value, a.size + b.size};
}

S e() {
    return {0, 0};
}

S mapping(F f, S x) {
    if(f != ID) {
        x.value = x.size - x.value;
    }
    return x;
}

F merge(F f, F g) {
    if(f == ID && g == ID) return f;
    else if(f != ID && g != ID) return ID;
    else return 1;
}

F id() { return ID; }

void main_() {
    int n,q;
    std::cin >> n >> q;
    graph g(n);
    std::vector<int> c(n);
    rep(i,1,n) {
        int p;
        std::cin >> p;
        p--;
        g[i].emplace_back(p);
        g[p].emplace_back(i);
    }
    rep(i,0,n) {
        char x;
        std::cin >> x;
        if(x == 'G') c[i] = 1;
    }
    std::vector<int> in(n);
    std::vector<int> out(n);
    LazySegtree<S, op, e, F, mapping, merge, id> seg(std::vector<S>(n, {0, 1}));
    int time = 0;
    auto dfs = [&](auto dfs, int v, int par = -1) -> void {
        in[v] = time;
        if(c[v] > 0) seg.apply(time, time+1, 1);
        for(auto nv: g[v]) {
            if(nv == par) continue;
            time++;
            dfs(dfs, nv, v);
        }
        out[v] = time+1;
    };
    dfs(dfs, 0);
    while(q--) {
        int v;
        std::cin >> v;
        v--;
        seg.apply(in[v], out[v], 1);
        int ans = seg.prod(0, n).value;
        if((n+1)/2 <= ans) {
            std::cout << "broccoli\n";
        }
        else {
            std::cout << "cauliflower\n";
        }
    }
}
 
}

 
int main() {
    std::cout << std::fixed << std::setprecision(15);
    std::cin.tie(nullptr);
    std::ios::sync_with_stdio(false);
    int t = 1;
    while(t--) {
        ebi::main_();
    }
    return 0;
}
accuracy: 1
time_ms: 100
memory_kb: 36116
final_rank: 18

code_snippet: #include <vector>
#include <cassert>
#include <stack>
#include <utility>

struct EulerTour {
	using size_type = std::size_t;
	using Tree = std::vector<std::vector<size_type>>;
	
private:
	size_type n;
	const Tree & tree;
	size_type root;
	std::vector<size_type> in_, out_;
	std::vector<size_type> par_, g_idx;
	
public:
	EulerTour(const Tree & tree, size_type root) : n(tree.size()), tree(tree), root(root) {
		in_.assign(size(), size());
		out_.assign(size(), size());
		par_.assign(n, n);
		g_idx.assign(size(), n);
		
		std::stack<std::pair<size_type, size_type>> stk;
		std::vector<size_type> par_edge(n, n);
		size_type num = 0;
		
		in_[root] = num++;
		stk.emplace(root, 0);
		
		while (!stk.empty()) {
			const size_type u = stk.top().first;
			const size_type i = stk.top().second;
			stk.pop();
			
			if (i < tree[u].size()) {
				const size_type v = tree[u][i];
				stk.emplace(u, i + 1);
				if (v == par_[u]) par_edge[u] = i;
				else {
					g_idx[num] = i;
					in_[v] = num++;
					par_[v] = u;
					stk.emplace(v, 0);
				}
			}
			else out_[u] = num++;
		}
		for (size_type i = 0; i < n; ++i) g_idx[out_[i]] = par_edge[i];
	}
	
	size_type size() const noexcept { return n << 1; }
	size_type par(size_type k) const { assert(k < size()); return par_[k]; }
	size_type in(size_type k) const { assert(k < size()); return in_[k]; }
	size_type out(size_type k) const { assert(k < size()); return out_[k]; }
	std::pair<size_type, size_type> par_from(size_type k) const { assert(k < size()); return {par_[k], g_idx[in_[k]]}; }
	size_type par_to(size_type k) const { assert(k < size()); return g_idx[out_[k]]; }
};

#include <functional>
#include <cassert>
#include <stack>
#include <cstdint>

/**
 * @brief https://tkmst201.github.io/Library/DataStructure/DynamicSegmentTree.hpp
 */
template<typename T>
struct DynamicSegmentTree {
	using value_type = T;
	using const_reference = const value_type &;
	using size_type = std::size_t;
	using F = std::function<value_type (const_reference, const_reference)>;
	
private:
	struct Node;
	using node_ptr = Node *;
	using const_ptr = const Node * const;
	struct Node {
		value_type val;
		node_ptr child[2] {nullptr, nullptr};
		Node() = default;
		Node(const_reference val) : val(val) {}
	};
	
	template<typename U>
	struct Data {
		U node;
		size_type l, r;
		Data(U node, size_type l, size_type r) : node(node), l(l), r(r) {}
	};
	
private:
	size_type n, n_;
	int log_n;
	value_type id_elem;
	F f;
	node_ptr root = nullptr;
	
public:
	DynamicSegmentTree(size_type n, const_reference id_elem, const F & f)
		: n(n), id_elem(id_elem), f(f), root(nullptr) {
		n_ = 1;
		log_n = 0;
		while (n_ < n) n_ <<= 1, ++log_n;
	}
	
	DynamicSegmentTree(const DynamicSegmentTree & rhs) {
		*this = rhs;
	}
	
	DynamicSegmentTree(DynamicSegmentTree && rhs) {
		*this = std::forward<DynamicSegmentTree>(rhs);
	}
	
	~DynamicSegmentTree() {
		clear();
	}
	
	DynamicSegmentTree & operator =(const DynamicSegmentTree & rhs) {
		if (this != &rhs) {
			clear();
			n = rhs.n;
			n_ = rhs.n_;
			log_n = rhs.log_n;
			id_elem = rhs.id_elem;
			f = rhs.f;
			root = copy_dfs(rhs.root, nullptr);
		}
		return *this;
	}
	
	DynamicSegmentTree & operator =(DynamicSegmentTree && rhs) {
		if (this != &rhs) {
			clear();
			n = rhs.n;
			n_ = rhs.n_;
			log_n = rhs.log_n;
			id_elem = rhs.id_elem;
			f = rhs.f;
			root = rhs.root;
			rhs.root = nullptr;
		}
		return *this;
	}
	
	void clear() {
		clear_subtree(root);
		root = nullptr;
	}
	
	size_type size() const noexcept {
		return n;
	}
	
	void set(size_type k, const_reference x) {
		assert(k < size());
		if (!root) root = new Node;
		node_ptr node = root;
		std::stack<node_ptr> stk;
		for (int i = log_n - 1; i >= 0; --i) {
			stk.emplace(node);
			const bool r = k >> i & 1;
			if (!node->child[r]) node->child[r] = new Node;
			node = node->child[r];
		}
		node->val = x;
		while (!stk.empty()) {
			node = stk.top();
			stk.pop();
			node->val = f(node->child[0] ? node->child[0]->val : id_elem, node->child[1] ? node->child[1]->val : id_elem);
		}
	}
	
	void set_id(size_type l, size_type r) {
		assert(l <= r);
		assert(r <= size());
		if (l == 0 && r == n_) {
			clear_sub(root);
			root = nullptr;
			return;
		}
		if (l == r || !root) return;
		std::stack<Data<node_ptr>> stk;
		stk.emplace(root);
		while (!stk.empty()) {
			auto [node, cl, cr] = stk.top();
			stk.pop();
			if (cl == cr) {
				node->val = f(node->child[0] ? node->child[0]->val : id_elem, node->child[1] ? node->child[1]->val : id_elem);
				continue;
			}
			const size_type m = cl + ((cr - cl) >> 1);
			stk.emplace(node, 0, 0);
			if (m < r && node->child[1]) {
				if (l <= m && cr <= r) {
					clear_subtree(node->child[1]);
					node->child[1] = nullptr;
				}
				else stk.emplace(node->child[1], m, cr);
			}
			if (l < m && node->child[0]) {
				if (l <= cl && m <= r) {
					clear_sub(node->child[0]);
					node->child[0] = nullptr;
				}
				else stk.emplace(node->child[0], cl, m);
			}
		}
	}
	
	const_reference get(size_type k) const noexcept {
		assert(k < size());
		if (!root) return id_elem;
		node_ptr node = root;
		for (int i = log_n - 1; i >= 0; --i) {
			const bool r = k >> i & 1;
			if (!node->child[r]) return id_elem;
			node = node->child[r];
		}
		return node->val;
	}
	
	const_reference fold_all() const noexcept {
		if (!root) return id_elem;
		return root->val;
	}
	
	value_type fold(size_type l, size_type r) const noexcept {
		assert(l <= r);
		assert(r <= size());
		if (l == r || !root) return id_elem;
		value_type res = id_elem;
		std::stack<Data<node_ptr>> stk;
		stk.emplace(root, 0, n_);
		while (!stk.empty()) {
			auto [node, cl, cr] = stk.top();
			stk.pop();
			if (l <= cl && cr <= r) res = f(res, node->val);
			else {
				const size_type m = cl + ((cr - cl) >> 1);
				if (m < r && node->child[1]) stk.emplace(node->child[1], m, cr);
				if (l < m && node->child[0]) stk.emplace(node->child[0], cl, m);
			}
		}
		return res;
	}
	
	void swap(DynamicSegmentTree & rhs, size_type l, size_type r) {
		assert(size() == rhs.size());
		assert(id_elem == rhs.id_elem);
		assert(l <= r);
		assert(r <= size());
		if (this == &rhs) return;
		if (l == r) return;
		if (l == 0 && r == n_ || size() == 1) { std::swap(root, rhs.root); return; }
		if (!root && !rhs.root) return;
		if (!root) root = new Node{id_elem};
		if (!rhs.root) rhs.root = new Node{id_elem};
		
		std::stack<Data<std::pair<node_ptr, node_ptr>>> stk;
		stk.emplace(std::make_pair(root, rhs.root), 0, n_);
		while (!stk.empty()) {
			auto [nodes, cl, cr] = stk.top();
			auto [node1, node2] = nodes;
			stk.pop();
			if (cl == cr) {
				node1->val = f(node1->child[0] ? node1->child[0]->val : id_elem, node1->child[1] ? node1->child[1]->val : id_elem);
				node2->val = f(node2->child[0] ? node2->child[0]->val : id_elem, node2->child[1] ? node2->child[1]->val : id_elem);
				continue;
			}
			const size_type m = cl + ((cr - cl) >> 1);
			stk.emplace(nodes, 0, 0);
			if (m < r && (node1->child[1] || node2->child[1])) {
				if (l <= m && cr <= r) std::swap(node1->child[1], node2->child[1]);
				else {
					if (!node1->child[1]) node1->child[1] = new Node;
					else if (!node2->child[1]) node2->child[1] = new Node;
					stk.emplace(std::make_pair(node1->child[1], node2->child[1]), m, cr);
				}
			}
			if (l < m && (node1->child[0] || node2->child[0])) {
				if (l <= cl && m <= r) std::swap(node1->child[0], node2->child[0]);
				else {
					if (!node1->child[0]) node1->child[0] = new Node{};
					else if (!node2->child[0]) node2->child[0] = new Node{};
					stk.emplace(std::make_pair(node1->child[0], node2->child[0]), cl, m);
				}
			}
		}
	}
	
private:
	node_ptr copy_dfs(const_ptr q, node_ptr r) {
		if (!q) return nullptr;
		node_ptr res = new Node{q->val};
		res->child[0] = copy_dfs(q->child[0], res);
		res->child[1] = copy_dfs(q->child[1], res);
		return res;
	}
	
	void clear_subtree(node_ptr r) {
		if (!r) return;
		std::stack<node_ptr> stk;
		stk.emplace(r);
		while (!stk.empty()) {
			node_ptr node = stk.top();
			stk.pop();
			if (node->child[0]) stk.emplace(node->child[0]);
			if (node->child[1]) stk.emplace(node->child[1]);
			delete node;
		}
	}
};

#include <cstdio>
#include <utility>

int main() {
	int N, Q;
	scanf("%d %d", &N, &Q);
	
	EulerTour::Tree tree(N);
	for (int i = 1; i < N; ++i) {
		int p;
		scanf("%d", &p);
		tree[p - 1].emplace_back(i);
	}
	
	EulerTour et(tree, 0);
	DynamicSegmentTree<int> seg(et.size(), 0, [](int x, int y) { return x + y; });
	auto segr = seg;
	
	for (int i = 0; i < N; ++i) {
		char c;
		scanf(" %c", &c);
		if (c == 'G') seg.set(et.in(i), 1);
		else segr.set(et.in(i), 1);
	}
	
	while (Q--) {
		int v;
		scanf("%d", &v);
		--v;
		seg.swap(segr, et.in(v), et.out(v));
		const int x = seg.fold_all();
		const int y = N - x;
		puts(x > y ? "broccoli" : "cauliflower");
	}
}
accuracy: 1
time_ms: 100
memory_kb: 26592
final_rank: 12