Advertisement
Guest User

Heavy_Light

a guest
Feb 21st, 2020
152
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 5.25 KB | None | 0 0
  1. #include <iostream>
  2. #include <vector>
  3.  
  4. #define int long long
  5.  
  6. using namespace std;
  7.  
  8. struct edge {
  9. int u;
  10. int v;
  11. int w;
  12. };
  13.  
  14. vector<vector<edge>> edges;
  15. vector<edge> parent;
  16. vector<int> s;
  17. vector<vector<int>> pathes;
  18. vector<vector<int>> chains;
  19. vector<int> global_chain;
  20. vector<int> tin, tout;
  21. vector<vector<int>> up;
  22. vector<int> myChain;
  23. vector<int> chainOffset;
  24. vector<vector<int>> answer;
  25. int n, m;
  26.  
  27. const int l = 15;
  28.  
  29. int calc_size(int index){
  30. int _count = 1;
  31. for (int i = 0; i < edges[index].size(); i++)
  32. _count += calc_size(edges[index][i].v);
  33. s[index] = _count;
  34. return _count;
  35. }
  36.  
  37. void build_path(int index, int chain){
  38. bool flag = (chain != -1);
  39.  
  40. if (chain == -1) {
  41. chain = pathes.size();
  42. pathes.resize(chain+1); pathes[chain].resize(0);
  43. chains.resize(chain+1); chains[chain].resize(0);
  44. }
  45. pathes[chain].push_back(index);
  46. if (flag) chains[chain].push_back(parent[index].w);
  47. myChain[index] = chain;
  48.  
  49. int _max = 0, child;
  50. for (int i = 0; i < edges[index].size(); i++){
  51. int to = edges[index][i].v;
  52. if (_max < s[to]) {
  53. _max = s[to];
  54. child = to;
  55. }
  56. }
  57.  
  58. if (_max > 0) build_path(child, chain);
  59.  
  60. for (int i = 0; i < edges[index].size(); i++){
  61. int to = edges[index][i].v;
  62. if (to != child) build_path(to, -1);
  63. }
  64. }
  65.  
  66. void reverse_chains(int num){
  67. if (num == chains.size()) return;
  68. int _size = chains[num].size();
  69. for (int i = 0; i < _size/2; i++)
  70. swap(chains[num][i], chains[num][_size-1-i]);
  71. reverse_chains(num+1);
  72. }
  73.  
  74. void build_global_chain(){
  75. int _size = 0;
  76. for (int i = 0; i < chains.size(); i++)
  77. _size += chains[i].size();
  78.  
  79. for (m = 1; m < _size; m *= 2);
  80.  
  81. global_chain.resize(2*m, 0);
  82. chainOffset.resize(chains.size());
  83.  
  84. int offset = 0;
  85. for (int i = 0; i < chains.size(); i++){
  86. for (int j = 0; j < chains[i].size(); j++)
  87. global_chain[offset + j + m] = chains[i][j];
  88. chainOffset[i] = offset;
  89. offset += chains[i].size();
  90. }
  91.  
  92. for (int i = m-1; i > 0; i--)
  93. global_chain[i] = global_chain[i*2] + global_chain[i*2+1];
  94. }
  95.  
  96. int timer;
  97. void dfs(int index, int parent){
  98. if (index == 0) timer = 0;
  99. tin[index] = ++timer;
  100. up[index][0] = parent;
  101. for (int i = 1; i < l; i++)
  102. up[index][i] = up[up[index][i-1]][i-1];
  103.  
  104. for (int i = 0; i < edges[index].size(); i++)
  105. dfs(edges[index][i].v, index);
  106.  
  107. tout[index] = ++timer;
  108. }
  109.  
  110. bool upper(int a, int b){
  111. return (tin[a] <= tin[b] && tout[b] <= tout[a]);
  112. }
  113.  
  114. int lca(int a, int b){
  115. if (upper(a,b)) return a;
  116. if (upper(b,a)) return b;
  117.  
  118. for (int i = l-1; i >= 0; i--){
  119. while (!upper(up[a][i], b)) a = up[a][i];
  120. }
  121.  
  122. return up[a][0];
  123. }
  124.  
  125. int _find(int index, int chain){
  126. int l = 0; int r = pathes[chain].size()-1;
  127. int m;
  128. while (r-l > 1){
  129. m = (l+r)/2;
  130. if (pathes[chain][m] < index) l = m; else r = m;
  131. }
  132.  
  133. if (pathes[chain][l] == index) return l;
  134. if (pathes[chain][r] == index) return r;
  135. return -1;
  136. }
  137.  
  138. int calcDistToLCA(int index, int _lca){
  139. int chain = myChain[index];
  140. int r = _find(index, chain);
  141. int l = _find(_lca, chain);
  142. bool flag = (l == -1);
  143. if (l == -1) l = 0;
  144.  
  145. l = m + chainOffset[chain] + l;
  146. r = m + chainOffset[chain] + r - 1;
  147.  
  148. int sum = 0;
  149.  
  150. if (r >= l){
  151. while (l != r){
  152. if (r > l){
  153. if (r % 2 == 1) r /= 2; else {
  154. sum += global_chain[r];
  155. r--;
  156. }
  157. } else {
  158. if (l % 2 == 0) l /= 2; else {
  159. sum += global_chain[l];
  160. l++;
  161. }
  162. }
  163. }
  164. sum += global_chain[l];
  165. }
  166.  
  167. if (flag){
  168. edge _parent = parent[pathes[chain][0]];
  169. sum += calcDistToLCA(_parent.u, _lca) + _parent.w;
  170. }
  171.  
  172. return sum;
  173. }
  174.  
  175. int getDistOnWay(int a, int b){
  176. int _lca = lca(a, b);
  177.  
  178. return calcDistToLCA(a, _lca) + calcDistToLCA(b, _lca);
  179. }
  180.  
  181. main()
  182. {
  183. ios_base::sync_with_stdio(false);
  184. cin.tie(0);
  185. cout.tie(0);
  186.  
  187. cin >> n;
  188. if (n == 0) {
  189. for (int i = 0; i < answer.size(); i++){
  190. for (int j = 0; j < answer[i].size(); j++) cout << answer[i][j] << " ";
  191. cout << endl;
  192. }
  193. return 0;
  194. }
  195. answer.resize(answer.size()+1);
  196.  
  197. edges.resize(n); for (int i = 0; i < n; i++) edges[i].resize(0);
  198. s.resize(n);
  199. parent.resize(n);
  200. tin.resize(n);
  201. tout.resize(n);
  202. up.resize(n); for (int i = 0; i < n; i++) up[i].resize(l);
  203. pathes.resize(0);
  204. chains.resize(0);
  205. global_chain.resize(0);
  206. myChain.resize(n);
  207.  
  208. edge e;
  209. for (int i = 1; i < n; i++){
  210. cin >> e.u >> e.w;
  211. e.v = i;
  212. edges[e.u].push_back(e);
  213. parent[i] = e;
  214. }
  215.  
  216. calc_size(0);
  217. build_path(0, -1);
  218. build_global_chain();
  219. dfs(0, 0);
  220.  
  221. int q; cin >> q;
  222. while (q--) {
  223. int a, b;
  224. cin >> a >> b;
  225. answer[answer.size()-1].push_back(getDistOnWay(a, b));
  226. }
  227.  
  228. main();
  229.  
  230. return 0;
  231. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement