Advertisement
FyanRu

Untitled

Jul 17th, 2024
23
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 7.21 KB | None | 0 0
  1. #pragma GCC optimize("O3,unroll-loops")
  2. #include <bits/stdc++.h>
  3. using namespace std;
  4.  
  5. #define sz(x) (int) (x).size()
  6. #define i64 int64_t
  7. #define all(x) (x).begin(), (x).end()
  8.  
  9. const int BUF_SZ = 1 << 15;
  10. const int LG = 20;
  11. const int FAKE = 5e5 + 3;
  12. const int mxn = 5e5 + 5;
  13. const int MM = 10;
  14.  
  15. inline int log2_floor(unsigned long long i) {
  16. return i ? 63 - __builtin_clzll(i) : -1;
  17. }
  18.  
  19. inline namespace Input {
  20. char buf[BUF_SZ]; int pos; int len;
  21. inline char next_char() {
  22. if (pos == len) {
  23. pos = 0;
  24. len = (int)fread(buf, 1, BUF_SZ, stdin);
  25. if (!len) { return EOF; }
  26. }
  27. return buf[pos++];
  28. }
  29. inline i64 read_int() {
  30. i64 x; char ch; int sgn = 1;
  31. while (!isdigit(ch = next_char())) {
  32. if (ch == '-') { sgn *= -1; }
  33. }
  34. x = ch - '0';
  35. while (isdigit(ch = next_char())) { x = x * 10ll + (ch - '0'); }
  36. return x * sgn;
  37. }
  38. }
  39.  
  40. inline namespace Output {
  41. char buf[BUF_SZ]; int pos;
  42. inline void flush_out() { fwrite(buf, 1, pos, stdout); pos = 0; }
  43. inline void write_char(char c) {
  44. if (pos == BUF_SZ) { flush_out(); }
  45. buf[pos++] = c;
  46. }
  47. inline void write_int(i64 x) {
  48. static char num_buf[100];
  49. if (x < 0) { write_char('-'); x *= -1; }
  50. int len = 0;
  51. do {
  52. num_buf[len++] = (char)('0' + (x % 10));
  53. x /= 10;
  54. } while (x);
  55. while (len) { write_char(num_buf[--len]); }
  56. write_char('\n');
  57. }
  58. void init_output() { assert(atexit(flush_out) == 0); }
  59. }
  60.  
  61. vector<array<int,2>> adj[FAKE];
  62. int etour[4*FAKE], tin[FAKE], tot[FAKE];
  63. i64 dtour[4*FAKE], dep[FAKE];
  64. int tourp = 0;
  65.  
  66. void tinit(int n) {
  67. for (int i = 0; i < n; i++) {
  68. adj[i].clear();
  69. }
  70. tourp = 0;
  71. }
  72.  
  73. void add_edge(int u, int v, i64 w) {
  74. adj[u].push_back({v, w});
  75. adj[v].push_back({u, w});
  76. }
  77.  
  78. void dfs(int v, int p, i64 d) {
  79. dep[v] = d;
  80. tin[v] = tourp;
  81. etour[tourp++] = v;
  82. for (const auto& e : adj[v]) {
  83. if (e[0] == p) continue;
  84. dfs(e[0], v, d + e[1]);
  85. etour[tourp++] = v;
  86. }
  87. tot[v] = tourp;
  88. etour[tourp++] = v;
  89. }
  90.  
  91. int sparsetable[LG][4*FAKE];
  92. void init_sparse() {
  93. dfs(0, 0, 0);
  94. for (int i = 0; i < tourp; i++) {
  95. dtour[i] = dep[etour[i]];
  96. sparsetable[0][i] = i;
  97. }
  98. for (int i = 1; i < LG; i++) {
  99. for (int j = 0; j + (1 << i) <= tourp; j++) {
  100. sparsetable[i][j] = (dtour[sparsetable[i-1][j]] < dtour[sparsetable[i-1][j + (1 << (i-1))]] ? sparsetable[i-1][j] : sparsetable[i-1][j + (1 << (i-1))]);
  101. }
  102. }
  103. }
  104.  
  105. int rmq(int l, int r) {
  106. int i = log2_floor(r - l + 1);
  107. return (dtour[sparsetable[i][l]] < dtour[sparsetable[i][r - (1 << i) + 1]] ? sparsetable[i][l] : sparsetable[i][r - (1 << i) + 1]);
  108. }
  109.  
  110. int lca(int u, int v) {
  111. return etour[rmq(min(tin[u], tin[v]), max(tot[u], tot[v]))];
  112. }
  113.  
  114. i64 dist(int u, int v) {
  115. return (u == FAKE || v == FAKE) ? -69 : dep[u] + dep[v] - 2 * dep[lca(u, v)];
  116. }
  117.  
  118. int n, q, c[mxn], qr[mxn][4], np;
  119. vector<int> col[mxn];
  120.  
  121. void chmax(int &x, int &y, int x1, int y1) {
  122. if (dist(x1, y1) >= dist(x, y)) {
  123. x = x1;
  124. y = y1;
  125. }
  126. }
  127.  
  128. int lo[MM*mxn], hi[MM*mxn], x[MM*mxn], y[MM*mxn], xd[MM*mxn], yd[MM*mxn], CXD[MM*mxn];
  129. int lc[MM*mxn], rc[MM*mxn];
  130. int nx = 0;
  131.  
  132. inline int create_node(int cxd) {
  133. CXD[nx] = cxd;
  134. x[nx] = y[nx] = FAKE;
  135. lc[nx] = rc[nx] = -1;
  136. return nx++;
  137. }
  138.  
  139. int create_node(int l, int h, int cxd) {
  140. lo[nx] = l;
  141. hi[nx] = h;
  142. return create_node(cxd);
  143. }
  144.  
  145. void pull(int v) {
  146. if (lc[v] != -1 && x[lc[v]] == FAKE) lc[v] = -1;
  147. if (rc[v] != -1 && x[rc[v]] == FAKE) rc[v] = -1;
  148. x[v] = y[v] = xd[v] = yd[v] = FAKE;
  149. if (lc[v] == -1 && rc[v] == -1) return;
  150. if (rc[v] == -1) {
  151. x[v] = x[lc[v]];
  152. y[v] = y[lc[v]];
  153. if (CXD[v]) {
  154. xd[v] = xd[lc[v]];
  155. yd[v] = yd[lc[v]];
  156. }
  157. return;
  158. }
  159. if (lc[v] == -1) {
  160. x[v] = x[rc[v]];
  161. y[v] = y[rc[v]];
  162. if (CXD[v]) {
  163. xd[v] = xd[rc[v]];
  164. yd[v] = yd[rc[v]];
  165. }
  166. return;
  167. }
  168. if (CXD[v]) {
  169. int lx = x[lc[v]], rx = x[rc[v]], ly = y[lc[v]], ry = y[rc[v]];
  170. int lxd = xd[lc[v]], rxd = xd[rc[v]], lyd = yd[lc[v]], ryd = yd[rc[v]];
  171. chmax(xd[v], yd[v], lx, rx);
  172. chmax(xd[v], yd[v], lx, ry);
  173. chmax(xd[v], yd[v], ly, rx);
  174. chmax(xd[v], yd[v], ly, ry);
  175. chmax(xd[v], yd[v], lxd, lyd);
  176. chmax(xd[v], yd[v], rxd, ryd);
  177. x[v] = xd[v];
  178. y[v] = yd[v];
  179. if (c[lx] != c[ly]) chmax(xd[v], yd[v], lx, ly);
  180. chmax(x[v], y[v], lx, ly);
  181. chmax(x[v], y[v], rx, ry);
  182. } else {
  183. int lx = x[lc[v]], rx = x[rc[v]], ly = y[lc[v]], ry = y[rc[v]];
  184. chmax(x[v], y[v], lx, ly);
  185. chmax(x[v], y[v], lx, rx);
  186. chmax(x[v], y[v], lx, ry);
  187. chmax(x[v], y[v], ly, rx);
  188. chmax(x[v], y[v], ly, ry);
  189. chmax(x[v], y[v], rx, ry);
  190. }
  191. }
  192.  
  193. void point_set(int v, int I, int X, int Y) {
  194. if (lo[v] == I && hi[v] == I) {
  195. x[v] = X;
  196. y[v] = Y;
  197. xd[v] = yd[v] = FAKE;
  198. return;
  199. }
  200. if (I <= (lo[v] + hi[v]) / 2) {
  201. if (lc[v] == -1) lc[v] = create_node(lo[v], (lo[v] + hi[v]) / 2, CXD[v]);
  202. point_set(lc[v], I, X, Y);
  203. } else {
  204. if (rc[v] == -1) rc[v] = create_node((lo[v] + hi[v]) / 2 + 1, hi[v], CXD[v]);
  205. point_set(rc[v], I, X, Y);
  206. }
  207. pull(v);
  208. }
  209.  
  210. int crt[mxn], trt;
  211.  
  212. void solve() {
  213. nx = 0;
  214. for (int i = 0; i <= q; i++) col[i].clear();
  215. q = read_int();
  216. c[0] = read_int();
  217. n = 0;
  218. col[c[0]].push_back(0);
  219. tinit(q + 1);
  220. np = 1;
  221. for (int i = 0; i < q; i++) {
  222. qr[i][0] = read_int();
  223. qr[i][1] = read_int();
  224. qr[i][2] = read_int();
  225. if (!qr[i][0]) {
  226. i64 d = read_int();
  227. add_edge(qr[i][1] - 1, np++, d);
  228. n++;
  229. qr[i][1] = np;
  230. }
  231. qr[i][1]--;
  232. col[qr[i][2]].push_back(qr[i][1]);
  233. }
  234. for (int i = 0; i <= q; i++) {
  235. sort(all(col[i]));
  236. col[i].erase(unique(all(col[i])), col[i].end());
  237. }
  238. init_sparse();
  239. for (int i = 0; i <= q; i++) {
  240. crt[i] = create_node(0, sz(col[i]) + 1, 0);
  241. }
  242. trt = create_node(0, q + 1, 1);
  243. point_set(crt[c[0]], 0, 0, 0);
  244. point_set(trt, c[0], x[crt[c[0]]], y[crt[c[0]]]);
  245. for (int i = 0; i < q; i++) {
  246. int tr = qr[i][0], xx = qr[i][1], ci = qr[i][2];
  247. int pcx = c[xx];
  248. c[xx] = ci;
  249. if (tr) {
  250. int xtv = lower_bound(all(col[pcx]), xx) - col[pcx].begin();
  251. point_set(crt[pcx], xtv, FAKE, FAKE);
  252. point_set(trt, pcx, x[crt[pcx]], y[crt[pcx]]);
  253. }
  254. int xtv = lower_bound(all(col[ci]), xx) - col[ci].begin();
  255. point_set(crt[ci], xtv, xx, xx);
  256. point_set(trt, ci, x[crt[ci]], y[crt[ci]]);
  257. write_int(max(dist(xd[trt], yd[trt]), 0ll));
  258. }
  259. }
  260.  
  261. signed main() {
  262. init_output();
  263. int t = read_int();;
  264. while (t--) {
  265. solve();
  266. }
  267. return 0;
  268. }
  269. //
  270.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement