結果
問題 |
No.1641 Tree Xor Query
|
ユーザー |
![]() |
提出日時 | 2025-05-20 22:42:29 |
言語 | C++23 (gcc 13.3.0 + boost 1.87.0) |
結果 |
AC
|
実行時間 | 330 ms / 5,000 ms |
コード長 | 4,526 bytes |
コンパイル時間 | 5,461 ms |
コンパイル使用メモリ | 334,072 KB |
実行使用メモリ | 30,848 KB |
最終ジャッジ日時 | 2025-05-20 22:42:38 |
合計ジャッジ時間 | 8,197 ms |
ジャッジサーバーID (参考情報) |
judge4 / judge2 |
(要ログイン)
ファイルパターン | 結果 |
---|---|
sample | AC * 3 |
other | AC * 18 |
ソースコード
#include <bits/stdc++.h> #include <atcoder/all> using namespace std; #define rep(i, n) for (long long i = 0; i < (long long)(n); i++) #define FOR(i, s, e) for (long long i = (long long)(s); i <= (long long)(e); i++) #define printYesNo(is_ok) puts(is_ok ? "Yes" : "No"); #define SORT(v) sort(v.begin(), v.end()); #define RSORT(v) sort(v.rbegin(), v.rend()); #define REVERSE(v) reverse(v.begin(), v.end()); class HeavyLightDecomposition { public: HeavyLightDecomposition(int n) : n(n), edges(n), parent(n, -1), depth(n, 0), heavy(n, -1), head(n), in_time(n), sz(n), built(false) { } void add_edge(int u, int v) { assert(0 <= u && u < n); assert(0 <= v && v < n); edges[u].push_back(v); edges[v].push_back(u); } void build(int root = 0) { assert(0 <= root && root < n); if (built) { return; } parent[root] = -1; depth[root] = 0; dfs_size(root); int time = 0; decompose(root, root, time); built = true; } vector<array<int, 2>> get_path_ranges(int u, int v) { assert(0 <= u && u < n); assert(0 <= v && v < n); ensure_built(); vector<array<int, 2>> ranges; while (head[u] != head[v]) { if (depth[head[v]] < depth[head[u]]) { ranges.push_back({in_time[head[u]], in_time[u] + 1}); u = parent[head[u]]; } else { ranges.push_back({in_time[head[v]], in_time[v] + 1}); v = parent[head[v]]; } } if (depth[v] < depth[u]) { swap(u, v); } ranges.push_back({in_time[u], in_time[v] + 1}); return ranges; } array<int, 2> get_subtree_range(int u) { assert(0 <= u && u < n); ensure_built(); return {in_time[u], in_time[u] + sz[u]}; } int lca(int u, int v) { assert(0 <= u && u < n); assert(0 <= v && v < n); ensure_built(); while (head[u] != head[v]) { if (depth[head[u]] > depth[head[v]]) { swap(u, v); } v = parent[head[v]]; } return depth[u] < depth[v] ? u : v; } int get_in_time(int v) { assert(0 <= v && v < n); ensure_built(); return in_time[v]; } int get_subtree_size(int u) { assert(0 <= u && u < n); ensure_built(); return sz[u]; } private: int n; vector<vector<int>> edges; vector<int> parent, depth, heavy, head, in_time, sz; bool built; void ensure_built() { if (!built) { build(); } } int dfs_size(int v) { sz[v] = 1; int max_size = 0; for (int u : edges[v]) { if (u == parent[v]) { continue; } parent[u] = v; depth[u] = depth[v] + 1; int sub = dfs_size(u); sz[v] += sub; if (sub > max_size) { max_size = sub; heavy[v] = u; } } return sz[v]; } void decompose(int v, int h, int &time) { head[v] = h; in_time[v] = time++; if (heavy[v] != -1) { decompose(heavy[v], h, time); } for (int u : edges[v]) { if (u == parent[v] || u == heavy[v]) { continue; } decompose(u, u, time); } } }; using S = int; S op(S a, S b) { return a ^ b; } S e() { return 0; } int main() { int N, Q; cin >> N >> Q; vector<int> C(N); rep(i, N) { cin >> C[i]; } HeavyLightDecomposition hld(N); rep(i, N - 1) { int a, b; cin >> a >> b; hld.add_edge(a - 1, b - 1); } hld.build(); atcoder::segtree<S, op, e> seg(N); rep(i, N) { seg.set(hld.get_in_time(i), C[i]); } rep(_, Q) { int T, x, y; cin >> T >> x >> y; x--; if (T == 1) { int xi = hld.get_in_time(x); seg.set(xi, seg.get(xi) ^ y); } if (T == 2) { auto [l, r] = hld.get_subtree_range(x); cout << seg.prod(l, r) << endl; } } return 0; };