fork download
  1.  
  2. import java.io.*;
  3. import java.util.*;
  4.  
  5. public class FearOfTheDark implements Runnable {
  6.  
  7. static PrintWriter out = new PrintWriter(new BufferedOutputStream(System.out));
  8. static StringTokenizer st = new StringTokenizer("");
  9.  
  10. public static String next() {
  11. try {
  12. while (!st.hasMoreTokens()) {
  13. String s = br.readLine();
  14. if (s == null)
  15. return null;
  16. st = new StringTokenizer(s);
  17. }
  18. return st.nextToken();
  19. } catch(Exception e) {
  20. return null;
  21. }
  22. }
  23. public static void main(String[] asda) throws Exception {
  24. new Thread(null, new FearOfTheDark(), "Main", 1<<28).run();
  25. }
  26. public void run() {
  27. int N = Integer.parseInt( next() );
  28. ArrayList<Integer> [] g = new ArrayList [N];
  29. for (int k = 0; k < N; k++) g[k] = new ArrayList<Integer>();
  30. for (int k = 1; k < N; k++) {
  31. int a = Integer.parseInt( next() ) - 1;
  32. int b = Integer.parseInt( next() ) - 1;
  33.  
  34. g[a].add(b);
  35. g[b].add(a);
  36. }
  37.  
  38. HLD h = new HLD(g);
  39. // h.print(out);
  40.  
  41. int M = Integer.parseInt( next() );
  42. while (M-- > 0) {
  43. int q = Integer.parseInt( next() );
  44. int a = Integer.parseInt( next() ) - 1;
  45. int b = Integer.parseInt( next() ) - 1;
  46.  
  47. if (q == 2) {
  48. out.println( h.query(a, b) );
  49. } else {
  50. h.update(a, b);
  51. }
  52. }
  53. //
  54. out.flush();
  55. System.exit(0);
  56. }
  57.  
  58. }
  59.  
  60. class HLD {
  61. private int root;
  62. private List<Integer> [] g;
  63.  
  64. LCA lca;
  65. LazyBinarySegmentTree stree;
  66.  
  67. HLD(List<Integer> [] g) {
  68. this.g = g;
  69. int N = g.length;
  70.  
  71. size = new int [N];
  72. parent = new int [N];
  73. root = 0;
  74. dfs(root, -1);
  75.  
  76. numberOfChains = currentIndex = 0;
  77. chains = new LinkedList [N];
  78. chainHead = new int [N];
  79. chainIndex = new int [N];
  80. nodeIndex = new int [N];
  81. decompose(root);
  82.  
  83. lca = new LCA(g, root);
  84. stree = new LazyBinarySegmentTree(N);
  85. }
  86.  
  87. public void update(int a, int b) {
  88. int ancestor = lca.getLCA(a, b);
  89.  
  90. mupdate(ancestor, a);
  91. // System.out.println("...");
  92.  
  93. mupdate(ancestor, b);
  94. // System.out.println();
  95.  
  96. stree.flip( nodeIndex[ancestor], nodeIndex[ancestor] );
  97. }
  98.  
  99. private void mupdate(int ancestor, int node) {
  100. while ( chainIndex[ancestor] != chainIndex[node] ) {
  101. int head = chains[ chainIndex[node] ].get(0);
  102.  
  103. // System.out.printf("updating(%d, %d)\n", nodeIndex[head], nodeIndex[node] );
  104. stree.flip(nodeIndex[head], nodeIndex[node]);
  105. node = parent[node];
  106. }
  107.  
  108. // System.out.printf("updating(%d, %d)\n", nodeIndex[ancestor], nodeIndex[node] );
  109. stree.flip( nodeIndex[ancestor], nodeIndex[node] );
  110. }
  111.  
  112. public int query(int a, int b) {
  113. int ancestor = lca.getLCA(a, b);
  114.  
  115. int ans = internalQuery(ancestor, a);
  116. // System.out.println("...");
  117.  
  118. ans += internalQuery(ancestor, b);
  119. // System.out.println();
  120.  
  121. ans += stree.getFlipped( nodeIndex[ancestor], nodeIndex[ancestor] );
  122.  
  123. return ans;
  124. }
  125.  
  126. private int internalQuery(int ancestor, int node) {
  127. int ans = 0;
  128. while ( chainIndex[ancestor] != chainIndex[node] ) {
  129. int head = chains[ chainIndex[node] ].get(0);
  130.  
  131. // System.out.printf("query(%d, %d)\n", nodeIndex[head], nodeIndex[node] );
  132. ans += stree.getFlipped(nodeIndex[head], nodeIndex[node]);
  133. node = parent[node];
  134. }
  135.  
  136. // System.out.printf("query(%d, %d)\n", nodeIndex[ancestor], nodeIndex[node] );
  137. ans += stree.getFlipped( nodeIndex[ancestor], nodeIndex[node] );
  138. return ans;
  139. }
  140.  
  141. public void print(PrintWriter out) {
  142. out.println("size: " + Arrays.toString(size) );
  143. out.println("chains:");
  144. for (int k = 0; k <= numberOfChains; k++)
  145. out.println(" " + k + ": " + chains[k] );
  146.  
  147. out.println("chainIndex: " + Arrays.toString(chainIndex));
  148. out.println("nodeIndex: " + Arrays.toString(nodeIndex));
  149. }
  150.  
  151. private int numberOfChains;
  152. private int currentIndex;
  153. private List<Integer> [] chains; // chains[k] = the list of nodes in the chain k
  154. private int [] chainHead; // chainHead[k] = the head note at chain k
  155. private int [] chainIndex; // chainindex[k] = the chain index where node k belongs
  156. private int [] nodeIndex; // nodeindex[k] = the index assigned to node k after decomposition
  157.  
  158. // apply decomposition to a node
  159. private void decompose(int node) {
  160. if (chains[numberOfChains] == null) {
  161. // this is a new chain
  162. chains[numberOfChains] = new LinkedList<Integer>();
  163. chainHead[numberOfChains] = node;
  164. }
  165. chains[numberOfChains].add(node);
  166. chainIndex[node] = numberOfChains;
  167. nodeIndex[node] = currentIndex++;
  168.  
  169. // System.out.println("decompose " + node);
  170. // find the heaviest child
  171. int heavyChild = -1;
  172. for (int to : g[node]) if (to != parent[node]) {
  173. if ( heavyChild == -1 || size[heavyChild] < size[to] ) {
  174. heavyChild = to;
  175. }
  176. }
  177.  
  178. // System.out.println(" heavy child " + heavyChild);
  179.  
  180. if (heavyChild == -1) {
  181. return; // this node is a leaf
  182. }
  183.  
  184. decompose(heavyChild);
  185.  
  186. for (int to : g[node]) if (to != parent[node] && to != heavyChild) {
  187. // decompose this child into a new chain
  188. numberOfChains++;
  189. decompose(to);
  190. }
  191. }
  192.  
  193. private int [] size; // size[k] = size of the subtree rooted at k
  194. private int [] parent; // parent[k] = parent of node k
  195. private void dfs(int node, int dad) {
  196. parent[node] = dad;
  197. size[node] = 1;
  198. for (int to : g[node]) if (dad != to) {
  199. dfs(to, node);
  200. size[node] += size[to];
  201. }
  202. }
  203. }
  204.  
  205. class LazyBinarySegmentTree {
  206. int [] ones, twos, flip;
  207. int size;
  208.  
  209.  
  210. public LazyBinarySegmentTree(int size) {
  211. size++;
  212. int N = 1;
  213. while ( (N <<= 1) < size);
  214. N <<= 1;
  215.  
  216. ones = new int[N];
  217. twos = new int[N];
  218. flip = new int[N];
  219.  
  220. this.size = size;
  221. }
  222. // x and y sould start in 1
  223. void flip(int x, int y) {
  224. x++; y++;
  225. update( 1, size, x, y, 1 );
  226. // System.out.printf("update(%d, %d)\n", x, y );
  227. }
  228.  
  229. int getFlipped(int x, int y) {
  230. x++; y++;
  231. // lasta parameter is for the initial status of each element in array (0, 1)
  232. // System.out.printf("query(%d, %d) = %d\n", x, y, query( 1, size, x, y, 1, 1 ) );
  233. return query( 1, size, x, y, 1, 1 );
  234. }
  235.  
  236.  
  237. private void update(int lo, int hi, int x, int y, int i) {
  238. if (x > hi || y < lo)
  239. return;
  240.  
  241. int mid;
  242. if (x <= lo && y >= hi) {
  243. ones[i] = (hi - lo + 1) - ones[i];
  244. flip[i] += 1;
  245. if (flip[i] > 1)
  246. flip[i] -= 2;
  247. return;
  248. }
  249.  
  250. mid = (lo + hi) >> 1;
  251. update(lo, mid, x, y, 2 * i);
  252. update(mid + 1, hi, x, y, 2 * i + 1);
  253.  
  254. ones[i] = ones[2 * i] + ones[2 * i + 1];
  255.  
  256. if (flip[i] == 1) {
  257. ones[i] = (hi - lo + 1) - ones[i];
  258. }
  259. }
  260.  
  261.  
  262. private int query(int lo, int hi, int x, int y, int i, int flag) {
  263. if (x > hi || y < lo)
  264. return 0;
  265.  
  266. if (x <= lo && y >= hi) {
  267. if (flag == 1)
  268. return ones[i];
  269.  
  270. return (hi - lo + 1) - ones[i];
  271. }
  272.  
  273.  
  274. int mid = (lo + hi) >> 1, nflag = (flag + flip[i]);
  275.  
  276. if (nflag > 1)
  277. nflag -= 2;
  278.  
  279. return query(lo, mid, x, y, 2 * i, nflag) +
  280. query(mid + 1, hi, x, y, 2 * i + 1, nflag);
  281. }
  282.  
  283. }
  284.  
  285.  
  286. class LCA {
  287. int N;
  288. int logN;
  289. int[] dep;
  290. int[][] go;
  291. List<Integer>[] g;
  292. // 1 based index
  293. LCA(List<Integer> g[], int root) {
  294. this.g = g;
  295. N = g.length;
  296. logN = 1;
  297. while ((1 << logN) <= N)
  298. logN++;
  299.  
  300. // System.out.println(N + " " + logN);
  301. dep = new int[N];
  302. go = new int[N][logN];
  303.  
  304. dfs(root, 0, 0);
  305.  
  306. // Prepare for LCA queries.
  307. for (int k = 1; k < logN; ++k) {
  308. for (int i = 1; i < N; ++i) {
  309. go[i][k] = go[go[i][k - 1]][k - 1];
  310. }
  311. }
  312. }
  313.  
  314. private void dfs(int id, int depth, int dad) {
  315. go[id][0] = dad;
  316. dep[id] = depth;
  317.  
  318. for (int to : g[id]) {
  319. if ( to != dad )
  320. dfs(to, depth + 1, id);
  321. }
  322. }
  323.  
  324. int getLCA(int u, int v) {
  325. if (dep[u] < dep[v]) {
  326. int aux = u;
  327. u = v;
  328. v = aux;
  329. }
  330.  
  331. int diff = dep[u] - dep[v];
  332. for (int i = 0; diff != 0; ++i, diff >>= 1) {
  333. if ( (diff & 1) != 0 ) {
  334. u = go[u][i];
  335. }
  336. }
  337.  
  338. if (u == v)
  339. return u;
  340.  
  341. for (int i = logN - 1; i >= 0; --i) {
  342. if (go[u][i] != go[v][i]) {
  343. u = go[u][i];
  344. v = go[v][i];
  345. }
  346. }
  347. return go[u][0];
  348. }
  349. }
  350.  
  351.  
  352.  
Compilation error #stdin compilation error #stdout 0s 0KB
stdin
Standard input is empty
compilation info
Main.java:5: error: class FearOfTheDark is public, should be declared in a file named FearOfTheDark.java
public class FearOfTheDark implements Runnable {
       ^
Note: Main.java uses unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.
1 error
stdout
Standard output is empty