CCCPaste

3055e60e8cfbe

//Слава Україні, Героям слава

#include <bits/stdc++.h>

using namespace std;

struct seg_tree {
//modify accordingly
int n;
vector<unsigned long long> v, lz, st;
void build() {
build(1, 1, n);
}
void build(int p, int l, int r) {
if(l == r) {
st[p] = v[l];
return;
}
build(2 * p, l, (l + r) >> 1);
build(2 * p + 1, ((l + r) >> 1) + 1, r);
st[p] = st[2 * p] + st[2 * p + 1];
}
seg_tree(int n_ = 1) {
n = n_;
lz.resize(4 * n);
st.resize(4 * n);
v.resize(n + 1);
build();
}
seg_tree(vector<unsigned long long> &v_) {
v = v_;
n = v.size();
n--;
lz.resize(4 * n);
st.resize(4 * n);
build();
}
void push(int p, int l, int r) {
if(lz[p]) {
st[p] = (r - l + 1) * lz[p];
if(l != r) {
lz[2 * p] = lz[p];
lz[2 * p + 1] = lz[p];
}
lz[p] = 0;
}
}
unsigned long long query(int i, int j) {
return query(i, j, 1, 1, n);
}
unsigned long long query(int i, int j, int p, int l, int r) {
push(p, l, r);
if(l > j or r < i) {
return 0;
}
if(l >= i and j >= r) {
return st[p];
}
return query(i, j, 2 * p, l, (l + r) >> 1) + query(i, j, 2 * p + 1, ((l + r) >> 1) + 1, r);
}
void update(int i, int j, unsigned long long v) {
update(i, j, v, 1, 1, n);
}
void update(int i, int j, unsigned long long v, int p, int l, int r) {
push(p, l, r);
if(l > j or r < i) {
return;
}
if(l >= i and j >= r) {
lz[p] = v;
push(p, l, r);
return;
}
update(i, j, v, 2 * p, l, (l + r) >> 1);
update(i, j, v, 2 * p + 1, ((l + r) >> 1) + 1, r);
st[p] = st[2 * p] + st[2 * p + 1];
}
};

template <bool EDGE> struct HLD {
vector<vector<int>> g1;
vector<vector<pair<int, int>>> g2;
vector<int> pos, sz, par, h;
vector<unsigned long long> v, w, sobe;
seg_tree seg;
int t;
HLD(int n) {
if(EDGE) {
g2.resize(n + 3);
} else {
g1.resize(n + 3);
}
pos.resize(n + 3); sz.resize(n + 3); par.resize(n + 3);
if(EDGE) {
sobe.resize(n + 3);
} else {
w.resize(n + 3);
}
h.resize(n + 3); v.resize(n + 3);
}
void build_hld(int k, int p = -1, int f = 1) {
v[pos[k] = t++] = (EDGE ? sobe : w)[k]; sz[k] = 1;
for(int i = 0; i < (int)(EDGE ? g2[k].size() : g1[k].size()); i++) {
if((EDGE and g2[k][i].first != p) or (!EDGE and g1[k][i] != p)) {
if(EDGE) {
sobe[g2[k][i].first] = g2[k][i].second; par[g2[k][i].first] = k;
h[g2[k][i].first] = (g2[k][i] == g2[k][0] ? h[k] : g2[k][i].first);
build_hld(g2[k][i].first, k, f); sz[k] += sz[g2[k][i].first];
if(sz[g2[k][i].first] > sz[g2[k][0].first] or g2[k][0].first == p) {
swap(g2[k][i], g2[k][0]);
}
} else {
par[g1[k][i]] = k;
h[g1[k][i]] = (g1[k][i] == g1[k][0] ? h[k] : g1[k][i]);
build_hld(g1[k][i], k, f);
sz[k] += sz[g1[k][i]];
if(sz[g1[k][i]] > sz[g1[k][0]] or g1[k][0] == p) {
swap(g1[k][i], g1[k][0]);
}
}
}
}
if(p * f == -1) {
t = 1;
build_hld(h[k] = k, -1, 0);
}
}
void add(int a, int b) {
g1[a].push_back(b);
g1[b].push_back(a);
}
void add(int a, int b, int x) {
g2[a].push_back({b, x});
g2[b].push_back({a, x});
}
void build(int root = 1) {
t = 1;
build_hld(root);
seg = seg_tree(v);
}
unsigned long long query_path(int a, int b) {
if(EDGE and a == b) return 0;
if(pos[a] < pos[b]) swap(a, b);
if(h[a] == h[b]) return seg.query(pos[b] + EDGE, pos[a]);
return seg.query(pos[h[a]], pos[a]) + query_path(par[h[a]], b);
}
void update_path(int a, int b, unsigned long long x) {
if(EDGE and a == b) return;
if(pos[a] < pos[b]) swap(a, b);
if(h[a] == h[b]) {
seg.update(pos[b] + EDGE, pos[a], x);
return;
}
seg.update(pos[h[a]], pos[a], x);
update_path(par[h[a]], b, x);
}
unsigned long query_subtree(int a) {
if(EDGE and sz[a] == 1) return 0;
return seg.query(pos[a] + EDGE, pos[a] + sz[a] - 1);
}
void update_subtree(int a, int x) {
if(EDGE and sz[a] == 1) return;
seg.update(pos[a] + EDGE, pos[a] + sz[a] - 1, x);
}
};

using ull = unsigned long long;

random_device rd;
mt19937 gen(rd());
uniform_int_distribution<ull> distrib(0, ULLONG_MAX);

int main() {
ios_base::sync_with_stdio(false);
cin.tie(nullptr);
int t;
cin >> t;
while(t--) {
int n, q;
cin >> n >> q;
vector<unsigned long long> v(n + 3);
vector<unsigned long long> hsh(n + 1), perm(n + 1);
set<unsigned long long> st;
for(int i = 1; i <= n; i++) {
cin >> v[i];
hsh[i] = distrib(gen);
perm[i] = perm[i - 1] + hsh[i];
st.insert(perm[i]);
}
HLD<false> hld(n);
for(int i = 1; i <= n; i++) hld.w[i] = hsh[v[i]];
for(int i = 1; i < n; i++) {
int a, b;
cin >> a >> b;
hld.add(a, b);
}
hld.build();
while(q--) {
int t, a, b;
cin >> t >> a >> b;
if(t == 1) {
unsigned long long x = hld.query_path(a, b);
cout << (st.find(x) != st.end() ? "Yes\n" : "No\n");
} else {
hld.update_path(a, a, hsh[b]);
}
}
}
return 0;
}