#include <cstdio>
#include <set>

using namespace std;

const int MAXN = 1E5 + 10, MAXM = 1E5 + 10;
const int MAXD = 30;
const int MAXNN = MAXN + MAXM;

struct Node{
	int ms, c;
	Node *ch[2];
	set<int> *s;
}pool[MAXNN * MAXD + MAXN];

Node *cntNode = pool;

Node* getNode(){
	cntNode->ms = MAXN;
	cntNode->c = 0;
	cntNode->ch[0] = cntNode->ch[1] = NULL;
	cntNode->s = NULL;
	return cntNode++;
}

void clear(){
	for (Node *p = pool; p < cntNode; ++p)
		if (p->s != NULL)
			delete p->s;
	cntNode = pool;
}

struct Trie{
	Node *T;

	void build(){
		T = getNode();
	}

	void insert(int sub, int num){
		int k = 1 << MAXD - 1, i;
		Node *u = T;

		for (; k; k >>= 1){
			i = !!(num & k);
			if (u->ch[i] == NULL)
				u->ch[i] = getNode();
			u = u->ch[i];
			++(u->c);
			u->ms = min(u->ms, sub);
		}

		if (u->s == NULL){
			u->s = new set<int>;
		}
		u->s->insert(sub);
	}

	void _erase(Node *u, int sub, int num, int k){
		if (k == 0){
			u->s->erase(sub);
			u->ms = *(u->s->begin());
			return;
		}
		int i = !!(num & k);
		if (--(u->ch[i]->c) == 0)
			u->ch[i] = NULL;
		else
			_erase(u->ch[i], sub, num, k >> 1);
		u->ms = min(u->ch[i] ? u->ch[i]->ms : MAXN, u->ch[!i] ? u->ch[!i]->ms : MAXN);
	}

	void erase(int sub, int num){
		_erase(T, sub, num, 1 << MAXD - 1);
	}

	int query(int sub, int num){
		int k = 1 << MAXD - 1, i;
		int ret = 0;
		Node *u = T;
		for (; k; k >>= 1){
			i = !(num & k);
			if (u->ch[i] != NULL && u->ch[i]->ms <= sub){;
				u = u->ch[i];
				ret |= k;
			}
			else
				u = u->ch[!i];
		}
		return ret;
	}
}trie[MAXN];

int n, m;
int num[MAXN];

struct Edge{
	int v;
	Edge *next;
}e[MAXN << 1];

Edge *edgeCnt, *E[MAXN];

void edgeInit(int n){
	edgeCnt = e;
	for (int i = 1; i <= n; ++i)
		E[i] = NULL;
}

inline void addEdge(int u, int v){
	edgeCnt->v = v;
	edgeCnt->next = E[u];
	E[u] = edgeCnt++;
}

struct HeavyLightDescomposition{
	static const int N = MAXN;

	int n;
	int fa[N], dep[N], size[N];
	int seg[N], idx[N];
	int cnt, low[N], top[N], len[N];

	void DFS(int u){
		int s = 0, v;
		size[u] = 1;
		for (Edge *p = E[u]; p; p = p->next)
			if ((v = p->v) != fa[u]){
				fa[v] = u;
				dep[v] = dep[u] + 1;
				DFS(v);
				size[u] += size[v];
				if (size[s] < size[v])
					s = v;
			}
		seg[u] = s ? seg[s] : cnt;
		idx[u] = s ? idx[s] + 1 : 1;
		if (!s)
			low[cnt++] = u;
		top[seg[u]] = u;
		len[seg[u]] = idx[u];
	}

	void build(int tn){
		n = tn;
		cnt = size[0] = 0;
		fa[1] = dep[1] = 0;
		DFS(1);

		for (int i = 0; i < cnt; ++i)
			trie[i].build();
		for (int i = 1; i <= n; ++i)
			trie[seg[i]].insert(i, num[i]);
	}

	void update(int u){
		trie[seg[u]].erase(u, num[u]);
		scanf("%d", &num[u]);
		trie[seg[u]].insert(u, num[u]);
	}

	int query(int u){
		int ret = 0, v = u;
		while (v){
			ret = max(ret, trie[seg[v]].query(v, num[u]));
			v = fa[top[seg[v]]];
		}
		return ret;
	}
}HLD;

int main(){
	int cas;
	scanf("%d", &cas);
	while (cas--){
		scanf("%d%d", &n, &m);
		edgeInit(n);
		for (int t, i = 2; i <= n; ++i){
			scanf("%d", &t);
			addEdge(i, t);
			addEdge(t, i);
		}
		for (int i = 1; i <= n; ++i)
			scanf("%d", &num[i]);
		
		HLD.build(n);

		int com, a;
		for (int i = 0; i < m; ++i){
			scanf("%d%d", &com, &a);
			if (com == 0)
				HLD.update(a);
			else
				printf("%d\n", HLD.query(a));
		}
		clear();
	}
	return 0;
}
