Problem: Abendsen assigned a mission to Juliana. In this mission, Juliana has a rooted tree with n vertices. Vertex number 1 is the root of this tree. Each vertex can be either black or white. At first, all vertices are white. Juliana is asked to process q queries. Each query is one of three types:

  1. If vertex v is white, mark it as black; otherwise, perform this operation on all direct sons of v instead. 
  2. Mark all vertices in the subtree of v (including v) as white. 
  3. Find the color of the i-th vertex. 

<image> An example of operation "1 1" (corresponds to the first example test). The vertices 1 and 2 are already black, so the operation goes to their sons instead.

Can you help Juliana to process all these queries?

Input

The first line contains two integers n and q (2≤ n≤ 10^5, 1≤ q≤ 10^5) — the number of vertices and the number of queries.

The second line contains n-1 integers p_2, p_3, …, p_n (1≤ p_i<i), where p_i means that there is an edge between vertices i and p_i. 

Each of the next q lines contains two integers t_i and v_i (1≤ t_i≤ 3, 1≤ v_i≤ n) — the type of the i-th query and the vertex of the i-th query.

It is guaranteed that the given graph is a tree.

Output

For each query of type 3, print "black" if the vertex is black; otherwise, print "white".

Examples

Input

8 10
1 2 1 2 5 4 5
1 2
3 2
3 1
1 1
1 1
3 5
3 7
3 4
2 2
3 5


Output

black
white
black
white
black
white


Input

8 11
1 1 2 3 3 6 6
1 1
1 1
1 3
3 2
3 4
3 6
3 7
2 3
1 6
3 7
3 6


Output

black
white
black
white
white
black

Note

The first example is shown on the picture below.

<image>

The second example is shown on the picture below.

<image>

Solution (in CPP):

