P4592 [TJOI2018]异或

Problem

  • 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 ;
}
posted @ 2019-10-31 16:16  _Isaunoya  阅读(136)  评论(0编辑  收藏  举报