1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151
| #include <cstdio> #include <stack> #define ls tree[O << 1] #define rs tree[O << 1 | 1]
typedef unsigned long long ull; const ull MAXULL = 18446744073709551615ull; struct Edge { int to, nxt; } e[200005]; int In[100005], son[100005], sze[100005], top[100005], fa[100005], cnt, tot; int dep[100005], head[100005], opt[100005], id[100005], n, m, k; ull val[100005]; struct Node { int l, r; ull lv0, lv1, rv0, rv1; } tree[400005]; struct Data { ull lv0, lv1, rv0, rv1; Data(ull lv0 = 0ull, ull lv1 = 0ull, ull rv0 = 0ull, ull rv1 = 0ull): lv0(lv0), lv1(lv1), rv0(rv0), rv1(rv1){} inline void operator = (const Data a) { lv0 = a.lv0, lv1 = a.lv1, rv0 = a.rv0, rv1 = a.rv1; } }; std::stack<Data> s; inline void AddEdge(int u, int v) { e[++ tot].to = v, e[tot].nxt = head[u], head[u] = tot; } void dfs1(int u) { sze[u] = 1, dep[u] = dep[fa[u]] + 1; for (int i = head[u]; i; i = e[i].nxt) if (e[i].to != fa[u]) { int v = e[i].to; fa[v] = u, dfs1(v), sze[u] += sze[v]; if (sze[v] > sze[son[u]]) son[u] = v; } } void dfs2(int u) { id[In[u] = ++ cnt] = u; if (son[u]) top[son[u]] = top[u], dfs2(son[u]); for (int i = head[u]; i; i = e[i].nxt) if (e[i].to != fa[u] && e[i].to != son[u]) top[e[i].to] = e[i].to, dfs2(e[i].to); }
inline void pushup(int O) { tree[O].lv0 = (ls.lv0 & rs.lv1) | (~ls.lv0 & rs.lv0); tree[O].lv1 = (ls.lv1 & rs.lv1) | (~ls.lv1 & rs.lv0); tree[O].rv0 = (rs.rv0 & ls.rv1) | (~rs.rv0 & ls.rv0); tree[O].rv1 = (rs.rv1 & ls.rv1) | (~rs.rv1 & ls.rv0); } inline void calcleaf(int O) { int x = id[tree[O].l]; if (opt[x] == 1) tree[O].lv0 = tree[O].rv0 = 0, tree[O].lv1 = tree[O].rv1 = val[x]; else if (opt[x] == 2) tree[O].lv0 = tree[O].rv0 = val[x], tree[O].lv1 = tree[O].rv1 = MAXULL; else tree[O].lv0 = tree[O].rv0 = val[x], tree[O].lv1 = tree[O].rv1 = ~val[x]; } void make_tree(int O, int L, int R) { tree[O].l = L, tree[O].r = R; if (tree[O].l != tree[O].r) { make_tree(O << 1, L, L + R >> 1); make_tree(O << 1 | 1, (L + R >> 1) + 1, R); pushup(O); } else calcleaf(O); } void update(int O, int p, int nopt, ull nval) { if (tree[O].l == tree[O].r) { opt[id[tree[O].l]] = nopt, val[id[tree[O].l]] = nval, calcleaf(O); return; } int mid = tree[O].l + tree[O].r >> 1; if (p <= mid) update(O << 1, p, nopt, nval); else update(O << 1 | 1, p, nopt, nval); pushup(O); } Data query(int O, int L, int R) { if (L > R) return Data(0, MAXULL, 0, MAXULL); if (L <= tree[O].l && tree[O].r <= R) return Data(tree[O].lv0, tree[O].lv1, tree[O].rv0, tree[O].rv1); int mid = tree[O].l + tree[O].r >> 1; if (R <= mid) return query(O << 1, L, R); if (mid < L) return query(O << 1 | 1, L, R); Data Ls = query(O << 1, L, R), Rs = query(O << 1 | 1, L, R), ans; ans.lv0 = (Ls.lv0 & Rs.lv1) | (~Ls.lv0 & Rs.lv0); ans.lv1 = (Ls.lv1 & Rs.lv1) | (~Ls.lv1 & Rs.lv0); ans.rv0 = (Rs.rv0 & Ls.rv1) | (~Rs.rv0 & Ls.rv0); ans.rv1 = (Rs.rv1 & Ls.rv1) | (~Rs.rv1 & Ls.rv0); return ans; }
int LCA(int u, int v) { while (top[u] != top[v]) { if (dep[top[u]] < dep[top[v]]) u ^= v ^= u ^= v; u = fa[top[u]]; } return dep[u] < dep[v] ? u : v; } int getson(int lca, int u) { int lst = u; while (top[u] != top[lca]) lst = top[u], u = fa[top[u]]; return u == lca ? lst : son[lca]; } ull Query(int u, int v, ull lim) { int lca = LCA(u, v), y = getson(lca, v); ull ans0 = 0ull, ans1 = MAXULL, ans = 0ull; Data tmp; while (top[u] != top[lca]) { tmp = query(1, In[top[u]], In[u]); ans0 = (ans0 & tmp.rv1) | (~ans0 & tmp.rv0); ans1 = (ans1 & tmp.rv1) | (~ans1 & tmp.rv0); u = fa[top[u]]; } tmp = query(1, In[lca], In[u]); ans0 = (ans0 & tmp.rv1) | (~ans0 & tmp.rv0); ans1 = (ans1 & tmp.rv1) | (~ans1 & tmp.rv0); if (v != lca) { while (top[v] != top[y]) s.push(query(1, In[top[v]], In[v])), v = fa[top[v]]; s.push(query(1, In[y], In[v])); } while (s.size()) { ans0 = (ans0 & s.top().lv1) | (~ans0 & s.top().lv0); ans1 = (ans1 & s.top().lv1) | (~ans1 & s.top().lv0); s.pop(); } ull now = lim; for (int i = k - 1; i >= 0; -- i) if ((ans1 & 1ull << i) > (ans0 & 1ull << i) && now >= 1ull << i) ans += 1ull << i, now -= 1ull << i; else ans += ans0 & 1ull << i; return ans; }
signed main() { scanf("%d%d%d", &n, &m, &k); for (int i = 1; i <= n; ++ i) scanf("%d%llu", opt + i, val + i); for (int i = 1, u, v; i < n; ++ i) scanf("%d%d", &u, &v), AddEdge(u, v), AddEdge(v, u); dfs1(1), top[1] = 1, dfs2(1); make_tree(1, 1, n); while (m --) { int type, x, y; ull z; scanf("%d%d%d%llu", &type, &x, &y, &z); if (type == 1) printf("%llu\n", Query(x, y, z)); else update(1, In[x], y, z); } return 0; }
|