There is a tree with n nodes. For each node, there is an integer value ai, (1≤ai≤1,000,000,000 for 1≤i≤n). There is q queries which are described as follow: Assume the value on the path from node a to node b is t0,t1,⋯tm. You are supposed to calculate t0 xor tk xor t2k xor ... xor tpk (pk≤m).
Input Format
There are multi datasets. (∑n≤50,000,∑q≤500,000).
For each dataset: In the first n−1 lines, there are two integers u,v, indicates there is an edge connect node uand node v.
In the next n lines, There is an integer ai (1≤ai≤1,000,000,000).
In the next q lines, There is three integers a,b and k. (1≤a,b,k≤n).
Output Format
For each query, output an integer in one line, without any additional space.
样例输入
5 6 1 5 4 1 2 1 3 2 19 26 0 8 17 5 5 1 1 3 2 3 2 1 5 4 2 3 4 4 1 4 5
样例输出
17 19 26 25 0 19
题意:给一棵树,然后每个点都有一个权值,另给q个查询,每个查询包括a,b,k三个值,表示求从a到b的路径上每相隔k个点的权值的异或值,起点从a开始;
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
const int maxed=50000+10;
struct E
{
int v,bef;
}e[maxed*2];
int n,m,ans,head[maxed],p[maxed];
int top[maxed],son[maxed],size_[maxed],d[maxed];
int f[maxed][20],sxor_[maxed][255];
int main()
{
//freopen("shuJu.txt","w",stdout);
void add_(int,int);
void slove_1(int,int);
void slove_2(int,int);
int lca(int,int);
int find_(int,int);
while(scanf("%d%d",&n,&m)!=EOF){
ans=1;
memset(head,-1,sizeof(head));
int a,b,c;
for(int i=1;i<=n-1;i++){
scanf("%d%d",&a,&b);
add_(a,b);
add_(b,a);
}
memset(f,0,sizeof(f));
for(int i=1;i<=n;i++){
scanf("%d",&p[i]);
son[i]=0;
if (i == 1)
f[i][0] = 0;
else
f[i][0] = i;
}
d[0] = 0;
memset(sxor_,0,sizeof(sxor_));
slove_1(1,1);
slove_2(1,1);
for(int i=1;i<=20;i++)
for(int j=1;j<=n;j++){
int r=f[j][i-1];
if(r==0)
continue;
f[j][i]=f[r][i-1];
}
int len=(int)sqrt(n);
while(m--){
scanf("%d%d%d",&a,&b,&c);
int wa=lca(a,b);
if(c<=len){
int answer=sxor_[a][c];
int k=c-(d[a]-d[wa])%c;
int kk=find_(wa,k);
answer^=sxor_[kk][c];
if (d[b] - d[wa] - k >= 0 && b != wa) {
kk = (d[b] - d[wa] - k)%c;
int r = find_(b, kk);
answer ^= sxor_[r][c];
kk = (d[a] - d[wa])%c;
k = find_(wa, kk);
answer ^= sxor_[k][c];
}
printf("%d\n", answer);
}
else{
int answer = 0, l = a, r = b;
while (d[l] >= d[wa]){
answer ^= p[l];
l = find_(l, c);
}
if (d[r] - d[wa] - (c - (d[a] - d[wa])%c) >= 0 && b != wa) {
int k = (d[r] - d[wa] - (c - (d[a] - d[wa])%c))%c;
r = find_(r, k);
while (d[r] > d[wa]) {
answer ^= p[r];
r = find_(r, c);
}
}
printf("%d\n", answer);
}
}
}
return 0;
}
void add_(int x,int y)
{
e[ans].v=y;
e[ans].bef=head[x];
head[x]=ans++;
}
void slove_1(int u,int dep)
{
size_[u]=1;
d[u]=dep;
int now=u,step=0;
while(step<255){
sxor_[u][step]=p[u]^sxor_[now][step];
now = f[now][0];
step++;
}
for(int i=head[u];i!=-1;i=e[i].bef){
int v=e[i].v;
if (f[u][0] == v)
continue;
f[v][0] = u;
slove_1(v,dep+1);
size_[u]+=size_[v];
if(!son[u]||size_[son[u]]<size_[v])
son[u]=v;
}
}
void slove_2(int u,int fa)
{
top[u]=fa;
if(son[u])
slove_2(son[u],fa);
for(int i=head[u];i!=-1;i=e[i].bef){
int v=e[i].v;
if (f[u][0] == v || son[u] == v)
continue;
slove_2(v,v);
}
}
int lca(int a,int b)
{
int f1=top[a],f2=top[b],l=a,r=b;
while(f1!=f2){
if(d[f1]<d[f2]){
swap(f1,f2);
swap(l,r);
}
l = f[f1][0];
f1=top[l];
}
if(d[l]>d[r])
swap(l,r);
return l;
}
int find_(int a,int x)
{
int s=0;
while(x){
if(x&1)
a=f[a][s];
x>>=1;
s++;
}
return a;
}