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<unsigned long long> 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<unsigned long long> &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]) {
- st[p] = (r - l + 1) * lz[p];
- if(l != r) {
- lz[2 * p] = lz[p];
- lz[2 * p + 1] = lz[p];
- }
- lz[p] = 0;
- }
- }
- unsigned long long query(int i, int j) {
- return query(i, j, 1, 1, n);
- }
- unsigned 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, unsigned long long v) {
- update(i, j, v, 1, 1, n);
- }
- void update(int i, int j, unsigned long long 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];
- }
- };
- template <bool EDGE> struct HLD {
- vector<vector<int>> g1;
- vector<vector<pair<int, int>>> g2;
- vector<int> pos, sz, par, h;
- vector<unsigned long long> v, w, sobe;
- seg_tree seg;
- int t;
- HLD(int n) {
- if(EDGE) {
- g2.resize(n + 3);
- } else {
- g1.resize(n + 3);
- }
- pos.resize(n + 3); sz.resize(n + 3); par.resize(n + 3);
- if(EDGE) {
- sobe.resize(n + 3);
- } else {
- w.resize(n + 3);
- }
- h.resize(n + 3); v.resize(n + 3);
- }
- void build_hld(int k, int p = -1, int f = 1) {
- v[pos[k] = t++] = (EDGE ? sobe : w)[k]; sz[k] = 1;
- for(int i = 0; i < (int)(EDGE ? g2[k].size() : g1[k].size()); i++) {
- if((EDGE and g2[k][i].first != p) or (!EDGE and g1[k][i] != p)) {
- if(EDGE) {
- sobe[g2[k][i].first] = g2[k][i].second; par[g2[k][i].first] = k;
- h[g2[k][i].first] = (g2[k][i] == g2[k][0] ? h[k] : g2[k][i].first);
- build_hld(g2[k][i].first, k, f); sz[k] += sz[g2[k][i].first];
- if(sz[g2[k][i].first] > sz[g2[k][0].first] or g2[k][0].first == p) {
- swap(g2[k][i], g2[k][0]);
- }
- } else {
- par[g1[k][i]] = k;
- h[g1[k][i]] = (g1[k][i] == g1[k][0] ? h[k] : g1[k][i]);
- build_hld(g1[k][i], k, f);
- sz[k] += sz[g1[k][i]];
- if(sz[g1[k][i]] > sz[g1[k][0]] or g1[k][0] == p) {
- swap(g1[k][i], g1[k][0]);
- }
- }
- }
- }
- if(p * f == -1) {
- t = 1;
- build_hld(h[k] = k, -1, 0);
- }
- }
- void add(int a, int b) {
- g1[a].push_back(b);
- g1[b].push_back(a);
- }
- void add(int a, int b, int x) {
- g2[a].push_back({b, x});
- g2[b].push_back({a, x});
- }
- void build(int root = 1) {
- t = 1;
- build_hld(root);
- seg = seg_tree(v);
- }
- unsigned long long query_path(int a, int b) {
- if(EDGE and a == b) return 0;
- if(pos[a] < pos[b]) swap(a, b);
- if(h[a] == h[b]) return seg.query(pos[b] + EDGE, pos[a]);
- return seg.query(pos[h[a]], pos[a]) + query_path(par[h[a]], b);
- }
- void update_path(int a, int b, unsigned long long x) {
- if(EDGE and a == b) return;
- if(pos[a] < pos[b]) swap(a, b);
- if(h[a] == h[b]) {
- seg.update(pos[b] + EDGE, pos[a], x);
- return;
- }
- seg.update(pos[h[a]], pos[a], x);
- update_path(par[h[a]], b, x);
- }
- unsigned long query_subtree(int a) {
- if(EDGE and sz[a] == 1) return 0;
- return seg.query(pos[a] + EDGE, pos[a] + sz[a] - 1);
- }
- void update_subtree(int a, int x) {
- if(EDGE and sz[a] == 1) return;
- seg.update(pos[a] + EDGE, pos[a] + sz[a] - 1, x);
- }
- };
- using ull = unsigned long long;
- random_device rd;
- mt19937 gen(rd());
- uniform_int_distribution<ull> distrib(0, ULLONG_MAX);
- int main() {
- ios_base::sync_with_stdio(false);
- cin.tie(nullptr);
- int t;
- cin >> t;
- while(t--) {
- int n, q;
- cin >> n >> q;
- vector<unsigned long long> v(n + 3);
- vector<unsigned long long> hsh(n + 1), perm(n + 1);
- set<unsigned long long> st;
- for(int i = 1; i <= n; i++) {
- cin >> v[i];
- hsh[i] = distrib(gen);
- perm[i] = perm[i - 1] + hsh[i];
- st.insert(perm[i]);
- }
- HLD<false> hld(n);
- for(int i = 1; i <= n; i++) hld.w[i] = hsh[v[i]];
- for(int i = 1; i < n; i++) {
- int a, b;
- cin >> a >> b;
- hld.add(a, b);
- }
- hld.build();
- while(q--) {
- int t, a, b;
- cin >> t >> a >> b;
- if(t == 1) {
- unsigned long long x = hld.query_path(a, b);
- cout << (st.find(x) != st.end() ? "Yes\n" : "No\n");
- } else {
- hld.update_path(a, a, hsh[b]);
- }
- }
- }
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment