[TJOI 2018] XOR
[题目链接]
https://www.lydsy.com/JudgeOnline/problem.php?id=5338
[算法]
首先对这棵树进行树链剖分
那么我们就将一个树上的问题转化为一个序列上的问题
建立可持久化字典树维护最大异或值即可
时间复杂度 : O(NlogN ^ 2)
[代码]
#include<bits/stdc++.h> using namespace std; typedef long long ll; typedef long double ld; typedef unsigned long long ull; const int N = 2e5 + 10; const int MAXLOG = 31; struct edge { int to , nxt; } e[N << 1]; int n , tot , timer , q; int head[N] , size[N] , top[N] , a[N] , perm[N] , l[N] , r[N] , son[N] , father[N] , depth[N] , rt[N]; struct Presitent_Trie { int sz; int child[N * MAXLOG][2] , latest[N * MAXLOG]; Presitent_Trie() { sz = 0; } inline void modify(int bit , int &now , int old , int x , int loc) { now = ++sz; child[now][0] = child[old][0] , child[now][1] = child[old][1]; latest[now] = loc; if (bit < 0) return; int value = 0; if (x & (1 << bit)) value = 1; modify(bit - 1 , child[now][value] , child[old][value] , x , loc); } inline int query(int bit , int now , int lft , int x) { if (bit < 0) return 0; int value = 1; if (x & (1 << bit)) value = 0; if (latest[child[now][value]] >= lft) return (1 << bit) + query(bit - 1 , child[now][value] , lft , x); else return query(bit - 1 , child[now][value ^ 1] , lft , x); } } PT; template <typename T> inline void chkmax(T &x,T y) { x = max(x,y); } template <typename T> inline void chkmin(T &x,T y) { x = min(x,y); } template <typename T> inline void read(T &x) { T f = 1; x = 0; char c = getchar(); for (; !isdigit(c); c = getchar()) if (c == '-') f = -f; for (; isdigit(c); c = getchar()) x = (x << 3) + (x << 1) + c - '0'; x *= f; } inline void addedge(int u , int v) { ++tot; e[tot] = (edge){v , head[u]}; head[u] = tot; } inline void dfs1(int u , int par) { size[u] = 1; depth[u] = depth[par] + 1; father[u] = par; for (int i = head[u]; i; i = e[i].nxt) { int v = e[i].to; if (v == par) continue; dfs1(v , u); size[u] += size[v]; if (size[v] > size[son[u]]) son[u] = v; } } inline void dfs2(int u , int t) { top[u] = t; l[u] = ++timer; if (son[u]) dfs2(son[u] , t); for (int i = head[u]; i; i = e[i].nxt) { int v = e[i].to; if (v == father[u] || v == son[u]) continue; dfs2(v , v); } r[u] = timer; } inline bool cmp(int x , int y) { return l[x] < l[y]; } inline int query(int x , int y , int z) { int ans = 0; while (top[x] != top[y]) { if (depth[top[x]] > depth[top[y]]) swap(x , y); chkmax(ans , PT.query(MAXLOG - 1 , rt[l[y]] , l[top[y]] , z)); y = father[top[y]]; } if (depth[x] > depth[y]) swap(x , y); chkmax(ans , PT.query(MAXLOG - 1 , rt[l[y]] , l[x] , z)); return ans; } int main() { read(n); read(q); for (int i = 1; i <= n; ++i) read(a[i]); for (int i = 1; i < n; ++i) { int x , y; read(x); read(y); addedge(x , y); addedge(y , x); } dfs1(1 , 0); dfs2(1 , 1); for (int i = 1; i <= n; ++i) perm[i] = i; sort(perm + 1 , perm + n + 1 , cmp); for (int i = 1; i <= n; ++i) PT.modify(MAXLOG - 1 , rt[i] , rt[i - 1] , a[perm[i]] , i); while (q--) { int type; read(type); if (type == 1) { int x , y; read(x); read(y); printf("%d\n" , PT.query(MAXLOG - 1 , rt[r[x]] , l[x] , y)); } else { int x , y , z; read(x); read(y); read(z); printf("%d\n" , query(x , y , z)); } } return 0; }