import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.StringTokenizer;

 class HeavyLightNoRecursion {

	segmentTree value[];

	List<Integer>[] tree;
	int[] size;
	int[] parent;
	int[] tin;
	int[] tout;
	int time;
	int[] path;
	int[] pathSize;
	int[] pathPos;
	int[] pathRoot;
	int pathCount;
	int len1;
	int[][] up;


	public HeavyLightNoRecursion(List<Integer>[] tree) {
		this.tree = tree;
		int n = tree.length;

		size = new int[n];
		parent = new int[n];
		tin = new int[n];
		tout = new int[n];
	
		len1 = 1;
		while ((1 << len1) <= n) ++len1;
		up = new int[len1][n];
		
		calcSizeParentTinTout(0);

		path = new int[n];
		pathSize = new int[n];
		pathPos = new int[n];
		pathRoot = new int[n];
		buildPaths(0);

		value=new segmentTree[pathCount];
		for (int i = 0; i < pathCount; i++) {
			int m = pathSize[i];
			
			value[i]=new segmentTree(new long[m]);
		}
	}
	
	class segmentTree
	{
		int n;  // array size
		long t[];

		public segmentTree(long[] arr)
		{
			n=arr.length;
			t=new long[3*n];
			for(int i=0;i<n;i++)
			{
				t[n+i]=arr[i];
			}
			build();
		}
		
		void build() {  // build the tree
			for (int i = n - 1; i > 0; --i) t[i] = Math.max(t[i<<1],t[i<<1|1]);
		}

		void modify(int p, long value) { 
			for (t[p += n] = value; p > 1; p >>= 1) t[p>>1] = Math.max(t[p],t[p^1]);
		}

		long query(int l, int r) {  // sum on interval [l, r)
			long res = 0;
			for (l += n, r += n; l < r; l >>= 1, r >>= 1) {
				if ((l&1)!=0) res=Math.max(res , t[l++]);
				if ((r&1)!=0) res= Math.max(res, t[--r]);
			}
			return res;
		}
	}
	
	int query_up(int u, int v) {
		if(u == v) return 0; 
		
		int uchain, vchain = path[v], ans = -1;
	
		while(true) {
		
			uchain = path[u];
			if(uchain == vchain) {
			
				if(u==v) break;
				ans=(int) Math.max(value[path[u]].query( pathPos[v]+1,pathPos[u]+1),ans);
			
				break;
			}
			ans=(int) Math.max(value[path[u]].query(0,pathPos[u]+1),ans);
		
			u = pathRoot[uchain]; // move u to u's chainHead
			u = parent[u]; //Then move to its parent, that means we changed chains
		}
		return ans;
	}

	
	int query(int u, int v) {
		/*
		 * We have a query from u to v, we break it into two queries, u to LCA(u,v) and LCA(u,v) to v
		 */
		int lca = lca(u, v);
		int ans = query_up(u, lca); // One part of path
		int temp = query_up(v, lca); // another part of path
		if(temp > ans) ans = temp; // take the maximum of both paths
		return ans;
	}

	void calcSizeParentTinTout(int root) {
		int n = tree.length;
		int[] curEdge = new int[n];
		int[] stack = new int[n];
		stack[0] = root;
		parent[root] = root;
		for (int top = 0; top >= 0; ) {
			int u = stack[top];
			if (curEdge[u] == 0) {
				
				//from
				up[0][u] = parent[u];
				for (int i = 1; i < len1; i++)
					up[i][u] = up[i - 1][up[i - 1][u]];
				//to
				
				tin[u] = time++;
				size[u] = 1;
			}
			if (curEdge[u] < tree[u].size()) {
				int v = tree[u].get(curEdge[u]++);
				if (curEdge[v] == 0) {
					stack[++top] = v;
					parent[v] = u;
				}
			} else {
				--top;
				if (parent[u] != u)
					size[parent[u]] += size[u];
				tout[u] = time++;
			}
		}
		parent[root]=-1;
	}

	int newPath(int u) {
		pathRoot[pathCount] = u;
		return pathCount++;
	}

	void buildPaths(int root) {
		int n = tree.length;
		int[] curEdge = new int[n];
		int[] stackPath = new int[n];
		int[] stack = new int[n];
		stack[0] = root;
		stackPath[0] = newPath(root);
		for (int top = 0; top >= 0; ) {
			int u = stack[top];
			int path = stackPath[top];
			if (curEdge[u] == 0) {
				this.path[u] = path;
				pathPos[u] = pathSize[path]++;
			}
			if (curEdge[u] < tree[u].size()) {
				int v = tree[u].get(curEdge[u]++);
				if (curEdge[v] == 0) {
					stack[++top] = v;
					stackPath[top] = 2 * size[v] >= size[u] ? path : newPath(v);
				}
			} else {
				--top;
			}
		}
	}

	void buildPaths(int u, int path) {
		this.path[u] = path;
		pathPos[u] = pathSize[path]++;
		for (int v : tree[u]) {
			if (v != parent[u])
				buildPaths(v, 2 * size[v] >= size[u] ? path : newPath(v));
		}
	}



	boolean isAncestor(int p, int ch) {
		return tin[p] <= tin[ch] && tout[ch] <= tout[p];
	}
	
	void change(int ver, int val) {
		int pa=path[ver];
		int pospa=pathPos[ver];
		value[pa].modify(pospa, val);
	}

	
	public int lca(int a, int b) {
		if (isAncestor(a, b))
			return a;
		if (isAncestor(b, a))
			return b;
		for (int i = len1 - 1; i >= 0; i--)
			if (!isAncestor(up[i][a], b))
				a = up[i][a];
	
		return up[0][a];
	}
	
	public static void main(String[] args) 
	{
		FastScanner in=new FastScanner(System.in);
		PrintWriter out=new PrintWriter(System.out);
		in.nextInt();
		int n=in.nextInt();
		Hashtable<Long, Integer> edgew=new Hashtable<>();
		Hashtable<Integer, Long> edgeidx=new Hashtable<>();
		ArrayList<Integer>[] arr=new ArrayList[n];
		for(int i=0;i<n;i++)
		{
			arr[i]=new ArrayList<Integer>();
		}
		
		for(int e=1;e<=(n-1);e++)
		{
			int a=in.nextInt()-1;
			int b=in.nextInt()-1;
			int c=in.nextInt();
			long imge=edge(a,b);
			edgew.put(imge,c);
			edgeidx.put(e, imge);
			arr[a].add(b);
			arr[b].add(a);
		}
		

		HeavyLightNoRecursion hdl=new HeavyLightNoRecursion(arr);
		
	
		for(int i=1;i<=n-1;i++)
		{
			long ab=edgeidx.get(i);
			int a=(int)(ab>>32);
			int b=(int)((ab<<32)>>32);
			if(hdl.parent[a]==b)
			{
				hdl.change(a, edgew.get(ab));
			}
			else
			{
				hdl.change(b, edgew.get(ab));
			}
		}
		l:
		while(true)
		{
			switch(in.next())
			{
			case "QUERY":
				int a1=in.nextInt()-1;
				int b1=in.nextInt()-1;
				out.println(hdl.query(a1,b1));
			break;
			case "CHANGE":
				int i=in.nextInt();
				int w=in.nextInt();
				long ab=edgeidx.get(i);
				int a=(int)(ab>>32);
				int b=(int)((ab<<32)>>32);
				edgew.put(ab, w);
				if(hdl.parent[a]==b)
				{
					hdl.change(a,  edgew.get(ab));
				}
				else
				{
					hdl.change(b, edgew.get(ab));
				}
			break;
			default:
				break l;
			}
		}
		out.close();
	}

	static long edge(int u, int v) {
		return ((long) Math.min(u, v) << 32) + Math.max(u, v);
	}

	
	static class FastScanner {
		BufferedReader br;
		StringTokenizer st;

		public FastScanner(File f) {
			try {
				br = new BufferedReader(new FileReader(f));
			} catch (FileNotFoundException e) {
				e.printStackTrace();
			}
		}

		public FastScanner(InputStream f) {
			br = new BufferedReader(new InputStreamReader(f));
		}

		String next() {
			while (st == null || !st.hasMoreTokens()) {
				String s = null;
				try {
					s = br.readLine();
				} catch (IOException e) {
					e.printStackTrace();
				}
				if (s == null)
					return null;
				st = new StringTokenizer(s);
			}
			return st.nextToken();
		}

		boolean hasMoreTokens() {
			while (st == null || !st.hasMoreTokens()) {
				String s = null;
				try {
					s = br.readLine();
				} catch (IOException e) {
					e.printStackTrace();
				}
				if (s == null)
					return false;
				st = new StringTokenizer(s);
			}
			return true;
		}

		int nextInt() {
			return Integer.parseInt(next());
		}

		long nextLong() {
			return Long.parseLong(next());
		}

		double nextDouble() {
			return Double.parseDouble(next());
		}
	}
}

