【题目大意】
一颗无根树,每个节点有权值,每次提问x,y,z,回答节点x到y的唯一路径上xor z的最大值。
【分析】
Trie保存每个2进制位,然后类似贪心的遍历一次即可,遍历的时候,用x,y,lca,falca的各个版本来维护是否有串即可。
【代码】
/***********************
ID:Ciocio
LANG:C++
DATE:2014-1-23
TASK:Tree
***********************/
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <iostream>
#include <algorithm>
#include <queue>
using namespace std;
#define MAXN 100005
#define MAXQ 100005
struct Tree{
Tree* lc;
int sz;
Tree* rc;
};
Tree Pool[50*MAXN];
Tree* New;
Tree* P[MAXN];
int N,Q,logn;
int Last[MAXN],Next[MAXN<<1],Y[MAXN<<1];
int val[MAXN],Dep[MAXN],Fa[MAXN*2][20];
void _read(int &x){
char tt=getchar();
while(tt<'0'||'9'<tt) tt=getchar();
for(x=0;'0'<=tt&&tt<='9';x=(x<<1)+(x<<3)+tt-'0',tt=getchar());
}
int totM;
void _addedge(int u,int v){
Y[++totM]=v;Next[totM]=Last[u];
Last[u]=totM;
}
void _init(){
for(int i=1;i<=N;i++) _read(val[i]);
int u,v;
for(int i=1;i<N;i++){
_read(u);_read(v);
_addedge(u,v);
_addedge(v,u);
}
}
Tree* null;
Tree* Get(Tree* lc,int sz,Tree* rc){
New->lc=lc;
New->sz=sz;
New->rc=rc;
return New++;
}
Tree* Insert(Tree* T,int num,int i){
if(i==-1) return Get(null,T->sz+1,null);
if((num>>i)&1)
return Get(Insert(T->lc,num,i-1),T->sz+1,T->rc);
else
return Get(T->lc,T->sz+1,Insert(T->rc,num,i-1));
}
void _Dfs(int u,int fa){
Fa[u][0]=fa;
P[u]=Insert(P[fa],val[u],15);
for(int j=Last[u];j;j=Next[j]){
int v=Y[j];
if(v!=fa) _Dfs(v,u);
}
}
void _pre_lca(int x){
Dep[x]=Dep[Fa[x][0]]+1;
for(int i=1;i<=15;i++) Fa[x][i]=Fa[Fa[x][i-1]][i-1];
for(int j=Last[x];j;j=Next[j])
if(Y[j]!=Fa[x][0])
_pre_lca(Y[j]);
}
int _Lca(int x,int y){
if(Dep[x]<Dep[y]) swap(x,y);
int k=Dep[x]-Dep[y];
for(int i=0;i<=logn;i++)
if((k>>i)&1)
x=Fa[x][i];
if(x==y) return x;
k=ceil(log2(Dep[x]));
for(int i=k;i>=0;i--)
if(Fa[x][i]!=Fa[y][i]){
x=Fa[x][i];
y=Fa[y][i];
}
return Fa[x][0];
}
int Search(Tree* x,Tree* y,Tree* flca,Tree* lca,int key,int i){
if(i==-1) return 0;
int lc_sz=x->lc->sz+y->lc->sz-flca->lc->sz-lca->lc->sz;
int rc_sz=x->rc->sz+y->rc->sz-flca->rc->sz-lca->rc->sz;
int tmp=((key>>i)&1);
if(tmp==0){
if(lc_sz!=0) return (1<<i)+Search(x->lc,y->lc,flca->lc,lca->lc,key,i-1);
return Search(x->rc,y->rc,flca->rc,lca->rc,key,i-1);
}
else{
if(rc_sz!=0) return (1<<i)+Search(x->rc,y->rc,flca->rc,lca->rc,key,i-1);
return Search(x->lc,y->lc,flca->lc,lca->lc,key,i-1);
}
}
void _solve(){
_Dfs(1,0);
_pre_lca(1);
int x,y,z,lca;
while(Q--){
_read(x);_read(y);_read(z);
lca=_Lca(x,y);
printf("%d\n",Search(P[x],P[y],P[Fa[lca][0]],P[lca],z,15));
}
}
int main(){
while(scanf("%d%d",&N,&Q)!=EOF){
logn=ceil(log2(N));
memset(Last,0,sizeof Last);
memset(Pool,0,sizeof Pool);
memset(P,0,sizeof P);
totM=0;
New=Pool;
null=Get(0,0,0);
null->lc=null;
null->rc=null;
P[0]=null;
_init();
_solve();
}
return 0;
}