#include <stdio.h>
#include <cmath>
#include <algorithm>
#include <cfloat>
#include <stack>
#include <queue>
#include <vector>
#include <string>
#include <iostream>
#include <set>
#include <map>
#include <time.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;

#define NUM 100001

int N = 1;
int index = 0;
int num_W[1000000],num_G[1000000],reverse_count[1000000];
int LEFT[NUM],RIGHT[NUM];
vector<int> G[NUM];

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

void add(int loc,char ch){
	loc += N-1;

	if(ch == 'W'){
		num_W[loc] += 1;
	}else{
		num_G[loc] += 1;
	}
	while(loc > 0){
		loc = (loc-1)/2;
		if(ch == 'W'){
			num_W[loc] = num_W[2*loc+1]+num_W[2*loc+2];
		}else{
			num_G[loc] = num_G[2*loc+1]+num_G[2*loc+2];
		}
	}
}

//指定された区間のデータを反転する関数
void update(int update_left,int update_right,int node_id,int node_left,int node_right){
	if(update_right < node_left || update_left > node_right)return; //範囲外なら何もしない
	else if(update_left <= node_left && update_right >= node_right){ //このノードのカバー区間が、更新区間の部分区間である場合
		reverse_count[node_id]++;
		swap(num_W[node_id],num_G[node_id]); //WとGの個数を反転
	}else{
		//このノードのカバー範囲と更新範囲に部分的な重なりがある場合

		//子の一部が変更されるため、まずは、現在自分が★蓄積していた(子供に伝えていなかった)★反転情報を子に投げる
		if(reverse_count[node_id]%2 == 1){ //現在の値を、更新命令という形で下に投げる。更新範囲に注意(node_left,node_rightの区間を更新)

			update(node_left,node_right,2*node_id+1,node_left,(node_left+node_right)/2); //★★更新区間が、node_left～node_rightであることに注意★★
			update(node_left,node_right,2*node_id+2,(node_left+node_right)/2+1,node_right);
		}
		reverse_count[node_id] = 0;
		//改めて今回のクエリを投げる
		update(update_left,update_right,2*node_id+1,node_left,(node_left+node_right)/2);
		update(update_left,update_right,2*node_id+2,(node_left+node_right)/2+1,node_right);

		//★★子にクエリを投げた結果、このノードの以下の集計が変わるので、ボトムアップ的に再帰的に計算する
		num_W[node_id] = num_W[2*node_id+1]+num_W[2*node_id+2];
		num_G[node_id] = num_G[2*node_id+1]+num_G[2*node_id+2];
	}
}

//Wの総数を返却する関数
int getSum(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 0;
	}else if(search_left <= node_left && search_right >= node_right){

		//★★仮にupdateで一様性が壊れたなら、再び計算をし直しているはずなので、このノードの値を返却すればOK★★
		return num_W[node_id];

	}else{ //結局、少なくとも一部検索区間がかぶっていて、このノードが値を持っていたら、このノードがカバーする区間の値は
		int left = getSum(search_left,search_right,2*node_id+1,node_left,(node_left+node_right)/2);
		int right = getSum(search_left,search_right,2*node_id+2,(node_left+node_right)/2+1,node_right);
		return left+right;
	}
}


//オイラーツアーで、ノードのカバー範囲を計算する
void euler_tour(int node_id,int pre_node){
	LEFT[node_id] = index++;

	for(int i = 0; i < G[node_id].size(); i++){
		if(G[node_id][i] == pre_node)continue;
		euler_tour(G[node_id][i],node_id);
	}
	RIGHT[node_id] = index++;
}

int main(){

	int V,Q;
	scanf("%d %d",&V,&Q);

	int parent_id;
	for(int i = 2; i <= V; i++){
		scanf("%d",&parent_id);
		parent_id--;
		G[parent_id].push_back(i-1); //0オリジンにする
		G[i-1].push_back(parent_id);
	}

	euler_tour(0,-1);

	int first_N = RIGHT[0]+1; //セグ木における最下層のノードは、最低RIGHT[0]+1個あれば良い(+1は0オリジンのため)

	init(first_N);

	for(int i = 0; i <= 2*N-2; i++){
		num_W[i] = 0;
		num_G[i] = 0;
		reverse_count[i] = 0;
	}

	char buf[2];
	for(int i = 0; i < V; i++){
		scanf("%s",buf);
		if(buf[0] == 'G'){
			add(LEFT[i],'G');
		}else{
			add(LEFT[i],'W');
		}
	}

	int node_id;
	int sum_W,sum_G;

	for(int loop = 0; loop < Q; loop++){
		scanf("%d",&node_id);
		node_id--;

		update(LEFT[node_id],RIGHT[node_id],0,0,N-1);
		sum_W = getSum(0,N-1,0,0,N-1);
		sum_G = V-sum_W;

		if(sum_G > sum_W){
			printf("broccoli\n");
		}else{
			printf("cauliflower\n");
		}
	}

	return 0;
}




Measured memory_bytes: 20252