Solution:
#include <bits/stdc++.h>
using namespace std;
template <typename T>
inline bool upmin(T &x, T y) {
  return y < x ? x = y, 1 : 0;
}
template <typename T>
inline bool upmax(T &x, T y) {
  return x < y ? x = y, 1 : 0;
}
const long double pi = acos(-1);
const int oo = 1 << 30;
const long long OO = 1LL << 62;
const int mod = 1e9 + 7;
int qpow(int x, int y) {
  int ans = 1;
  while (y) {
    if (y & 1) ans = 1LL * ans * x % mod;
    x = 1LL * x * x % mod;
    y >>= 1;
  }
  return ans;
}
int gi() {
  int w = 0;
  bool q = 1;
  char c = getchar();
  while ((c < '0' || c > '9') && c != '-') c = getchar();
  if (c == '-') q = 0, c = getchar();
  while (c >= '0' && c <= '9') w = w * 10 + c - '0', c = getchar();
  return q ? w : -w;
}
namespace io {
const int L = (1 << 21) + 1;
char ibuf[L], *iS, *iT, obuf[L], *oS = obuf, *oT = obuf + L - 1, c, st[55];
int f, tp;
inline char getc() {
  return (iS == iT ? (iT = (iS = ibuf) + fread(ibuf, 1, L, stdin),
                      (iS == iT ? EOF : *iS++))
                   : *iS++);
}
inline void flush() {
  fwrite(obuf, 1, oS - obuf, stdout);
  oS = obuf;
}
inline void putc(char x) {
  *oS++ = x;
  if (oS == oT) flush();
}
template <class I>
inline void gi(I &x) {
  for (f = 1, c = (iS == iT ? (iT = (iS = ibuf) + fread(ibuf, 1, L, stdin),
                              (iS == iT ? EOF : *iS++))
                            : *iS++);
       c < '0' || c > '9';
       c = (iS == iT ? (iT = (iS = ibuf) + fread(ibuf, 1, L, stdin),
                       (iS == iT ? EOF : *iS++))
                     : *iS++))
    if (c == '-') f = -1;
  for (x = 0; c <= '9' && c >= '0';
       c = (iS == iT ? (iT = (iS = ibuf) + fread(ibuf, 1, L, stdin),
                       (iS == iT ? EOF : *iS++))
                     : *iS++))
    x = x * 10 + (c & 15);
  x *= f;
}
template <class I>
inline void print(I x) {
  if (!x) putc('0');
  if (x < 0) putc('-'), x = -x;
  while (x) st[++tp] = x % 10 + '0', x /= 10;
  while (tp) putc(st[tp--]);
}
inline void gs(char *s, int &l) {
  for (c = (iS == iT ? (iT = (iS = ibuf) + fread(ibuf, 1, L, stdin),
                       (iS == iT ? EOF : *iS++))
                     : *iS++);
       c < 'a' || c > 'z';
       c = (iS == iT ? (iT = (iS = ibuf) + fread(ibuf, 1, L, stdin),
                       (iS == iT ? EOF : *iS++))
                     : *iS++))
    ;
  for (l = 0; c <= 'z' && c >= 'a';
       c = (iS == iT ? (iT = (iS = ibuf) + fread(ibuf, 1, L, stdin),
                       (iS == iT ? EOF : *iS++))
                     : *iS++))
    s[l++] = c;
  s[l] = 0;
}
inline void ps(const char *s) {
  for (int i = 0, n = strlen(s); i < n; i++) putc(s[i]);
}
struct IOFLUSHER {
  ~IOFLUSHER() { flush(); }
} _ioflusher_;
};  // namespace io
using io::getc;
using io::gi;
using io::gs;
using io::print;
using io::ps;
using io::putc;
int n;
const int N = 1e5 + 100;
struct Tag {
  bool w;
  friend Tag operator+(const Tag &a, const Tag &b) { return (Tag){a.w || b.w}; }
  void clear() { w = 0; }
};
struct Node {
  int sum, suf, siz;
  friend Node operator+(const Node &a, const Node &b) {
    return (Node){a.sum + b.sum, max(a.suf + b.sum, b.suf), a.siz + b.siz};
  }
  Node operator+(const Tag &b) { return b.w ? (Node){-siz, -1, siz} : *this; }
  void init() {
    sum = suf = -1;
    siz = 1;
  }
};
struct tree_devide_to_chain {
  Tag tag[N * 4];
  Node s[N * 4];
  void mark(int i, int l, int r, Tag t) {
    s[i] = s[i] + t;
    tag[i] = tag[i] + t;
  }
  void pushdown(int i, int l, int r) {
    mark((i << 1), l, ((l + r) >> 1), tag[i]);
    mark(((i << 1) | 1), ((l + r) >> 1) + 1, r, tag[i]);
    tag[i].clear();
  }
  void update(int i) { s[i] = s[(i << 1)] + s[((i << 1) | 1)]; }
  void build(int i, int l, int r) {
    if (l == r)
      s[i].init();
    else {
      build((i << 1), l, ((l + r) >> 1));
      build(((i << 1) | 1), ((l + r) >> 1) + 1, r);
      update(i);
    }
  }
  void modify(int i, int l, int r, int L, int R, Tag t) {
    if (L <= l && r <= R)
      mark(i, l, r, t);
    else {
      pushdown(i, l, r);
      if (L <= ((l + r) >> 1)) modify((i << 1), l, ((l + r) >> 1), L, R, t);
      if (((l + r) >> 1) < R)
        modify(((i << 1) | 1), ((l + r) >> 1) + 1, r, L, R, t);
      update(i);
    }
  }
  void modify(int i, int l, int r, int k, Node t) {
    if (l == r)
      s[i] = t;
    else {
      pushdown(i, l, r);
      k <= ((l + r) >> 1) ? modify((i << 1), l, ((l + r) >> 1), k, t)
                          : modify(((i << 1) | 1), ((l + r) >> 1) + 1, r, k, t);
      update(i);
    }
  }
  Node query(int i, int l, int r, int L, int R) {
    if (L <= l && r <= R)
      return s[i];
    else {
      pushdown(i, l, r);
      if (R <= ((l + r) >> 1)) return query((i << 1), l, ((l + r) >> 1), L, R);
      if (((l + r) >> 1) < L)
        return query(((i << 1) | 1), ((l + r) >> 1) + 1, r, L, R);
      return query((i << 1), l, ((l + r) >> 1), L, R) +
             query(((i << 1) | 1), ((l + r) >> 1) + 1, r, L, R);
    }
  }
  int head[N], nxt[N * 2], to[N * 2], tot = 1;
  int fa[N], siz[N], son[N], dep[N], top[N];
  int sa[N], L[N], R[N], cnt;
  void link(int a, int b) {
    to[++tot] = b, nxt[tot] = head[a], head[a] = tot;
    to[++tot] = a, nxt[tot] = head[b], head[b] = tot;
  }
  void dfs1(int k) {
    siz[k] = 1;
    son[k] = 0;
    dep[k] = dep[fa[k]] + 1;
    for (int i = head[k]; i; i = nxt[i])
      if (to[i] != fa[k]) {
        fa[to[i]] = k;
        dfs1(to[i]);
        siz[k] += siz[to[i]];
        if (siz[to[i]] > siz[son[k]]) son[k] = to[i];
      }
  }
  void dfs2(int k) {
    sa[L[k] = ++cnt] = k;
    if (!top[k]) top[k] = k;
    if (son[k]) {
      top[son[k]] = top[k];
      dfs2(son[k]);
      for (int i = head[k]; i; i = nxt[i])
        if (to[i] != fa[k] && to[i] != son[k]) dfs2(to[i]);
    }
    R[k] = cnt;
  }
  int lca(int a, int b) {
    while (top[a] ^ top[b])
      dep[top[a]] > dep[top[b]] ? a = fa[top[a]] : b = fa[top[b]];
    return dep[a] < dep[b] ? a : b;
  }
  void chain_work(int a, int b, Tag c) {
    while (top[a] != top[b])
      if (dep[top[a]] > dep[top[b]]) {
        modify(1, 1, n, L[top[a]], L[a], c);
        a = fa[top[a]];
      } else {
        modify(1, 1, n, L[top[b]], L[b], c);
        b = fa[top[b]];
      }
    if (dep[a] > dep[b])
      modify(1, 1, n, L[b], L[a], c);
    else
      modify(1, 1, n, L[a], L[b], c);
  }
  int chain_query(int k) {
    Node ans = {0, -oo, 0};
    while (k) ans = query(1, 1, n, L[top[k]], L[k]) + ans, k = fa[top[k]];
    return ans.suf;
  }
  void init() {
    dfs1(1);
    cnt = 0;
    dfs2(1);
    build(1, 1, n);
  }
};
tree_devide_to_chain T;
int main() {
  int m, i, k, op, t;
  gi(n), gi(m);
  for (i = 2; i <= n; i++) gi(k), T.link(i, k);
  T.init();
  while (m--) {
    gi(op), gi(k);
    if (op == 1) {
      t = T.query(1, 1, n, T.L[k], T.L[k]).sum;
      T.modify(1, 1, n, T.L[k], (Node){t + 1, t + 1, 1});
    } else if (op == 2) {
      t = max(T.chain_query(T.fa[k]), 0);
      T.modify(1, 1, n, T.L[k], (Node){-t - 1, -t - 1, 1});
      if (T.L[k] != T.R[k]) T.modify(1, 1, n, T.L[k] + 1, T.R[k], (Tag){1});
    } else
      ps(T.chain_query(k) >= 0 ? "black\n" : "white\n");
  }
  return 0;
}