Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- //Слава Україні, Героям слава
- #include <bits/stdc++.h>
- using namespace std;
- struct seg_tree {
- //modify accordingly
- int n;
- vector<int> v, lz, st;
- void build() {
- build(1, 1, n);
- }
- void build(int p, int l, int r) {
- if(l == r) {
- st[p] = v[l];
- return;
- }
- build(2 * p, l, (l + r) >> 1);
- build(2 * p + 1, ((l + r) >> 1) + 1, r);
- st[p] = st[2 * p] + st[2 * p + 1];
- }
- seg_tree(int n_ = 1) {
- n = n_;
- lz.resize(4 * n);
- st.resize(4 * n);
- v.resize(n + 1);
- build();
- }
- seg_tree(vector<int> &v_) {
- v = v_;
- n = v.size();
- n--;
- lz.resize(4 * n);
- st.resize(4 * n);
- build();
- }
- void push(int p, int l, int r) {
- if(lz[p]) {
- if(l != r) {
- lz[2 * p] = lz[p];
- lz[2 * p + 1] = lz[p];
- }
- if(lz[p] == -1) lz[p] = 0;
- st[p] = (r - l + 1) * lz[p];
- lz[p] = 0;
- }
- }
- long long query(int i, int j) {
- return query(i, j, 1, 1, n);
- }
- long long query(int i, int j, int p, int l, int r) {
- push(p, l, r);
- if(l > j or r < i) {
- return 0;
- }
- if(l >= i and j >= r) {
- return st[p];
- }
- return query(i, j, 2 * p, l, (l + r) >> 1) + query(i, j, 2 * p + 1, ((l + r) >> 1) + 1, r);
- }
- void update(int i, int j, int v) {
- update(i, j, v, 1, 1, n);
- }
- void update(int i, int j, int v, int p, int l, int r) {
- push(p, l, r);
- if(l > j or r < i) {
- return;
- }
- if(l >= i and j >= r) {
- lz[p] = v;
- push(p, l, r);
- return;
- }
- update(i, j, v, 2 * p, l, (l + r) >> 1);
- update(i, j, v, 2 * p + 1, ((l + r) >> 1) + 1, r);
- st[p] = st[2 * p] + st[2 * p + 1];
- }
- };
- struct LCA {
- //one indexed shit
- int n, l;
- vector<vector<int>> adj, up;
- vector<int> h;
- LCA (int n_) {
- n = n_;
- l = 31 - __builtin_clz(n);
- adj.resize(n + 1);
- up.assign(n + 1, vector<int>(l + 1));
- h.resize(n + 1);
- }
- void add(int a, int b) {
- adj[a].push_back(b);
- adj[b].push_back(a);
- }
- void dfs(int v = 1, int p = 0, int hh = 0) {
- up[v][0] = p;
- for(int i = 1; i <= l; i++) {
- up[v][i] = up[up[v][i - 1]][i - 1];
- }
- for(auto u : adj[v]) {
- if(u != p) {
- dfs(u, v, hh + 1);
- }
- }
- h[v] = hh;
- }
- int lca(int a, int b) {
- if(h[a] > h[b]) {
- swap(a, b);
- }
- int dff = h[b] - h[a], cnt = 0;
- while(dff) {
- if(dff & 1) {
- b = up[b][cnt];
- }
- cnt++;
- dff >>= 1;
- }
- if(a == b) {
- return a;
- }
- for(int i = l; i >= 0; i--) {
- if(up[a][i] != up[b][i]) {
- a = up[a][i];
- b = up[b][i];
- }
- }
- return up[a][0];
- }
- int raise(int node, int dist) {
- //if it returns 0, then it fucked up
- int cnt = 0;
- while(dist) {
- if(dist & 1) {
- node = up[node][cnt];
- }
- cnt++;
- dist >>= 1;
- }
- return node;
- }
- int dist(int a, int b) {
- int z = lca(a, b);
- return h[a] + h[b] - 2 * h[z];
- }
- };
- struct HLD {
- vector<vector<int>> adj;
- vector<int> pos, sz, w, par, h, v;
- seg_tree seg;
- int t;
- HLD(int n) {
- adj.resize(n + 1);
- pos.resize(n + 1); sz.resize(n + 1); w.resize(n + 1); par.resize(n + 1);
- h.resize(n + 1); v.resize(n + 1);
- }
- void build_hld(int k, int p = -1, int f = 1) {
- v[pos[k] = t++] = w[k]; sz[k] = 1;
- for(auto &i : adj[k]) {
- if(i != p) {
- par[i] = k;
- h[i] = (i == adj[k][0] ? h[k] : i);
- build_hld(i, k, f);
- sz[k] += sz[i];
- if(sz[i] > sz[adj[k][0]] or adj[k][0] == p) {
- swap(i, adj[k][0]);
- }
- }
- }
- if(p * f == -1) {
- t = 1;
- build_hld(h[k] = k, -1, 0);
- }
- }
- void add(int a, int b) {
- adj[a].push_back(b);
- adj[b].push_back(a);
- }
- void build(int root = 1) {
- t = 1;
- build_hld(root);
- seg = seg_tree(v);
- }
- long long query_path(int a, int b) {
- if(pos[a] < pos[b]) swap(a, b);
- if(h[a] == h[b]) return seg.query(pos[b], pos[a]);
- return seg.query(pos[h[a]], pos[a]) + query_path(par[h[a]], b);
- }
- void update_path(int a, int b, int x) {
- if(pos[a] < pos[b]) swap(a, b);
- if(h[a] == h[b]) {
- seg.update(pos[b], pos[a], x);
- return;
- }
- seg.update(pos[h[a]], pos[a], x);
- update_path(par[h[a]], b, x);
- }
- long long query_subtree(int a) {
- return seg.query(pos[a], pos[a] + sz[a] - 1);
- }
- void update_subtree(int a, int x) {
- seg.update(pos[a], pos[a] + sz[a] - 1, x);
- }
- };
- int main() {
- ios_base::sync_with_stdio(false);
- cin.tie(nullptr);
- int n;
- cin >> n;
- LCA lca(n);
- HLD hld(n);
- vector<int> posl(n + 1), posr(n + 1);
- int t = 1;
- for(int i = 1; i < n; i++) {
- int a, b;
- cin >> a >> b;
- lca.add(a, b);
- hld.add(a, b);
- }
- lca.dfs();
- hld.build();
- function<int(int, int)> dfs = [&](int u, int p) {
- posl[u] = t;
- bool foi = false;
- for(auto e : lca.adj[u]) {
- if(e != p) {
- foi = true;
- posr[u] = max(posr[u], dfs(e, u));
- }
- }
- if(!foi) posr[u] = t++;
- return posr[u];
- };
- dfs(1, 0);
- seg_tree leaves(t);
- int q;
- cin >> q;
- while(q--) {
- int a, b;
- cin >> a >> b;
- if(a == 1) {
- int l = 0, r = lca.h[b], ans = 0;
- leaves.update(posl[b], posr[b], 1);
- hld.update_subtree(b, 1);
- while(l <= r) {
- int m = (l + r) >> 1;
- int mid = lca.raise(b, m);
- if(leaves.query(posl[mid], posr[mid]) == posr[mid] - posl[mid] + 1) {
- ans = mid;
- l = m + 1;
- } else {
- r = m - 1;
- }
- }
- hld.update_path(ans, b, 1);
- } else if(a == 2) {
- leaves.update(posl[b], posr[b], -1);
- hld.update_subtree(b, -1);
- hld.update_path(1, b, -1);
- } else {
- cout << hld.query_subtree(b) << "\n";
- }
- }
- return 0;
- }
Add Comment
Please, Sign In to add comment