danielvitor23

QTREE6 - Query on a tree VI

May 8th, 2023
1,033
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 6.53 KB | Source Code | 0 0
  1. #include <bits/stdc++.h>
  2. using namespace std;
  3.  
  4. const int INF = 0x3f3f3f3f;
  5.  
  6. struct SegTree {
  7.   int N;
  8.  
  9.   vector<int> tr;
  10.  
  11.   void init(int n, vector<int> &v) {
  12.     N = n;
  13.     tr.assign(n << 2, 0);
  14.     build(1, 1, n, v);
  15.   }
  16.  
  17.   inline int join(int a, int b) {
  18.     return a + b;
  19.   }
  20.  
  21.   void build(int node, int l, int r, vector<int> &v) {
  22.     if (l == r) {
  23.       // tr[node] = 0;
  24.       tr[node] = v[l];
  25.       return;
  26.     }
  27.     int lc = node << 1;
  28.     int mid = l + (r - l) / 2;
  29.     build(lc, l, mid, v);
  30.     build(lc + 1, mid + 1, r, v);
  31.   }
  32.  
  33.   int query(int node, int l, int r, int idx) {
  34.     if (l == r) return tr[node];
  35.     int lc = node << 1;
  36.     int mid = l + (r - l) / 2;
  37.     if (idx <= mid)
  38.       return tr[node] + query(lc, l, mid, idx);
  39.     else
  40.       return tr[node] + query(lc+1, mid+1, r, idx);
  41.   }
  42.  
  43.   void update(int node, int l, int r, int ql, int qr, int val) {
  44.     if (r < l or qr < l or r < ql) return;
  45.     if (ql <= l and r <= qr) return void(tr[node] += val);
  46.     int lc = node << 1;
  47.     int mid = l + (r - l) / 2;
  48.     update(lc, l, mid, ql, min(mid, qr), val);
  49.     update(lc+1, mid+1, r, max(mid+1, ql), qr, val);
  50.   }
  51.  
  52.   void update(int l, int r, int val) {
  53.     return update(1, 1, N, l, r, val);
  54.   }
  55.  
  56.   int query(int idx) {
  57.     return query(1, 1, N, idx);
  58.   }
  59. };
  60.  
  61. struct SegTreeMax {
  62.   int N;
  63.   vector<int> tr;
  64.  
  65.   void init(int n, vector<int> &v) {
  66.     N = n;
  67.     tr.assign(n << 2, 0);
  68.     build(1, 1, n, v);
  69.   }
  70.  
  71.   inline int join(int a, int b) {
  72.     return max(a, b);
  73.   }
  74.  
  75.   void build(int node, int l, int r, vector<int> &v) {
  76.     if (l == r) {
  77.       // tr[node] = -INF;
  78.       tr[node] = v[l];
  79.       return;
  80.     }
  81.     int lc = node << 1;
  82.     int mid = l + (r - l) / 2;
  83.     build(lc, l, mid, v);
  84.     build(lc + 1, mid + 1, r, v);
  85.     tr[node] = join(tr[lc], tr[lc+1]);
  86.   }
  87.  
  88.   void update(int node, int l, int r, int idx, int val) {
  89.     if (l == r) {
  90.       tr[node] = val;
  91.       return;
  92.     }
  93.     int lc = node << 1;
  94.     int mid = l + (r - l) / 2;
  95.     if (idx <= mid)
  96.       update(lc, l, mid, idx, val);
  97.     else
  98.       update(lc+1, mid+1, r, idx, val);
  99.     tr[node] = join(tr[lc], tr[lc+1]);
  100.   }
  101.  
  102.   int query(int node, int l, int r, int ql, int qr) {
  103.     if (r < l or qr < l or r < ql) return -INF;
  104.     if (ql <= l and r <= qr) return tr[node];
  105.     int lc = node << 1;
  106.     int mid = l + (r - l) / 2;
  107.     return join(query(lc, l, mid, ql, min(mid, qr)),
  108.       query(lc+1, mid+1, r, max(mid+1, ql), qr));
  109.   }
  110.  
  111.   void update(int idx, int val) {
  112.     return update(1, 1, N, idx, val);
  113.   }
  114.  
  115.   int query(int l, int r) {
  116.     return query(1, 1, N, l, r);
  117.   }
  118. };
  119.  
  120. int n;
  121. vector<vector<int>> gr, aux;
  122.  
  123. int timer;
  124. vector<int> h, sub, pos, dad;
  125.  
  126. SegTree st[2];
  127. SegTreeMax stMax[2];
  128.  
  129. vector<int> clr;
  130. vector<int> tr[2], trMax[2];
  131.  
  132. // st[0] -> armazena os tamanhos da subarvores de cor 0
  133. // st[1] -> armazena os tamanhos da subarvores de cor 1
  134. // stMax[0] -> armazena os índices onde está da cor 0
  135. // stMax[1] -> armazena os índices onde está da cor 1
  136.  
  137. void dfs(int u, int par = -1) {
  138.   sub[u] = 1;
  139.   for (int &to : gr[u]) if (to != par) {
  140.     dad[to] = u;
  141.     dfs(to, u);
  142.     sub[u] += sub[to];
  143.     if (sub[to] > sub[gr[u][0]] or gr[u][0] == par)
  144.       swap(to, gr[u][0]);
  145.   }
  146. }
  147.  
  148. void build_hld(int u, int par = -1) {
  149.   pos[u] = ++timer;
  150.   tr[0][pos[u]] = 1;
  151.   tr[1][pos[u]] = sub[u];
  152.   trMax[0][pos[u]] = -INF;
  153.   trMax[1][pos[u]] = pos[u];
  154.   // st[0].update(pos[u], pos[u], 1);
  155.   // st[1].update(pos[u], pos[u], sub[u]);
  156.   // stMax[0].update(pos[u], -INF);
  157.   // stMax[1].update(pos[u], pos[u]);
  158.   for (int to : gr[u]) if (to != par) {
  159.     h[to] = (to == gr[u][0] ? h[u] : to);
  160.     build_hld(to, u);
  161.   }
  162. }
  163.  
  164. int query(int o) {
  165.   // update_pos -> primeira posição de cor clr[o] ^ 1
  166.   // ou -INF caso não exista
  167.   int u = o, update_pos = -1;
  168.   while (u != -1) {
  169.     update_pos = stMax[clr[o] ^ 1].query(pos[h[u]], pos[u]);
  170.     if (update_pos != -INF)
  171.       break;
  172.  
  173.     o = h[u];
  174.     u = dad[o];
  175.     // cout << u << ' ' << o << '\n'; // 0 2
  176.     // cout << dad[o] << '\n'; // 0
  177.   }
  178.  
  179.   if (update_pos == -INF) {
  180.     // caso não exista, faz a query a partir do root
  181.     update_pos = 0;
  182.   } else {
  183.     if (update_pos == pos[u]) {
  184.       // caso update_pos seja o primeiro de uma chain
  185.       update_pos = pos[o];
  186.     } else {
  187.       // caso esteja no meio da chain, pega o filho
  188.       update_pos = update_pos + 1;
  189.     }
  190.   }
  191.  
  192.   return st[clr[o]].query(update_pos);
  193. }
  194.  
  195. void update(int o) {
  196.   // diminui da cor antiga
  197.   int sz = st[clr[o]].query(pos[o]);
  198.   int u = dad[o];
  199.   while (u != -1) {
  200.     int update_pos = stMax[clr[o] ^ 1].query(pos[h[u]], pos[u]);
  201.     st[clr[o]].update(update_pos == -INF ? pos[h[u]] : update_pos, pos[u], -sz);
  202.     if (update_pos != -INF) break;
  203.     u = dad[h[u]];
  204.   }
  205.  
  206.   stMax[clr[o]].update(pos[o], -INF);
  207.  
  208.   // muda cor
  209.   clr[o] ^= 1;
  210.  
  211.   stMax[clr[o]].update(pos[o], pos[o]);
  212.  
  213.   // aumenta da próxima cor
  214.   sz = st[clr[o]].query(pos[o]);
  215.   u = dad[o];
  216.   while (u != -1) {
  217.     int update_pos = stMax[clr[o] ^ 1].query(pos[h[u]], pos[u]);
  218.     st[clr[o]].update(update_pos == -INF ? pos[h[u]] : update_pos, pos[u], sz);
  219.     if (update_pos != -INF) break;
  220.     u = dad[h[u]];
  221.   }
  222. }
  223.  
  224. int main() {
  225.   cin.tie(0)->sync_with_stdio(0);
  226.  
  227.   cin >> n;
  228.  
  229.   gr.assign(n, vector<int>());
  230.   aux.assign(n, vector<int>());
  231.   clr.assign(n, 1);
  232.  
  233.   for (int i = 0; i < n-1; ++i) {
  234.     int a, b; cin >> a >> b, --a, --b;
  235.     gr[a].push_back(b);
  236.     gr[b].push_back(a);
  237.   }
  238.  
  239.   sub.assign(n, 0);
  240.   pos.assign(n, 0);
  241.   dad.assign(n, -1);
  242.   h.assign(n, 0);
  243.  
  244.   tr[0].assign(n + 1, 0);
  245.   tr[1].assign(n + 1, 0);
  246.   trMax[0].assign(n + 1, -INF);
  247.   trMax[1].assign(n + 1, -INF);
  248.  
  249.   dfs(0);
  250.   build_hld(0);
  251.  
  252.   // for (int i = 1; i <= n; ++i) {
  253.   //   cout << tr[0][i] << " \n"[i==n];
  254.   // }
  255.  
  256.   // for (int i = 1; i <= n; ++i) {
  257.   //   cout << tr[1][i] << " \n"[i==n];
  258.   // }
  259.  
  260.   st[0].init(n, tr[0]);
  261.   st[1].init(n, tr[1]);
  262.   stMax[0].init(n, trMax[0]);
  263.   stMax[1].init(n, trMax[1]);
  264.  
  265.   // for (int i = 1; i <= n; ++i) {
  266.   //   cout << st[0].query(i) << " \n"[i==n];
  267.   // }
  268.  
  269.   // for (int i = 1; i <= n; ++i) {
  270.   //   cout << st[1].query(i) << " \n"[i==n];
  271.   // }
  272.  
  273.   int m; cin >> m;
  274.   while (m--) {
  275.     int t, u; cin >> t >> u, --u;
  276.     if (t == 0) {
  277.       // subir enquanto tiver a mesma cor e depois pegar ans
  278.       cout << query(u) << '\n';
  279.     } else {
  280.       // mudar cor do atual, e atualizar os ancestrais
  281.       update(u);
  282.     }
  283.   }
  284. }
  285. /*
  286. 5
  287. 1 2
  288. 1 3
  289. 1 4
  290. 1 5
  291. 5
  292. 0 1
  293. 0 2
  294. 0 3
  295. 0 4
  296. 0 5
  297.  
  298. */
Advertisement
Add Comment
Please, Sign In to add comment