题意:一棵树,点权,Q次询问,A---B路径上每K个点的异或和
链接:点击打开链接
思路:分类讨论,k小于200,类似dp的预处理,在求lca的过程中可以求出来,k大于200,直接暴力跳,最多跳sqrtn步,其中还带个log的倍增。1200ms AC。。
PS :场上手残。。。
代码:
#include<bits/stdc++.h>
using namespace std;
const int MAXN = 100010;
const int DEG = 20;
int root;
struct Edge{
int to,next;
} edge[MAXN*2];
int head[MAXN],tot;
void addedge(int u,int v){
edge[tot].to = v;
edge[tot].next = head[u];
head[u] = tot++;
}
void init(){
tot = 0;
memset(head,-1,sizeof(head));
}
int fa[MAXN][DEG];//fa[i][j]表示结点i的第2^j个祖先
int deg[MAXN];//深度数组
int w[MAXN];
int dp[MAXN][205];
int fa2[MAXN][205];
void BFS(int root){
queue<int>que;
deg[root] = 0;
fa[root][0] = root;
que.push(root);
while(!que.empty()){
int tmp = que.front();
que.pop();
for(int i = 1; i < DEG; i++)
fa[tmp][i] = fa[fa[tmp][i-1]][i-1];
fa2[tmp][0]=tmp;
for(int i = 1; i <= 200; i++)
fa2[tmp][i]=fa2[fa[tmp][0]][i-1];
for(int i = 1; i <= 200; i++)
dp[tmp][i]=dp[fa2[tmp][i]][i]^w[tmp];
for(int i = head[tmp]; i != -1; i = edge[i].next){
int v = edge[i].to;
if(v == fa[tmp][0])continue;
deg[v] = deg[tmp] + 1;
fa[v][0] = tmp;
que.push(v);
}
}
}
int LCA(int u,int v){
if(deg[u] > deg[v])swap(u,v);
int hu = deg[u], hv = deg[v];
int tu = u, tv = v;
for(int det = hv-hu, i = 0; det ; det>>=1, i++)
if(det&1)tv = fa[tv][i];
if(tu == tv)return tu;
for(int i = DEG-1; i >= 0; i--){
if(fa[tu][i] == fa[tv][i])continue;
tu = fa[tu][i];
tv = fa[tv][i];
}
return fa[tu][0];
}
bool flag[MAXN];
int go(int x,int step){
for(int det = step, i = 0; det ; det>>=1, i++)
if(det&1){
x = fa[x][i];
if(x==root) break;
}
return x;
}
int Sum(int x,int step){
int ret=w[x];
while(x!=root){
x=go(x,step);
ret^=w[x];
}
return ret;
}
int main(){
int T,N,Q;
int u,v,k;
while(scanf("%d%d",&N,&Q)!=EOF){
init();
memset(dp,0,sizeof(dp));
memset(w,0,sizeof(w));
for(int i = 1; i < N; i++){
scanf("%d%d",&u,&v);
addedge(u,v);
addedge(v,u);
}
for(int i=1;i<=N;i++) scanf("%d",&w[i]);
for(int i=1;i<=N;i++) addedge(N+i,N+i-1),addedge(N+i-1,N+i);
root=N+N;
BFS(root);
for(int i=0;i<Q;i++){
scanf("%d%d%d",&u,&v,&k);
int ans=0;
if(u==v){
ans=w[u];
}
else if(k<=200){
int lca=LCA(u,v);
int lab=deg[u]+deg[v]-2*deg[lca];
int lalca=deg[u]-deg[lca];
int yu1=lalca%k,yu2=k-yu1,yu3=lab%k;
ans=dp[u][k]^dp[go(lca,yu2)][k]^dp[go(v,yu3)][k]^dp[go(lca,yu1)][k];
}
else{
int lca=LCA(u,v);
int lab=deg[u]+deg[v]-2*deg[lca];
int lalca=deg[u]-deg[lca];
int yu1=lalca%k,yu2=k-yu1,yu3=lab%k;
ans=Sum(u,k)^Sum(go(lca,yu2),k)^Sum(go(v,yu3),k)^Sum(go(lca,yu1),k);
}
printf("%d
",ans);
}
}
return 0;
}