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>
template <typename T>
inline T max(T a, T b) {
  return a > b ? a : b;
}
template <typename T>
inline T min(T a, T b) {
  return a < b ? a : b;
}
template <typename T>
inline T abs(T a) {
  return a > 0 ? a : -a;
}
template <typename T>
inline bool repr(T &a, T b) {
  return a < b ? a = b, 1 : 0;
}
template <typename T>
inline bool repl(T &a, T b) {
  return a > b ? a = b, 1 : 0;
}
template <typename T>
inline T gcd(T a, T b) {
  T t;
  if (a < b) {
    while (a) {
      t = a;
      a = b % a;
      b = t;
    }
    return b;
  } else {
    while (b) {
      t = b;
      b = a % b;
      a = t;
    }
    return a;
  }
}
template <typename T>
inline T sqr(T x) {
  return x * x;
}
struct Cg {
  inline char operator()() { return getchar(); }
};
struct Cp {
  inline void operator()(char x) { putchar(x); }
};
inline bool IS(char x) { return x == 10 || x == 13 || x == ' '; }
template <typename T>
struct Fr {
  T P;
  inline Fr &operator,(int &x) {
    x = 0;
    unsigned char t = P();
    while ((t < '0' || t > '9') && t != '-') t = P();
    bool f = 0;
    if (t == '-') t = P(), f = 1;
    x = t - '0';
    for (t = P(); t >= '0' && t <= '9'; t = P()) x = x * 10 + t - '0';
    if (f) x = -x;
    return *this;
  }
  inline operator int() {
    int x;
    *this, x;
    return x;
  }
  inline Fr &operator,(long long &x) {
    x = 0;
    unsigned char t = P();
    while ((t < '0' || t > '9') && t != '-') t = P();
    bool f = 0;
    if (t == '-') t = P(), f = 1;
    x = t - '0';
    for (t = P(); t >= '0' && t <= '9'; t = P()) x = x * 10 + t - '0';
    if (f) x = -x;
    return *this;
  }
  inline operator long long() {
    long long x;
    *this, x;
    return x;
  }
  inline Fr &operator,(char &x) {
    for (x = P(); IS(x); x = P())
      ;
    return *this;
  }
  inline operator char() {
    char x;
    *this, x;
    return x;
  }
  inline Fr &operator,(char *x) {
    char t = P();
    for (; IS(t); t = P())
      ;
    if (~t) {
      for (; !IS(t) && ~t; t = P()) *x++ = t;
    }
    *x++ = 0;
    return *this;
  }
  inline Fr &operator,(double &x) {
    x = 0;
    unsigned char t = P();
    while ((t < '0' || t > '9') && t != '-') t = P();
    bool f = 0;
    if (t == '-') t = P(), f = 1;
    x = t - '0';
    for (t = P(); t >= '0' && t <= '9'; t = P()) x = x * 10 + t - '0';
    if (t == '.') {
      double u = 0.1;
      for (t = P(); t >= '0' && t <= '9'; t = P(), u *= 0.1) x += u * (t - '0');
    }
    if (f) x = -x;
    return *this;
  }
  inline operator double() {
    double x;
    *this, x;
    return x;
  }
  inline Fr &operator,(long double &x) {
    x = 0;
    unsigned char t = P();
    while ((t < '0' || t > '9') && t != '-') t = P();
    bool f = 0;
    if (t == '-') t = P(), f = 1;
    x = t - '0';
    for (t = P(); t >= '0' && t <= '9'; t = P()) x = x * 10 + t - '0';
    if (t == '.') {
      double u = 0.1;
      for (t = P(); t >= '0' && t <= '9'; t = P(), u *= 0.1) x += u * (t - '0');
    }
    if (f) x = -x;
    return *this;
  }
  inline operator long double() {
    long double x;
    *this, x;
    return x;
  }
  inline Fr &operator,(unsigned int &x) {
    x = 0;
    unsigned char t = P();
    while (t < '0' || t > '9') t = P();
    x = t - '0';
    for (t = P(); t >= '0' && t <= '9'; t = P()) x = x * 10 + t - '0';
    return *this;
  }
  inline operator unsigned int() {
    unsigned int x;
    *this, x;
    return x;
  }
  inline Fr &operator,(unsigned long long &x) {
    x = 0;
    unsigned char t = P();
    while (t < '0' || t > '9') t = P();
    x = t - '0';
    for (t = P(); t >= '0' && t <= '9'; t = P()) x = x * 10 + t - '0';
    return *this;
  }
  inline operator unsigned long long() {
    unsigned long long x;
    *this, x;
    return x;
  }
};
Fr<Cg> in;
template <typename T>
struct Fw {
  T P;
  inline Fw &operator,(int x) {
    if (x) {
      if (x < 0) P('-'), x = -x;
      unsigned char s[10], c = 0;
      while (x) s[c++] = x % 10 + '0', x /= 10;
      while (c--) P(s[c]);
    } else
      P('0');
    return *this;
  }
  inline Fw &operator()(int x) {
    if (x) {
      if (x < 0) P('-'), x = -x;
      unsigned char s[10], c = 0;
      while (x) s[c++] = x % 10 + '0', x /= 10;
      while (c--) P(s[c]);
    } else
      P('0');
    return *this;
  }
  inline Fw &operator,(unsigned int x) {
    if (x) {
      unsigned char s[10], c = 0;
      while (x) s[c++] = x % 10 + '0', x /= 10;
      while (c--) P(s[c]);
    } else
      P('0');
    return *this;
  }
  inline Fw &operator()(unsigned int x) {
    if (x) {
      unsigned char s[10], c = 0;
      while (x) s[c++] = x % 10 + '0', x /= 10;
      while (c--) P(s[c]);
    } else
      P('0');
    return *this;
  }
  inline Fw &operator,(long long x) {
    if (x) {
      if (x < 0) P('-'), x = -x;
      unsigned char s[19], c = 0;
      while (x) s[c++] = x % 10 + '0', x /= 10;
      while (c--) P(s[c]);
    } else
      P('0');
    return *this;
  }
  inline Fw &operator()(long long x) {
    if (x) {
      if (x < 0) P('-'), x = -x;
      unsigned char s[19], c = 0;
      while (x) s[c++] = x % 10 + '0', x /= 10;
      while (c--) P(s[c]);
    } else
      P('0');
    return *this;
  }
  inline Fw &operator,(unsigned long long x) {
    if (x) {
      unsigned char s[20], c = 0;
      while (x) s[c++] = x % 10 + '0', x /= 10;
      while (c--) P(s[c]);
    } else
      P('0');
    return *this;
  }
  inline Fw &operator()(unsigned long long x) {
    if (x) {
      unsigned char s[20], c = 0;
      while (x) s[c++] = x % 10 + '0', x /= 10;
      while (c--) P(s[c]);
    } else
      P('0');
    return *this;
  }
  inline Fw &operator,(char x) {
    P(x);
    return *this;
  }
  inline Fw &operator()(char x) {
    P(x);
    return *this;
  }
  inline Fw &operator,(const char *x) {
    while (*x) P(*x++);
    return *this;
  }
  inline Fw &operator()(const char *x) {
    while (*x) P(*x++);
    return *this;
  }
  inline Fw &operator()(double x, int y) {
    if (y) {
      double t = 0.5;
      for (int i = y; i--;) t *= 0.1;
      if (x >= 0)
        x += t;
      else
        x -= t, P('-');
      *this, (long long)(abs(x));
      P('.');
      if (x < 0) x = -x;
      while (y--) {
        x *= 10;
        x -= floor(x * 0.1) * 10;
        P(((int)x) % 10 + '0');
      }
    } else if (x >= 0)
      *this, (long long)(x + 0.5);
    else
      *this, (long long)(x - 0.5);
    ;
    return *this;
  }
  inline Fw &operator()(long double x, int y) {
    if (y) {
      double t = 0.5;
      for (int i = y; i--;) t *= 0.1;
      if (x >= 0)
        x += t;
      else
        x -= t, P('-');
      *this, (long long)(abs(x));
      P('.');
      if (x < 0) x = -x;
      while (y--) {
        x *= 10;
        x -= floor(x * 0.1) * 10;
        P(((int)x) % 10 + '0');
      }
    } else if (x >= 0)
      *this, (long long)(x + 0.5);
    else
      *this, (long long)(x - 0.5);
    ;
    return *this;
  }
};
Fw<Cp> out;
const int N = 100007;
std::vector<int> p[N];
int n, m, idm, fa[N], dep[N], sz[N], ws[N], top[N], id[N], idr[N], ir[N], bv[N];
inline void dfs(int x) {
  sz[x] = 1;
  int y = 0;
  for (__typeof((p[x]).end()) i = (p[x]).begin(); i != (p[x]).end(); ++i) {
    dfs(*i);
    sz[x] += sz[*i];
    if (sz[*i] > y) y = sz[*i], ws[x] = *i;
  }
}
inline void dfs2(int x, int y) {
  top[x] = y;
  id[x] = ++idm;
  if (ws[x]) dfs2(ws[x], y);
  for (__typeof((p[x]).end()) i = (p[x]).begin(); i != (p[x]).end(); ++i)
    if (*i != ws[x]) dfs2(*i, *i);
  idr[x] = idm;
}
struct node {
  int mi, ui, ua, tag;
} f[262333];
inline void st(int x, int v) {
  f[x].mi += v;
  f[x].tag += v;
}
inline void pd(int x) {
  if (f[x].tag) {
    st(x << 1, f[x].tag);
    st(x << 1 | 1, f[x].tag);
    f[x].tag = 0;
  }
}
inline void pu(int x) {
  f[x].mi = min(f[x << 1].mi, f[x << 1 | 1].mi);
  f[x].ui = min(f[x << 1].ui, f[x << 1 | 1].ui);
  f[x].ua = max(f[x << 1].ua, f[x << 1 | 1].ua);
}
inline void build(int x, int l, int r) {
  if (l == r)
    f[x].mi = bv[l];
  else {
    int t = (l + r) >> 1;
    build(x << 1, l, t);
    build(x << 1 | 1, t + 1, r);
    pu(x);
  }
}
inline void _mod(int x, int l, int r, int ql, int qr, int v) {
  if (l >= ql && r <= qr) return st(x, v);
  int t = (l + r) >> 1;
  pd(x);
  if (ql <= t) _mod(x << 1, l, t, ql, qr, v);
  if (qr > t) _mod(x << 1 | 1, t + 1, r, ql, qr, v);
  pu(x);
}
inline void mod(int x, int l, int r, int ql, int qr, int v) {
  if (ql <= qr) _mod(x, l, r, ql, qr, v);
}
inline void modu(int x, int l, int r, int p, int v) {
  if (l == r) {
    f[x].ui += v;
    f[x].ua += v;
    return;
  }
  int t = (l + r) >> 1;
  pd(x);
  if (p <= t)
    modu(x << 1, l, t, p, v);
  else
    modu(x << 1 | 1, t + 1, r, p, v);
  pu(x);
}
int qa;
inline void _qry(int x, int l, int r, int ql, int qr) {
  if (l >= ql && r <= qr) {
    repl(qa, f[x].mi);
    return;
  }
  int t = (l + r) >> 1;
  pd(x);
  if (ql <= t) _qry(x << 1, l, t, ql, qr);
  if (qr > t) _qry(x << 1 | 1, t + 1, r, ql, qr);
}
inline int qry(int x, int l, int r, int ql, int qr) {
  qa = 1e9;
  _qry(x, l, r, ql, qr);
  return qa;
}
inline int qryu(int x, int l, int r, int p) {
  if (l == r) return f[x].ua;
  int t = (l + r) >> 1;
  if (p <= t) return qryu(x << 1, l, t, p);
  return qryu(x << 1 | 1, t + 1, r, p);
}
std::pair<int, int> ru[N];
int rc;
inline void rst(int x, int l, int r, int ql, int qr) {
  if (f[x].ua == 0 && f[x].ui == 0) return;
  if (l == r) {
    ru[rc++] = std::make_pair(ir[l], f[x].ua);
    f[x].ua = f[x].ui = 0;
    return;
  }
  int t = (l + r) >> 1;
  pd(x);
  if (ql <= t) rst(x << 1, l, t, ql, qr);
  if (qr > t) rst(x << 1 | 1, t + 1, r, ql, qr);
  pu(x);
}
int main() {
  in, n, m;
  for (int i = 2, iend = n; i <= iend; i++) in, fa[i];
  for (int i = 2, iend = n; i <= iend; i++) p[fa[i]].push_back(i);
  dfs(1);
  dfs2(1, 1);
  for (int i = 1, iend = n; i <= iend; i++) ir[id[i]] = i;
  for (int i = 2, iend = n; i <= iend; i++) dep[i] = dep[fa[i]] + 1;
  for (int i = 1, iend = n; i <= iend; i++) bv[id[i]] = -dep[i];
  build(1, 1, n);
  while (m--) {
    int op, x;
    in, op, x;
    if (op == 1) {
      modu(1, 1, n, id[x], 1);
      mod(1, 1, n, id[x] + 1, idr[x], 1);
    } else if (op == 2) {
      rc = 0;
      rst(1, 1, n, id[x], idr[x]);
      for (int i = 0, iend = rc; i < iend; i++)
        mod(1, 1, n, id[ru[i].first] + 1, idr[ru[i].first], -ru[i].second);
      int y = x, r = 1e9;
      while (y) {
        repl(r, qry(1, 1, n, id[top[y]], id[y]));
        y = fa[top[y]];
      }
      r -= qry(1, 1, n, id[x], id[x]);
      modu(1, 1, n, id[x], r);
      mod(1, 1, n, id[x] + 1, idr[x], r);
    } else {
      int v = qry(1, 1, n, id[x], id[x]) + qryu(1, 1, n, id[x]), r = v;
      while (x) {
        repl(r, qry(1, 1, n, id[top[x]], id[x]));
        x = fa[top[x]];
      }
      out, r < v ? "black" : "white", '\n';
    }
  }
}