HDU - 4757 Tree
题意:在树上每个节点都有一个权值,每次询问给出x,y和一个值z,求在树上点x到点y的路径上每个点的权值异或z之后的最大值。
思路:可持久化01字典树,利用LCA,即两段路径,x到LCA(a,b)和y到LCA(a,b),可以按dfs序来可持久化,比如root[i]可以接他的父亲即root[fa[i]]。挺有用的想法,应该可以扩展到树上主席树。
#include<iostream>
#include<cstdio>
#include<vector>
#include<cstring>
#include<algorithm>
using namespace std;
const int MAX_N=101000;
vector<int>edge[MAX_N];
int dp[MAX_N][20],have[MAX_N],d[MAX_N],N,log_2[MAX_N];
void dfs(int now){
int i;
for(i=0;i<edge[now].size();i++){
if(!have[edge[now][i]]){
have[edge[now][i]]=1;
dp[edge[now][i]][0]=now;
d[edge[now][i]]=d[now]+1;
dfs(edge[now][i]);
have[edge[now][i]]=0;
}
}
}
int LCA(int a,int b){
int k=log_2[N],i;
if(d[a]<d[b]){
int c=a;
a=b;
b=c;
}
while(d[a]!=d[b]){
for(i=k;i>=0;i--){
if(d[dp[a][i]]>=d[b])
a=dp[a][i];
}
}
if(a==b){
return b;
}
for(i=k;i>=0;i--){
if(dp[a][i]!=dp[b][i]){
a=dp[a][i];
b=dp[b][i];
}
}
return dp[a][0];
}
int trie[MAX_N*20][2],latest[MAX_N*20];
int s[MAX_N],root[MAX_N],tot;
void insert(int k,int k1,int val,int i,int deep){
if(deep<0){
latest[k1]=i;
return;
}
int x=(val>>deep)&1;
if(k)
trie[k1][x^1]=trie[k][x^1];
trie[k1][x]=++tot;
insert(trie[k][x],trie[k1][x],val,i,deep-1);
latest[k1]=max(latest[trie[k1][0]],latest[trie[k1][1]]);
}
int dft[MAX_N],dfx[MAX_N];
int ask(int k,int val,int deep,int limit){
if(deep<0)
return s[dfx[latest[k]]]^val;
int x=(val>>deep)&1;
//cout<<latest[trie[k][x^1]]<<" "<<limit<<" "<<deep<<"\n";
if(latest[trie[k][x^1]]>=limit)
return ask(trie[k][x^1],val,deep-1,limit);
else
return ask(trie[k][x],val,deep-1,limit);
}
int cnt=0;
void dfs_(int now,int fa){
int i;
dft[now]=++cnt;
dfx[cnt]=now;
root[now]=++tot;
insert(root[fa],root[now],s[now],cnt,17);
//cout<<root[now]<<" "<<dft[now]<<" "<<now<<" "<<fa<<" hi\n";
for(i=0;i<edge[now].size();i++){
int to=edge[now][i];
if(to!=fa){
dfs_(to,now);
}
}
}
int main(void){
int m,i,j,u,v;
for(i=1;i<=100000;i++)
log_2[i]=log_2[i-1]+(1<<log_2[i-1]==i);
while(scanf("%d%d",&N,&m)!=EOF){
for(i=1;i<=N;i++){
edge[i].clear();
have[i]=0;
scanf("%d",&s[i]);
}
for(i=0;i<N-1;i++){
scanf("%d%d",&u,&v);
edge[u].push_back(v);
edge[v].push_back(u);
}
tot=0;
cnt=0;
memset(trie,0,sizeof(trie));
memset(latest,0,sizeof(latest));
dfs_(1,0);
have[1]=1;
dfs(1);
d[0]=-1;
for(i=1;i<=log_2[N];i++){
for(j=1;j<=N;j++){
dp[j][i]=dp[dp[j][i-1]][i-1];
}
}
int a,b,z;
for(i=0;i<m;i++){
scanf("%d%d%d",&a,&b,&z);
int pre=LCA(a,b);
//cout<<dft[pre]<<"hi\n";
int ans=max(ask(root[a],z,17,dft[pre]),ask(root[b],z,17,dft[pre]));
cout<<ans<<"\n";
}
}
return 0;
}