【树上倍增】【lca】计蒜客 - Xor (2017ICPC西安网络赛)
https://nanti.jisuanke.com/t/17120
求一棵树上u到v路径上距离间隔k的元素的异或和。不错的题,稍后编辑
1 #include<bits/stdc++.h> 2 using namespace std; 3 4 const int maxn = 100010, MOD = 1e9+7, M = 18, K = 63; 5 int n,q,a[maxn],dep[maxn],fa[maxn][M+2],sum[maxn][K+2]; 6 vector<vector<int>> G(maxn); 7 8 int lca(int u,int v){ 9 if(dep[u] > dep[v]) swap(u,v); 10 int d = dep[v] - dep[u]; 11 for(int i = 0;i <= M;++i) 12 if(d >> i & 1) v = fa[v][i]; 13 if(u == v) return v; 14 for(int i = M; ~i; --i){ 15 if(fa[u][i] != fa[v][i]){ 16 u = fa[u][i]; 17 v = fa[v][i]; 18 } 19 } 20 return fa[v][0]; 21 } 22 23 int fnd(int v,int k){ 24 int tmp = 0; 25 while(k){ 26 if(k & 1) v = fa[v][tmp]; 27 k >>= 1; 28 tmp++; 29 } 30 return v; 31 } 32 33 void dfs(int v,int pre){ 34 fa[v][0] = pre; 35 for(auto x: G[v]){ 36 if(x == pre) continue; 37 dep[x] = dep[v] + 1; 38 dfs(x,v); 39 } 40 } 41 42 void dfs2(int v,int pre){ 43 for(int i = 1;i <= K;++i) 44 sum[v][i] = sum[fnd(v,i)][i] ^ a[v]; 45 for(auto x: G[v]){ 46 if(x == pre) continue; 47 dfs2(x,v); 48 } 49 } 50 51 void init(){ 52 dfs(1,0); 53 for(int i = 1;i <= M;++i) 54 for(int j = 1;j <= n;++j) 55 fa[j][i] = fa[fa[j][i-1]][i-1]; 56 dfs2(1,0); 57 } 58 59 int query(int u,int v,int k){ 60 int l = lca(u,v), now = u, ans = 0; 61 if(k <= K){ 62 int x = (dep[u] - dep[l]) / k; 63 int t = fnd(u,x*k+k); 64 ans ^= sum[u][k]; 65 ans ^= sum[t][k]; 66 x = dep[l] + k - ((dep[u] - x * k) - dep[l]); 67 if(x <= dep[v]){ 68 int tmp = dep[v] - x; 69 now = fnd(v,tmp % k); 70 ans ^= sum[now][k]; 71 t = fnd(v,tmp+k); 72 ans ^= sum[t][k]; 73 } 74 } 75 else{ 76 for(;;){ 77 ans ^= a[now]; 78 if(dep[now] - k < dep[l]) break; 79 now = fnd(now,k); 80 } 81 int x = dep[l] + k - (dep[now] - dep[l]); 82 if(x <= dep[v]){ 83 int tmp = dep[v] - x; 84 now = fnd(v,tmp % k); 85 for(;;){ 86 ans ^= a[now]; 87 if(dep[now] - k < x) break; 88 now = fnd(now,k); 89 } 90 } 91 } 92 return ans; 93 } 94 95 int main(){ 96 while(~scanf("%d%d",&n,&q)){ 97 for(int i = 1;i <= n;++i) G[i].clear(); 98 for(int i = 1;i < n;++i){ 99 int u, v; 100 scanf("%d%d",&u,&v); 101 G[u].push_back(v); 102 G[v].push_back(u); 103 } 104 for(int i = 1;i <= n;++i) scanf("%d",&a[i]); 105 init(); 106 while(q--){ 107 int u,v,k; 108 scanf("%d%d%d",&u,&v,&k); 109 printf("%d\n",query(u,v,k)); 110 } 111 } 112 113 return 0; 114 }