hdu 4757
树链剖分 + 可持久化trie树
到现在才有点大彻大悟,可持久化trie的作用就是可以查询到历史版本, 那么既然可以,最最暴力的做法,就是每一个点都建立一个新的,这个新的版本既包含旧版本, 也包含最新的结点, 但是空间复杂度实在是不敢恭维, 故大佬们想的做法就是在暴力的基础上进行修改, 每个点依旧建立新版本, 但是只建立之前旧版本没有的东西, 然后再把旧版本和这个空间占用上面很小的结点联系起来, 这样既降低了空间复杂度, 还能新老版本一块使用, 每个结点都代表一个新版本 , 然后还和旧版本连接在一起,例如rt[x] ,表示第x个结点所在的新版本, 那么这个rt[x] , 里面只存储了这个新版本的信息和x - 1 的联系, 然后rt[x - 1] 存储的是x - 1 这个新版本的信息, 链接的是x - 2 ,这个旧版本,所以这样就实现了可持久化数据结构,
然后就在处理好树链剖分的树上结构进行可持久化trie树,
建立的话旧版本就是父亲结点, 新版本就是孩子结点了。
#include <bits/stdc++.h>
using namespace std ;
const int N = 1e5 + 10 ;
int e[N << 1] , ne[N << 1] , num[N << 5] , h[N << 1] , size[N <<2] , son[N << 2] , ch[N << 5][2] ;
int n , m , idx , cnt ;
int fa[N << 1] , deep[N << 1] , top[N << 1] , rt[N << 1] , val[N<< 1];
void dfs1(int u , int f , int d)
{
size[u] = 1 , son[u] = 0 , fa[u] = f , deep[u] = d;
for(int i = h[u] ; ~i ;i = ne[i])
{
int v = e[i] ;
if(v == f) continue ;
dfs1(v , u , d + 1 ) ;
size[u] += size[v] ;
if(!son[u] || size[son[u]] < size[v])
son[u] = v ;
}
}
void dfs2(int u , int tp)
{
top[u] = tp ;
if(!son[u]) return ;
dfs2(son[u] , tp) ;
for(int i = h[u] ; ~i ; i = ne[i])
{
int v = e[i] ;
if(v == fa[u] || v == son[u]) continue ;
dfs2(v , v) ;
}
}
int lca(int x , int y)
{
while(top[x] != top[y])
{
if(deep[top[x]] < deep[top[y]])
swap(x , y) ;
x = fa[top[x]] ;
}
return deep[x] > deep[y] ? y : x ;
}
void add(int a, int b)
{
e[idx] = b , ne[idx] = h[a] , h[a] = idx ++ ;
}
void insert(int last , int &now , int x)
{
now = ++ cnt ;
int p = now ;
for(int i = 30 ;i >= 0;i --)
{
int id = (x >> i) & 1 ;
ch[p][id] = ++ cnt ;
ch[p][id ^ 1] = ch[last][id ^ 1] ;
num[p] = num[last] + 1;
p = ch[p][id] , last = ch[last][id] ;
}
num[p] = num[last] + 1 ;
}
void dfs(int u)
{
insert(rt[fa[u]] , rt[u] , val[u]) ;
for(int i = h[u] ; ~i ;i = ne[i])
{
int v = e[i] ;
if(v == fa[u])
continue ;
dfs(v) ;
}
}
int ask(int x , int y , int z , int v)
{
int res = v ^ val[z] , ans = 0 ;
z = rt[z] ;
for(int i = 30 ;i >= 0 ;i --)
{
int id = (v >> i) & 1 ;
int t = num[ch[x][id ^ 1]] + num[ch[y][id ^ 1]] - 2 * num[ch[z][id ^ 1]] ;
if(t > 0)
ans += 1 << i , id ^= 1 ;
x =ch[x][id] , y = ch[y][id] , z = ch[z][id] ;
}
return max(ans , res) ;
}
int main()
{
while(~scanf("%d%d" , &n , &m))
{
idx = 0 , cnt = 0 ;
memset(h , -1 , sizeof h) ;
for(int i = 1 ;i <= n ;i ++)
scanf("%d" , &val[i]) ;
for(int i = 1; i < n ;i ++)
{
int u , v ;
scanf("%d%d" , &u , &v) ;
add(u , v) , add(v , u) ;
}
dfs1(1 , 0 , 1) , dfs2(1 , 1) , dfs(1) ;
for(int i = 1; i <= m ;i ++)
{
int x , y , z ;
scanf("%d%d%d" , &x , &y , &z) ;
printf("%d
" , ask(rt[x] , rt[y] , lca(x , y) , z)) ;
}
}
return 0 ;
}