fork(1) download
  1. import java.io.BufferedReader;
  2. import java.io.File;
  3. import java.io.FileNotFoundException;
  4. import java.io.FileReader;
  5. import java.io.IOException;
  6. import java.io.InputStream;
  7. import java.io.InputStreamReader;
  8. import java.io.PrintWriter;
  9. import java.util.ArrayList;
  10. import java.util.Arrays;
  11. import java.util.HashMap;
  12. import java.util.Hashtable;
  13. import java.util.List;
  14. import java.util.Map;
  15. import java.util.Random;
  16. import java.util.StringTokenizer;
  17.  
  18. class HeavyLightNoRecursion {
  19.  
  20. segmentTree value[];
  21.  
  22. List<Integer>[] tree;
  23. int[] size;
  24. int[] parent;
  25. int[] tin;
  26. int[] tout;
  27. int time;
  28. int[] path;
  29. int[] pathSize;
  30. int[] pathPos;
  31. int[] pathRoot;
  32. int pathCount;
  33. int len1;
  34. int[][] up;
  35.  
  36.  
  37. public HeavyLightNoRecursion(List<Integer>[] tree) {
  38. this.tree = tree;
  39. int n = tree.length;
  40.  
  41. size = new int[n];
  42. parent = new int[n];
  43. tin = new int[n];
  44. tout = new int[n];
  45.  
  46. len1 = 1;
  47. while ((1 << len1) <= n) ++len1;
  48. up = new int[len1][n];
  49.  
  50. calcSizeParentTinTout(0);
  51.  
  52. path = new int[n];
  53. pathSize = new int[n];
  54. pathPos = new int[n];
  55. pathRoot = new int[n];
  56. buildPaths(0);
  57.  
  58. value=new segmentTree[pathCount];
  59. for (int i = 0; i < pathCount; i++) {
  60. int m = pathSize[i];
  61.  
  62. value[i]=new segmentTree(new long[m]);
  63. }
  64. }
  65.  
  66. class segmentTree
  67. {
  68. int n; // array size
  69. long t[];
  70.  
  71. public segmentTree(long[] arr)
  72. {
  73. n=arr.length;
  74. t=new long[3*n];
  75. for(int i=0;i<n;i++)
  76. {
  77. t[n+i]=arr[i];
  78. }
  79. build();
  80. }
  81.  
  82. void build() { // build the tree
  83. for (int i = n - 1; i > 0; --i) t[i] = Math.max(t[i<<1],t[i<<1|1]);
  84. }
  85.  
  86. void modify(int p, long value) {
  87. for (t[p += n] = value; p > 1; p >>= 1) t[p>>1] = Math.max(t[p],t[p^1]);
  88. }
  89.  
  90. long query(int l, int r) { // sum on interval [l, r)
  91. long res = 0;
  92. for (l += n, r += n; l < r; l >>= 1, r >>= 1) {
  93. if ((l&1)!=0) res=Math.max(res , t[l++]);
  94. if ((r&1)!=0) res= Math.max(res, t[--r]);
  95. }
  96. return res;
  97. }
  98. }
  99.  
  100. int query_up(int u, int v) {
  101. if(u == v) return 0;
  102.  
  103. int uchain, vchain = path[v], ans = -1;
  104.  
  105. while(true) {
  106.  
  107. uchain = path[u];
  108. if(uchain == vchain) {
  109.  
  110. if(u==v) break;
  111. ans=(int) Math.max(value[path[u]].query( pathPos[v]+1,pathPos[u]+1),ans);
  112.  
  113. break;
  114. }
  115. ans=(int) Math.max(value[path[u]].query(0,pathPos[u]+1),ans);
  116.  
  117. u = pathRoot[uchain]; // move u to u's chainHead
  118. u = parent[u]; //Then move to its parent, that means we changed chains
  119. }
  120. return ans;
  121. }
  122.  
  123.  
  124. int query(int u, int v) {
  125. /*
  126. * 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
  127. */
  128. int lca = lca(u, v);
  129. int ans = query_up(u, lca); // One part of path
  130. int temp = query_up(v, lca); // another part of path
  131. if(temp > ans) ans = temp; // take the maximum of both paths
  132. return ans;
  133. }
  134.  
  135. void calcSizeParentTinTout(int root) {
  136. int n = tree.length;
  137. int[] curEdge = new int[n];
  138. int[] stack = new int[n];
  139. stack[0] = root;
  140. parent[root] = root;
  141. for (int top = 0; top >= 0; ) {
  142. int u = stack[top];
  143. if (curEdge[u] == 0) {
  144.  
  145. //from
  146. up[0][u] = parent[u];
  147. for (int i = 1; i < len1; i++)
  148. up[i][u] = up[i - 1][up[i - 1][u]];
  149. //to
  150.  
  151. tin[u] = time++;
  152. size[u] = 1;
  153. }
  154. if (curEdge[u] < tree[u].size()) {
  155. int v = tree[u].get(curEdge[u]++);
  156. if (curEdge[v] == 0) {
  157. stack[++top] = v;
  158. parent[v] = u;
  159. }
  160. } else {
  161. --top;
  162. if (parent[u] != u)
  163. size[parent[u]] += size[u];
  164. tout[u] = time++;
  165. }
  166. }
  167. parent[root]=-1;
  168. }
  169.  
  170. int newPath(int u) {
  171. pathRoot[pathCount] = u;
  172. return pathCount++;
  173. }
  174.  
  175. void buildPaths(int root) {
  176. int n = tree.length;
  177. int[] curEdge = new int[n];
  178. int[] stackPath = new int[n];
  179. int[] stack = new int[n];
  180. stack[0] = root;
  181. stackPath[0] = newPath(root);
  182. for (int top = 0; top >= 0; ) {
  183. int u = stack[top];
  184. int path = stackPath[top];
  185. if (curEdge[u] == 0) {
  186. this.path[u] = path;
  187. pathPos[u] = pathSize[path]++;
  188. }
  189. if (curEdge[u] < tree[u].size()) {
  190. int v = tree[u].get(curEdge[u]++);
  191. if (curEdge[v] == 0) {
  192. stack[++top] = v;
  193. stackPath[top] = 2 * size[v] >= size[u] ? path : newPath(v);
  194. }
  195. } else {
  196. --top;
  197. }
  198. }
  199. }
  200.  
  201. void buildPaths(int u, int path) {
  202. this.path[u] = path;
  203. pathPos[u] = pathSize[path]++;
  204. for (int v : tree[u]) {
  205. if (v != parent[u])
  206. buildPaths(v, 2 * size[v] >= size[u] ? path : newPath(v));
  207. }
  208. }
  209.  
  210.  
  211.  
  212. boolean isAncestor(int p, int ch) {
  213. return tin[p] <= tin[ch] && tout[ch] <= tout[p];
  214. }
  215.  
  216. void change(int ver, int val) {
  217. int pa=path[ver];
  218. int pospa=pathPos[ver];
  219. value[pa].modify(pospa, val);
  220. }
  221.  
  222.  
  223. public int lca(int a, int b) {
  224. if (isAncestor(a, b))
  225. return a;
  226. if (isAncestor(b, a))
  227. return b;
  228. for (int i = len1 - 1; i >= 0; i--)
  229. if (!isAncestor(up[i][a], b))
  230. a = up[i][a];
  231.  
  232. return up[0][a];
  233. }
  234.  
  235. public static void main(String[] args)
  236. {
  237. FastScanner in=new FastScanner(System.in);
  238. in.nextInt();
  239. int n=in.nextInt();
  240. Hashtable<Long, Integer> edgew=new Hashtable<>();
  241. Hashtable<Integer, Long> edgeidx=new Hashtable<>();
  242. ArrayList<Integer>[] arr=new ArrayList[n];
  243. for(int i=0;i<n;i++)
  244. {
  245. arr[i]=new ArrayList<Integer>();
  246. }
  247.  
  248. for(int e=1;e<=(n-1);e++)
  249. {
  250. int a=in.nextInt()-1;
  251. int b=in.nextInt()-1;
  252. int c=in.nextInt();
  253. long imge=edge(a,b);
  254. edgew.put(imge,c);
  255. edgeidx.put(e, imge);
  256. arr[a].add(b);
  257. arr[b].add(a);
  258. }
  259.  
  260.  
  261. HeavyLightNoRecursion hdl=new HeavyLightNoRecursion(arr);
  262.  
  263.  
  264. for(int i=1;i<=n-1;i++)
  265. {
  266. long ab=edgeidx.get(i);
  267. int a=(int)(ab>>32);
  268. int b=(int)((ab<<32)>>32);
  269. if(hdl.parent[a]==b)
  270. {
  271. hdl.change(a, edgew.get(ab));
  272. }
  273. else
  274. {
  275. hdl.change(b, edgew.get(ab));
  276. }
  277. }
  278. l:
  279. while(true)
  280. {
  281. switch(in.next())
  282. {
  283. case "QUERY":
  284. int a1=in.nextInt()-1;
  285. int b1=in.nextInt()-1;
  286. out.println(hdl.query(a1,b1));
  287. break;
  288. case "CHANGE":
  289. int i=in.nextInt();
  290. int w=in.nextInt();
  291. long ab=edgeidx.get(i);
  292. int a=(int)(ab>>32);
  293. int b=(int)((ab<<32)>>32);
  294. edgew.put(ab, w);
  295. if(hdl.parent[a]==b)
  296. {
  297. hdl.change(a, edgew.get(ab));
  298. }
  299. else
  300. {
  301. hdl.change(b, edgew.get(ab));
  302. }
  303. break;
  304. default:
  305. break l;
  306. }
  307. }
  308. out.close();
  309. }
  310.  
  311. static long edge(int u, int v) {
  312. return ((long) Math.min(u, v) << 32) + Math.max(u, v);
  313. }
  314.  
  315.  
  316. static class FastScanner {
  317.  
  318. public FastScanner(File f) {
  319. try {
  320. br = new BufferedReader(new FileReader(f));
  321. } catch (FileNotFoundException e) {
  322. e.printStackTrace();
  323. }
  324. }
  325.  
  326. public FastScanner(InputStream f) {
  327. }
  328.  
  329. String next() {
  330. while (st == null || !st.hasMoreTokens()) {
  331. String s = null;
  332. try {
  333. s = br.readLine();
  334. } catch (IOException e) {
  335. e.printStackTrace();
  336. }
  337. if (s == null)
  338. return null;
  339. st = new StringTokenizer(s);
  340. }
  341. return st.nextToken();
  342. }
  343.  
  344. boolean hasMoreTokens() {
  345. while (st == null || !st.hasMoreTokens()) {
  346. String s = null;
  347. try {
  348. s = br.readLine();
  349. } catch (IOException e) {
  350. e.printStackTrace();
  351. }
  352. if (s == null)
  353. return false;
  354. st = new StringTokenizer(s);
  355. }
  356. return true;
  357. }
  358.  
  359. int nextInt() {
  360. return Integer.parseInt(next());
  361. }
  362.  
  363. long nextLong() {
  364. return Long.parseLong(next());
  365. }
  366.  
  367. double nextDouble() {
  368. return Double.parseDouble(next());
  369. }
  370. }
  371. }
  372.  
  373.  
Success #stdin #stdout 0.12s 320576KB
stdin
1
15
1 2 5
1 4 15
1 10 10
2 3 11
2 5 3
5 9 4
9 15 5
3 11 12
3 6 14
6 7 20
6 8 21
8 12 1
12 13 2
13 14 3
QUERY 4 11
QUERY 7 10
QUERY 15 12
DONE
stdout
15
20
21