题意:
给出树的u,v节点询问每隔K个取一个数字异或。
思路:
是卡过去的。。竟然没TLE。
找U点和V点的LCA,之后从U点先向上用ST算法找到第K个祖先,依次类推。 之后再V点再重新处理向上找。注意在找完U后,可能LCA并不是K的位置。因此V点的起始位置要特判
#include<bits/stdc++.h>
using namespace std;
#define rank Rank
#define pb push_back
#define fi first
#define se second
#define MAXN 100050
#define inf 0x3f3f3f3f
int dep[MAXN];
int pre[20][MAXN] ;
int n,m;
int num[MAXN];
vector<int>vec[MAXN];
int a[MAXN];
int numlen[MAXN];
void dfs(int u, int fa)
{
dep[u] = dep[fa] + 1;
for(int i=0; i<vec[u].size(); i++)
{
int v = vec[u][i];
if(v == fa) continue;
dfs(v, u);
pre[0][v] = u;
}
}
int lca(int u, int v, int MAX)
{
if(dep[u] < dep[v]) swap(u, v);
int k = dep[u] - dep[v];
for(int i=0; i<MAX; i++)
{
if((k>>i)&1)
u = pre[i][u];
}
if(u == v)return u;
for(int i=MAX-1; i>=0; i--)
while(pre[i][u] != pre[i][v])
{
u = pre[i][u];
v = pre[i][v];
}
return pre[0][u];
}
int main()
{
int q,u,v;
while(~scanf("%d%d",&n,&q))
{
for(int i=1;i<=n;i++)
vec[i].clear();
for(int i=1; i<n; i++)
{
scanf("%d%d",&u,&v);
vec[u].push_back(v);
vec[v].push_back(u);
}
dep[1] = 1;
dfs(1, 0);
int k = 0,t = 1;
while(t <= n)t <<= 1,k++;
for(int i=0; i+1<k; i++)
{
for(int j=1; j<=n; j++)
{
pre[i+1][j] = pre[i][pre[i][j]];
}
}
for(int i=1; i<=n; i++)
{
scanf("%d",&a[i]);
}
int kk;
while(q--)
{
scanf("%d%d%d",&u,&v,&kk);
int Lca=lca(u,v,k);
int len=dep[u]+dep[v]-dep[Lca]*2;
int now=u;
int ans=a[u],cnt=0;
int kkk=kk;
while(kk!=0)
{
if(kk&1)
num[cnt]=1;
else num[cnt]=0;
cnt++;
kk>>=1;
}
while(dep[now]>=dep[Lca])
{
for(int i=cnt-1; i>=0; i--)
{
if(num[i]==1)
{
now=pre[i][now];
}
}
if(dep[now]<dep[Lca])
break;
ans^=a[now];
}
///vvv
now=v;
len=len%kkk;
if(dep[v]-dep[Lca]>len)
{
int cntlen=0;
while(len!=0)
{
if(len&1)
numlen[cntlen]=1;
else numlen[cntlen]=0;
cntlen++;
len>>=1;
}
if(dep[now]>=dep[Lca])
{
for(int i=cntlen-1; i>=0; i--)
{
if(numlen[i]==1)
{
now=pre[i][now];
}
}
}
///kk
ans^=a[now];
while(dep[now]>=dep[Lca])
{
for(int i=cnt-1; i>=0; i--)
{
if(num[i]==1)
{
now=pre[i][now];
}
}
if(dep[now]<=dep[Lca])
break;
ans^=a[now];
}
}
printf("%d\n",ans);
}
}
}