There is a tree with nn nodes. For each node, there is an integer value a_iai, (1 le a_i le 1,000,000,0001≤ai≤1,000,000,000 for 1 le i le n1≤i≤n). There is qq queries which are described as follow: Assume the value on the path from node aa to node bb is t_0, t_1, cdots t_mt0,t1,⋯tm. You are supposed to calculate t_0t0 xor t_ktk xor t_{2k}t2k xor ... xor t_{pk}tpk (pk le m)(pk≤m).
Input Format
There are multi datasets. (sum n le 50,000, sum q le 500,000)(∑n≤50,000,∑q≤500,000).
For each dataset: In the first n-1n−1 lines, there are two integers u,vu,v, indicates there is an edge connect node uu and node vv.
In the next nn lines, There is an integer a_iai (1 le a_i le 1,000,000,0001≤ai≤1,000,000,000).
In the next qq lines, There is three integers a,ba,band kk. (1 le a,b,k le n1≤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
分析:求树上路径从距离起点为k的倍数的权值和;
大于根号n暴力,小于的话预处理,处理到根的前缀异或和;
代码:
#include <iostream> #include <cstdio> #include <cstdlib> #include <cmath> #include <algorithm> #include <climits> #include <cstring> #include <string> #include <set> #include <bitset> #include <map> #include <queue> #include <stack> #include <vector> #include <cassert> #include <ctime> #define rep(i,m,n) for(i=m;i<=(int)n;i++) #define inf 0x3f3f3f3f #define mod 1000000007 #define vi vector<int> #define pb push_back #define mp make_pair #define fi first #define se second #define ll long long #define pi acos(-1.0) #define pii pair<int,int> #define sys system("pause") #define ls (rt<<1) #define rs (rt<<1|1) #define all(x) x.begin(),x.end() const int maxn=5e4+10; const int N=2e5+10; using namespace std; ll gcd(ll p,ll q){return q==0?p:gcd(q,p%q);} ll qmul(ll p,ll q,ll mo){ll f=0;while(q){if(q&1)f=(f+p)%mo;p=(p+p)%mo;q>>=1;}return f;} ll qpow(ll p,ll q,ll mo){ll f=1;while(q){if(q&1)f=f*p%mo;p=p*p%mo;q>>=1;}return f;} int n,m,k,t,dp[maxn][310],fa[20][maxn],dep[maxn],a[maxn],sz,q,head[maxn],tot; struct node { int to,nxt; }e[maxn<<1]; void add(int x,int y) { e[tot].to=y; e[tot].nxt=head[x]; head[x]=tot++; } int lca(int x,int y) { int i; if(dep[x]<dep[y])swap(x,y); for(i=19;i>=0;i--)if(dep[fa[i][x]]>=dep[y])x=fa[i][x]; if(x==y)return x; for(i=19;i>=0;i--) { if(fa[i][x]!=fa[i][y]) { x=fa[i][x], y=fa[i][y]; } } return fa[0][x]; } int find(int x,int y) { int i; for(i=19;i>=0;i--) { if(y>>i&1) { x=fa[i][x]; if(x==0)return 0; } } return x; } void dfs(int x,int y) { int i; dep[x]=dep[y]+1; for(i=1;fa[i-1][fa[i-1][x]];i++) { fa[i][x]=fa[i-1][fa[i-1][x]]; } rep(i,1,sz) { dp[x][i]=a[x]; dp[x][i]^=dp[find(x,i)][i]; } for(i=head[x];i!=-1;i=e[i].nxt) { int z=e[i].to; if(z==y)continue; fa[0][z]=x; dfs(z,x); } } int main(){ int i,j; while(~scanf("%d%d",&n,&q)) { sz=round(sqrt(n)); rep(i,1,n) { head[i]=-1; rep(j,0,19)fa[j][i]=0; } tot=0; rep(i,1,n-1) { int x,y; scanf("%d%d",&x,&y); add(x,y);add(y,x); } rep(i,1,n)scanf("%d",&a[i]); dfs(1,0); while(q--) { int x,y,k; int ret=0; scanf("%d%d%d",&x,&y,&k); if(x==y) { printf("%d ",a[x]); continue; } int fa=lca(x,y),len=dep[x]+dep[y]-2*dep[fa],pos; if((dep[x]-dep[fa])%k==0&&fa!=x&&fa!=y)ret^=a[fa]; if(k>sz) { if(fa!=x) { pos=x; ret^=a[pos]; while(dep[j=find(pos,k)]>=dep[fa]) { pos=j; ret^=a[pos]; } } if(fa!=y) { pos=find(y,len%k); if(dep[pos]>=dep[fa]) { ret^=a[pos]; while(dep[j=find(pos,k)]>=dep[fa]) { pos=j; ret^=a[pos]; } } } } else { int len1=dep[x]-dep[fa]; if(fa!=x) { len1=len1/k*k; pos=find(x,len1); ret=(ret^dp[x][k]^dp[pos][k]^a[pos]); } if(fa!=y) { int st=find(y,len%k); if(dep[st]>=dep[fa]) { len1=dep[st]-dep[fa]; len1=len1/k*k; pos=find(st,len1); ret=(ret^dp[st][k]^dp[pos][k]^a[pos]); } } } printf("%d ",ret); } } return 0; } /* 6 1 3 2 1 4 4 6 6 2 1 5 60 2 75 34 60 15 4 6 1 ans:45 */