【树上倍增】【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 }

 

posted @ 2017-09-20 10:21  doub7e  阅读(291)  评论(0编辑  收藏  举报