結果
問題 | No.1641 Tree Xor Query |
ユーザー | だれ |
提出日時 | 2021-08-06 22:23:59 |
言語 | C++17 (gcc 13.3.0 + boost 1.87.0) |
結果 |
AC
|
実行時間 | 98 ms / 5,000 ms |
コード長 | 6,795 bytes |
コンパイル時間 | 3,681 ms |
コンパイル使用メモリ | 179,508 KB |
最終ジャッジ日時 | 2025-01-23 15:47:09 |
ジャッジサーバーID (参考情報) |
judge2 / judge4 |
(要ログイン)
ファイルパターン | 結果 |
---|---|
sample | AC * 3 |
other | AC * 18 |
ソースコード
#include <algorithm> #include <bitset> #include <cassert> #include <cmath> #include <cstdio> #include <fstream> #include <functional> #include <iomanip> #include <iostream> #include <iterator> #include <map> #include <numeric> #include <queue> #include <set> #include <sstream> #include <stack> #include <unordered_set> using namespace std; #if __has_include(<atcoder/all>) #include <atcoder/all> using namespace atcoder; #endif #define GET_MACRO(_1, _2, _3, NAME, ...) NAME #define _rep(i, n) _rep2(i, 0, n) #define _rep2(i, a, b) for(int i = (int)(a); i < (int)(b); i++) #define rep(...) GET_MACRO(__VA_ARGS__, _rep2, _rep)(__VA_ARGS__) #define all(x) (x).begin(), (x).end() #define rall(x) (x).rbegin(), (x).rend() using i64 = long long; template<class T, class U> bool chmin(T& a, const U& b) { return (b < a) ? (a = b, true) : false; } template<class T, class U> bool chmax(T& a, const U& b) { return (b > a) ? (a = b, true) : false; } template<typename T>istream& operator>>(istream&i,vector<T>&v){rep(j,v.size())i>>v[j];return i;} template<typename T>string join(vector<T>&v){stringstream s;rep(i,v.size())s<<' '<<v[i];return s.str().substr(1);} template<typename T>ostream& operator<<(ostream&o,vector<T>&v){if(v.size())o<<join(v);return o;} template<typename T>string join(vector<vector<T>>&vv){string s="\n";rep(i,vv.size())s+=join(vv[i])+"\n";return s;} template<typename T>ostream& operator<<(ostream&o,vector<vector<T>>&vv){if(vv.size())o<<join(vv);return o;} template<class T, T (*op) (T, T), T (*e)()> struct SegmentTree { private: std::vector<T> data; int _n, size; void update(int k) { data[k] = op(data[k << 1], data[k << 1 | 1]); } public: SegmentTree(int n) : SegmentTree(std::vector<T>(n, e())) {} SegmentTree(const std::vector<T>& v) : size(int(v.size())) { for (_n = 1; _n < size; _n *= 2); data.resize(2 * _n, e()); for (int i = 0; i < size; i++) data[i + _n] = v[i]; for (int i = _n - 1; i > 0; i--) update(i); } void set(int i, const T x) { assert(0 <= i && i < size); i += _n; data[i] = x; while (i > 1) { i >>= 1; update(i); } } void add(int i, const T x) { assert(0 <= i && i < size); i += _n; data[i] += x; while (i > 1) { i >>= 1; update(i); } } T get(int i) { assert(0 <= i && i < size); return data[i + _n]; } T prod(int l, int r) { assert(0 <= l && l <= r && r <= size); T lf = e(), rf = e(); l += _n; r += _n; while(l < r) { if (l & 1) lf = op(lf, data[l++]); if (r & 1) rf = op(data[--r], rf); l >>= 1; r >>= 1; } return op(lf, rf); } T all_prod() const { return data[1]; } template<bool (*f) (T, T)> int min_left(int l, int r, T target) { assert(0 <= l && l <= r && r <= size); int nr = r; l += _n; r += _n; vector<int> lv, rv; while (l < r) { if (l & 1) { lv.push_back(l++); } if (r & 1) { rv.push_back(--r); } l >>= 1; r >>= 1; } while (!rv.empty()) { lv.push_back(rv.back()); rv.pop_back(); } T now = e(); for (auto i: lv) { if (f(op(now, data[i]), target)) { while (true) { if(f(op(now, data[i]), target)) { if (i >= _n) return i - _n; i <<= 1; } else now = op(now, data[i++]); } } else now = op(now, data[i]); } return nr; } template<bool (*f) (T, T)> int max_right(int l, int r, T target) { assert(0 <= l && l <= r && r <= size); int nl = l; l += _n; r += _n; vector<int> lv, rv; while (l < r) { if (l & 1) { lv.push_back(l++); } if (r & 1) { rv.push_back(--r); } l >>= 1; r >>= 1; } while (!lv.empty()) { rv.push_back(lv.back()); lv.pop_back(); } T now = e(); for (auto i: rv) { if (f(op(data[i], now), target)) { while (true) { if(f(op(data[i], now), target)) { if (i >= _n) return i - _n; i <<= 1; i++; } else now = op(data[i--], now); } } else now = op(data[i], now); } return nl; } }; vector<int> c; vector<vector<int>> edge; vector<int> dp; vector<int> in, out; int k; void dfs(int now, int p){ in[now] = k; dp[k] = c[now]; k++; for (auto e: edge[now]){ if (e == p) continue; dfs(e, now); } out[now] = k++; return; } int op(int a, int b){ return a ^ b; } int e(){ return 0; } int main(){ cin.tie(nullptr); ios::sync_with_stdio(false); int n, q; cin >> n >> q; c.resize(n); cin >> c; edge.resize(n); dp.resize(2 * n + 10); in.resize(n); out.resize(n); rep(i, n - 1){ int a, b; cin >> a >> b; a--, b--; edge[a].emplace_back(b); edge[b].emplace_back(a); } dfs(0, -1); vector<int> ans; SegmentTree<int, op, e> seg(dp); while (q--){ int t, x, y; cin >> t >> x >> y; x--; if (t == 1){ seg.set(in[x], seg.get(in[x]) ^ y); } else{ ans.emplace_back(seg.prod(in[x], out[x])); } } for (auto i: ans) cout << i << "\n"; }