#vulnerable code 
                                public static void main(String[] args) throws IOException {
        final InputReader in = new InputReader(System.in);
        V = in.readInt();
        final int Q = in.readInt();
        adj = new ArrayList[V + 1];
        for (int i = 1; i <= V; i++) {
            adj[i] = new ArrayList<>();
        }
        val = new int[V + 1];
        for (int i = 1; i <= V; i++) {
            val[i] = in.readInt();
        }
        final Map<Integer, Integer> map = new HashMap<>();
        for (int i = 1; i <= V; i++) {
            if (!map.containsKey(val[i])) {
                map.put(val[i], map.size());
            }
            val[i] = map.get(val[i]);
        }
        final int currVal[] = new int[V + 1];
        System.arraycopy(val, 0, currVal, 0, V + 1);
        final int edges = V - 1;
        for (int i = 0; i < edges; i++) {
            final int u = in.readInt();
            final int v = in.readInt();
            adj[u].add(v);
            adj[v].add(u);
        }
        start = new int[V + 1];
        end = new int[V + 1];
        final int[] eulerTour = new int[2 * (V + 1)];
        level = new int[V + 1];
        marked = new boolean[V + 1];
        DP = new int[log(V) + 1][V + 1];
        parent = new int[V + 1];
        final int block[] = new int[2 * (V + 1)];
        dfs(1, 0, 0, eulerTour);
        binaryLift();
        int numberOfQueries = 0, numberOfUpdates = 0;
        final Query queries[] = new Query[MAX];
        final Update updates[] = new Update[MAX];
        for (int i = 0; i < Q; i++) {
            if (in.readInt() == 1) { // Query
                final int u = in.readInt();
                final int v = in.readInt();
                final Query q;
                if (end[u] < start[v])    // Cousin Nodes
                {
                    q = new Query(end[u], start[v], numberOfUpdates, LCA(u, v), numberOfQueries);
                } else if (start[u] > end[v]) {
                    q = new Query(end[v], start[u], numberOfUpdates, LCA(u, v), numberOfQueries);
                } else            // Ancestors
                {
                    q = new Query(Math.min(start[u], start[v]),
                                  Math.max(start[u], start[v]),
                                  numberOfUpdates,
                                  -1,
                                  numberOfQueries);
                }
                queries[numberOfQueries++] = q;
            } else {
                final int idx = in.readInt();
                int newVal = in.readInt();
                if (!map.containsKey(newVal)) {
                    map.put(newVal, map.size());
                }
                newVal = map.get(newVal);
                updates[numberOfUpdates++] = new Update(idx, newVal, currVal[idx]);
                currVal[idx] = newVal;
            }
        }
        final int BLOCK_SIZE = (int) (Math.pow(2 * V, 2.0 / 3.0) + 1);
        for (int i = 0; i < block.length; i++) {
            block[i] = i / BLOCK_SIZE;
        }
        Arrays.sort(queries, 0, numberOfQueries, (o1, o2) -> {
            if (block[o1.L] != block[o2.L]) {
                return block[o1.L] - block[o2.L];
            } else if (block[o1.R] != block[o2.R]) {
                return block[o1.R] - block[o2.R];
            } else {
                return o1.updatesTillNow - o2.updatesTillNow;
            }
        });
        final int ans[] = new int[numberOfQueries];
        int moLeft = -1, moRight = -1;
        int currentUpdateCount = 0;
        final int[] freq = new int[map.size()];
        for (int i = 0; i < numberOfQueries; i++) {
            final Query query = queries[i];
            while (currentUpdateCount < query.updatesTillNow) {
                final Update update = updates[currentUpdateCount];
                update(update.idx, update.newVal, freq);
                currentUpdateCount++;
            }
            while (currentUpdateCount > query.updatesTillNow) {
                currentUpdateCount--;
                final Update update = updates[currentUpdateCount];
                update(update.idx, update.prevVal, freq);
            }
            while (moLeft < query.L - 1) {
                moLeft++;
                visit(eulerTour[moLeft], freq);
            }
            while (moLeft >= query.L) {
                visit(eulerTour[moLeft], freq);
                moLeft--;
            }
            while (moRight < query.R) {
                moRight++;
                visit(eulerTour[moRight], freq);
            }
            while (moRight > query.R) {
                visit(eulerTour[moRight], freq);
                moRight--;
            }
            if (query.LCA != -1) {
                visit(query.LCA, freq);
            }
            ans[query.id] = distinctCount;
            if (query.LCA != -1) {
                visit(query.LCA, freq);
            }
        }
        final StringBuilder stringBuilder = new StringBuilder();
        for (final int a : ans) {
            stringBuilder.append(a).append('\n');
        }
        System.out.println(stringBuilder);
    } 
                            #location 18 
                            #vulnerability type NULL_DEREFERENCE
#fixed code
                                public static void main(String[] args) throws IOException {
        final InputReader in = new InputReader(System.in);
        V = in.readInt();
        final int Q = in.readInt();
        adj = new ArrayList[V + 1];
        for (int i = 1; i <= V; i++) {
            adj[i] = new ArrayList<>();
        }
        vertices = new int[V + 1];
        for (int i = 1; i <= V; i++) {
            vertices[i] = in.readInt();
        }
        final Map<Integer, Integer> map = new HashMap<>();
        for (int i = 1; i <= V; i++) {
            map.putIfAbsent(vertices[i], map.size());
            vertices[i] = map.get(vertices[i]);
        }
        final int verticesCopy[] = new int[V + 1];
        System.arraycopy(vertices, 0, verticesCopy, 0, V + 1);
        final int edges = V - 1;
        for (int i = 0; i < edges; i++) {
            final int u = in.readInt();
            final int v = in.readInt();
            adj[u].add(v);
            adj[v].add(u);
        }
        start = new int[V + 1];
        end = new int[V + 1];
        final int[] eulerTour = new int[2 * (V + 1)];
        level = new int[V + 1];
        marked = new boolean[V + 1];
        DP = new int[log(V) + 1][V + 1];
        parent = new int[V + 1];
        dfs(1, 0, 0, eulerTour);
        findAncestorsAtEachLevel();
        int numberOfQueries = 0, numberOfUpdates = 0;
        final Query queries[] = new Query[Q];
        final Update updates[] = new Update[Q];
        for (int i = 0; i < Q; i++) {
            if (in.readInt() == 1) {
                final int u = in.readInt();
                final int v = in.readInt();
                final Query q;
                if (start[v] > end[u]) {
                    q = new Query(end[u], start[v], numberOfUpdates, LCA(u, v), numberOfQueries);
                } else if (start[u] > end[v]) {
                    q = new Query(end[v], start[u], numberOfUpdates, LCA(u, v), numberOfQueries);
                } else {
                    q = new Query(Math.min(start[u], start[v]),
                                  Math.max(start[u], start[v]),
                                  numberOfUpdates,
                                  -1,
                                  numberOfQueries);
                }
                queries[numberOfQueries++] = q;
            } else {
                final int idx = in.readInt();
                int newVal = in.readInt();
                map.putIfAbsent(newVal, map.size());
                newVal = map.get(newVal);
                updates[numberOfUpdates++] = new Update(idx, newVal, verticesCopy[idx]);
                verticesCopy[idx] = newVal;
            }
        }
        final int BLOCK_SIZE = (int) (Math.pow(2 * V, 2.0 / 3.0) + 1);
        Arrays.sort(queries, 0, numberOfQueries, (first, second) -> {
            if (first.L / BLOCK_SIZE != second.L / BLOCK_SIZE) {
                return first.L / BLOCK_SIZE - second.L / BLOCK_SIZE;
            } else if (first.R / BLOCK_SIZE != second.R / BLOCK_SIZE) {
                return first.R / BLOCK_SIZE - second.R / BLOCK_SIZE;
            } else {
                return first.updatesTillNow - second.updatesTillNow;
            }
        });
        final int ans[] = new int[numberOfQueries];
        int moLeft = -1, moRight = -1;
        int currentUpdateCount = 0;
        final int[] frequency = new int[map.size()];
        for (int i = 0; i < numberOfQueries; i++) {
            final Query query = queries[i];
            while (currentUpdateCount < query.updatesTillNow) {
                final Update update = updates[currentUpdateCount++];
                update(update.idx, update.newValue, frequency);
            }
            while (currentUpdateCount > query.updatesTillNow) {
                final Update update = updates[--currentUpdateCount];
                update(update.idx, update.previousValue, frequency);
            }
            while (moLeft < query.L - 1) {
                moLeft++;
                visit(eulerTour[moLeft], frequency);
            }
            while (moLeft >= query.L) {
                visit(eulerTour[moLeft], frequency);
                moLeft--;
            }
            while (moRight < query.R) {
                moRight++;
                visit(eulerTour[moRight], frequency);
            }
            while (moRight > query.R) {
                visit(eulerTour[moRight], frequency);
                moRight--;
            }
            if (query.LCA != -1) {
                visit(query.LCA, frequency);
            }
            ans[query.id] = distinctCount;
            if (query.LCA != -1) {
                visit(query.LCA, frequency);
            }
        }
        final StringBuilder stringBuilder = new StringBuilder();
        for (final int a : ans) {
            stringBuilder.append(a).append('\n');
        }
        System.out.println(stringBuilder);
    }