传送门:https://www.luogu.org/problem/show?pid=3613
【题解】
按二进制位分开,对于每一位,用“起床困难综合征”的方法贪心做。
写棵LCT,维护正反两种权值,每个维护2种,代表全0的输出和全1的输出。
然后直接上LCT即可。
权值的合并有点trick,可以参考代码,需要压位。
# include <stdio.h> # include <string.h> # include <iostream> # include <algorithm> // # include <bits/stdc++.h> using namespace std; typedef long long ll; typedef long double ld; typedef unsigned long long ull; const int M = 1e5 + 10; const int mod = 1e9+7; int n, m, K; struct node { ull p0, p1; node () {} node (ull p0, ull p1) : p0(p0), p1(p1) {} friend node operator + (node a, node b) { return node( (a.p0 & b.p1) | ((~a.p0) & b.p0), (a.p1 & b.p1) | ((~a.p1) & b.p0) ); } }; inline node deal(int op, ull x) { if(op == 1) return node(0, x); if(op == 2) return node(x, ull(-1)); if(op == 3) return node(x, ~x); } struct LCT { int ch[M][2], fa[M]; bool rev[M]; node w[M][2], val[M]; # define ls ch[x][0] # define rs ch[x][1] inline void up(int x) { if(!x) return ; w[x][0] = w[x][1] = val[x]; if(ls) w[x][0] = w[ls][0] + w[x][0], w[x][1] = w[x][1] + w[ls][1]; if(rs) w[x][0] = w[x][0] + w[rs][0], w[x][1] = w[rs][1] + w[x][1]; } inline void pushrev(int x) { if(!x) return ; rev[x] ^= 1; swap(ch[x][0], ch[x][1]); swap(w[x][0], w[x][1]); } inline void down(int x) { if(!x || !rev[x]) return ; pushrev(ls); pushrev(rs); rev[x] = 0; } # undef ls # undef rs inline bool isrt(int x) { return ch[fa[x]][0] != x && ch[fa[x]][1] != x; } inline void rotate(int x) { int y = fa[x], z = fa[y], ls = ch[y][1] == x, rs = ls^1; if(!isrt(y)) ch[z][ch[z][1] == y] = x; fa[ch[x][rs]] = y, fa[y] = x, fa[x] = z; ch[y][ls] = ch[x][rs]; ch[x][rs] = y; up(y); up(x); } int st[M]; inline void splay(int x) { int stn = 0, tx = x; while(!isrt(tx)) st[++stn] = tx, tx = fa[tx]; st[++stn] = tx; for (int i=stn; i; --i) down(st[i]); while(!isrt(x)) { int y = fa[x], z = fa[y]; if(!isrt(y)) { if((ch[z][0] == y)^(ch[y][0] == x)) rotate(x); else rotate(y); } rotate(x); } } inline int access(int x) { int t = 0; for (; x; t = x, x = fa[x]) { splay(x); ch[x][1] = t; up(x); } return t; } inline void makeroot(int x) { access(x); splay(x); pushrev(x); } inline void link(int x, int y) { makeroot(y); fa[y] = x; } }T; # define bit(x, i) (((x) >> (i)) & 1) int main() { // freopen("sleep.in", "r", stdin); // freopen("sleep.out", "w", stdout); scanf("%d%d%d", &n, &m, &K); for (int i=1, op; i<=n; ++i) { ull x; scanf("%d%llu", &op, &x); T.val[i] = T.w[i][0] = T.w[i][1] = deal(op, x); T.ch[i][0] = T.ch[i][1] = T.fa[i] = T.rev[i] = 0; } for (int i=1, u, v; i<n; ++i) { scanf("%d%d", &u, &v); T.link(u, v); } int op, x, y; ull z, tx, ty, ans, t; while(m--) { scanf("%d%d%d%llu", &op, &x, &y, &z); if(op == 1) { ans = 0; t = 0; T.makeroot(x); T.access(y); T.splay(y); tx = T.w[y][0].p0, ty = T.w[y][0].p1; for (int i=63; ~i; --i) { if(bit(tx, i)) ans |= (1ull << i); else if(bit(ty, i)) { if(t + (1ull << i) <= z) t = t + (1ull << i), ans |= (1ull << i); } } printf("%llu ", ans); } else { T.splay(x); T.val[x] = deal(y, z); T.up(x); } } return 0; }