P4592 [TJOI2018]异或
- 1 \(x,y\):查询节点\(x\)的子树中与\(y\)异或结果的最大值
- 2 \(x,y,z\):查询路径\(x\)到\(y\)上点与\(z\)异或结果最大值
看到区间异或的最大值 不难想到 可持久化trie
用树剖把这些剖成链 每次就是链的查询。。这样就可以了。
#include<bits/stdc++.h>
using namespace std ;
int n , q ;
const int N = 1e5 + 10 ;
struct node { int v , nxt ; } e[N << 1] ;
int val[N] ;
int head[N] , cnt = 0 ;
inline void add(int u , int v) { e[++ cnt] = { v , head[u] } ; head[u] = cnt ; }
int size[N] , son[N] , fa[N] , d[N] ;
inline void dfs1(int u) { size[u] = 1 ;
for(int i = head[u] ; i ; i = e[i].nxt) {
int v = e[i].v;
if(v == fa[u]) continue ;
fa[v] = u ; d[v] = d[u] + 1 ;
dfs1(v) ;
size[u] += size[v] ;
if(size[v] > size[son[u]]) son[u] = v ;
}
}
int top[N] , id[N] , idx = 0 , a[N] ;
inline void dfs2(int u , int t) {
top[u] = t ; id[u] = ++ idx ; a[idx] = val[u] ;
if(! son[u]) return ; dfs2(son[u] , t) ;
for(int i = head[u] ; i ; i = e[i].nxt) {
int v = e[i].v ;
if(v == fa[u]) continue ;
if(v == son[u]) continue ;
dfs2(v , v) ;
}
}
int tot = 0 ;
int t[N] ; int ch[N << 5][2] ;
int sz[N << 5] ;
inline void upd(int x , int p , int q) {
ch[p][0] = ch[q][0] ; ch[p][1] = ch[q][1] ; sz[p] = sz[q] + 1 ;
for(register int i = 29 ; ~ i ; i --) {
int c = (x >> i) & 1 ;
ch[p][c] = ++ tot ;
p = ch[p][c] ;
q = ch[q][c] ;
ch[p][0] = ch[q][0] ;
ch[p][1] = ch[q][1] ;
sz[p] = sz[q] + 1 ;
}
}
inline int query(int x , int p , int q) {
int res = 0 ;
for(register int i = 29 ; ~ i ; i --) {
int c = (x >> i) & 1 ;
if(sz[ch[q][c ^ 1]] - sz[ch[p][c ^ 1]]) res |= 1 << i , p = ch[p][c ^ 1] , q = ch[q][c ^ 1] ;
else p = ch[p][c] , q = ch[q][c] ;
} return res ;
}
inline int query_range(int x , int y , int val) {
int fx = top[x] , fy = top[y] ; int res = 0 ;
while(fx ^ fy) {
if(d[fx] < d[fy]) swap(x , y) , swap(fx , fy) ;
res = max(res , query(val , t[id[fx] - 1] , t[id[x]])) ;
x = fa[fx] , fx = top[x] ;
}
if(d[x] > d[y]) swap(x , y) ;
res = max(res , query(val , t[id[x] - 1] , t[id[y]])) ;
return res ;
}
signed main() {
ios :: sync_with_stdio(false) ;
cin.tie(nullptr) ;
cout.tie(nullptr) ;
cin >> n >> q ;
for(register int i = 1 ; i <= n ; i ++) cin >> val[i] ;
for(register int i = 1 ; i <= n - 1 ; i ++) {
int u , v ; cin >> u >> v ;
add(u , v) ; add(v , u) ;
} dfs1(1) ; dfs2(1 , 1) ;
for(register int i = 1 ; i <= n ; i ++) t[i] = ++ tot , upd(a[i] , t[i] , t[i - 1]) ;
for(register int i = 1 ; i <= q ; i ++) {
int opt ; cin >> opt ;
if(opt == 1) {
int x , y ;
cin >> x >> y ;
cout << query(y , t[id[x] - 1] , t[id[x] + size[x] - 1]) << '\n' ;
}
else {
int x , y , z ;
cin >> x >> y >> z ;
cout << query_range(x , y , z) << '\n' ;
}
}
return 0 ;
}