#include <bits/stdc++.h>
#define rep(i,n) for(int i=0;i<(int)(n);i++)
#define rep1(i,n) for(int i=1;i<=(int)(n);i++)
#define all(c) c.begin(),c.end()
#define pb push_back
#define fs first
#define sc second
#define show(x) cout << #x << " = " << x << endl
#define chmin(x,y) x=min(x,y)
#define chmax(x,y) x=max(x,y)
using namespace std;
template<class S,class T> ostream& operator<<(ostream& o,const pair<S,T> &p){return o<<"("<<p.fs<<","<<p.sc<<")";}
template<class T> ostream& operator<<(ostream& o,const vector<T> &vc){o<<"sz = "<<vc.size()<<endl<<"[";for(const T& v:vc) o<<v<<",";o<<"]";return o;}

template<class Handler>
struct segtree_lazy{
	using val_t = typename Handler::val_t;
	using opr_t = typename Handler::opr_t;
	int N;
	vector<val_t> val;
	vector<opr_t> lazy;
	segtree_lazy(){}
	segtree_lazy(int n){init(n);}
	segtree_lazy(const vector<val_t>& vc){init(vc);}
	void init(int n){
		N=1;
		while(N<n) N*=2;
		val .assign(N*2,val_t::e());
		lazy.assign(N*2,opr_t::e());
	}
	void init(const vector<val_t>& vc){
		int n = vc.size();
		N=1;
		while(N<n) N*=2;
		val .assign(N*2,val_t::e());
		rep(i,n) val[i+N] = vc[i];
		for(int i=N-1;i>0;i--) val[i] = val[i*2] + val[i*2+1];
		lazy.assign(N*2,opr_t::e());
	}
	val_t realvalue(int k,int l,int r){
//		return Handler::act(lazy[k],val[k]);
		return Handler::act(lazy[k],val[k],k,l,r);
	}

	val_t query(int a,int b,int l=0,int r=-1,int k=1){	//query_calc
		if(r==-1) r=N;
		if(b<=l||r<=a) return val_t::e();
		if(a<=l&&r<=b) return realvalue(k,l,r);
		propagate(l,r,k);
		val_t ret = query(a,b,l,(l+r)/2,k*2) + query(a,b,(l+r)/2,r,k*2+1);
		val[k] = realvalue(k*2,l,(l+r)/2) + realvalue(k*2+1,(l+r)/2,r);
		return ret;

	}
//	val_t query_leftassoc(){}
	void update(int a,int b,const opr_t &x,int l=0,int r=-1,int k=1){	//query_update
		if(r==-1) r=N;
		if(b<=l||r<=a) return;
		if(a<=l&&r<=b){
			Handler::setg2fg(x,lazy[k]);
			return;
		}
		propagate(l,r,k);
		update(a,b,x,l,(l+r)/2,k*2);
		update(a,b,x,(l+r)/2,r,k*2+1);
		val[k] = realvalue(k*2,l,(l+r)/2) + realvalue(k*2+1,(l+r)/2,r);
	}
	void propagate(int l,int r,int k){	//opr_child -> opr_parent * opr_child		parent after child
		Handler::setg2fg(lazy[k],lazy[k*2  ]);
		Handler::setg2fg(lazy[k],lazy[k*2+1]);
		lazy[k] = opr_t::e();
	}
};

struct handler{
	struct val_t{
		int x;
		int s;
		val_t(){*this = e();}
		val_t(int x,int s):x(x),s(s){}

		const static val_t e(){
			return val_t(0,0);
		}
		val_t operator+(const val_t &r) const {
			return val_t(x+r.x,s+r.s);
		}
		friend ostream& operator<<(ostream& o,const val_t& d){return o<<d.x;}
	};

	struct opr_t{
		bool x;
		opr_t(){*this = e();}
		opr_t(bool x):x(x){}

		const static opr_t e(){
			return opr_t(false);
		}
		friend ostream& operator<<(ostream& o,const opr_t& d){return o<<d.x;}
	};

	/*
		もしコピーコストとかが気になって,しかも楽に書けるならsetg2fgを直接書く
		そうじゃないなら g = getfg(f,g)
	*/
	static void setg2fg(const opr_t &f, opr_t &g){	//g -> fg		f after g
		if(f.x) g.x = !g.x;
	}
	static val_t act(const opr_t &f, const val_t &v,int k,int l,int r){
		if(f.x) return val_t(v.s-v.x,v.s);
		else return v;
	}
};
using val_t = handler::val_t;
using opr_t = handler::opr_t;

int N,Q;
vector<vector<int>> G;

vector<int> v2l,v2r;
int I;

void dfs(int v){
	v2l[v] = I++;
	for(int u:G[v]) dfs(u);
	v2r[v] = I;
}

int main(){
	cin>>N>>Q;
	G.resize(N);
	v2l.resize(N);
	v2r.resize(N);
	rep1(i,N-1){
		int p;
		cin>>p;
		p--;
		G[p].pb(i);
	}
	vector<bool> v2is1(N);
	rep(v,N){
		char c;
		cin>>c;
		v2is1[v] = c=='G';
	}
	dfs(0);

	vector<val_t> vc(N);

	rep(v,N){
		int l = v2l[v];
		if(v2is1[v]){
			vc[l] = val_t(1,1);
		}else{
			vc[l] = val_t(0,1);
		}
	}
	segtree_lazy<handler> seg(vc);

	rep(qt,Q){
		int v;
		cin>>v;
		v--;
		int l = v2l[v], r = v2r[v];
		seg.update(l,r,opr_t(true));
		int g = seg.query(0,N).x;
		int w = N-g;
		if(g>w){
			puts("broccoli");
		}else{
			puts("cauliflower");
		}
	}
}



Measured memory_bytes: 15180