2017 ICPC网络赛(西安)--- Xor

题目连接

Problem

There is a tree with n nodes. For each node, there is an integer value ai, (1ai1,000,000,000 for 1in). There is q queries which are described as follow:

Assume the value on the path from node a to node b is t0,t1,tm. You are supposed to calculate t0 xor tk xor t2k xor ... xor tpk (pkm).

Input Format

There are multi datasets. (n50,000,q500,000).

For each dataset: In the first n1 lines, there are two integers u,v, indicates there is an edge connect node uand node v.

In the next nn lines, There is an integer ai (1ai1,000,000,000).

In the next q lines, There is three integers a,b and k. (1a,b,kn).

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

题意: 有一棵n个节点的树,每个节点上有个权值vi,现在q次询问:节点a到节点b的路径上,从a开始每k个节点跳一次所经过的所有节点的异或值为(a0,ak,a2k,a3k...)?

思路: 建树,倍增算法记录每个节点的深度和2^i的祖先,处理并记录每个节点i到根节点间隔为k(1,2,3……100)的异或值dp[i][k]。当k<=100时,使用记录的异或值dp计算a到b间隔为k的异或值;当k>100时,直接从a走到b,每次跳动使用倍增的信息(快速跳动)。

代码如下:
  1 //https://nanti.jisuanke.com/t/A1273 《Xor》
  2 #include <iostream>
  3 #include <algorithm>
  4 #include <cstdio>
  5 #include <cstring>
  6 using namespace std;
  7 const int N = 5e4 + 5;
  8 int fa[N][20], deep[N], head[N];
  9 int v[N], cnt;
 10 bool vis[N];
 11 int dp[N][105];
 12 struct data
 13 {
 14     int to, next;
 15 }e[2 * N];
 16 
 17 void insert(int u, int v)
 18 {
 19     e[++cnt].to = v;
 20     e[cnt].next = head[u];
 21     head[u] = cnt;
 22     e[++cnt].to = u;
 23     e[cnt].next = head[v];
 24     head[v] = cnt;
 25 }
 26 int cal(int x, int t)
 27 {
 28     for (int i = 0; i <= 19; i++)
 29         if (t&(1 << i)) x = fa[x][i];
 30     return x;
 31 }
 32 void dfs(int x)
 33 {
 34     vis[x] = 1;
 35     for (int i = 1; i <= 19; i++)
 36     {
 37         if (deep[x]<(1 << i))break;
 38         fa[x][i] = fa[fa[x][i - 1]][i - 1];///倍增处理祖先信息
 39     }
 40     for (int k = 1; k <= 100; k++)
 41     {
 42         dp[x][k] = v[x];
 43         if (deep[x]<k) continue;
 44         int p = cal(x, k);
 45         dp[x][k] ^= dp[p][k];
 46     }
 47     for (int i = head[x]; i; i = e[i].next)
 48     {
 49         if (vis[e[i].to]) continue;
 50         deep[e[i].to] = deep[x] + 1;
 51         fa[e[i].to][0] = x;
 52         dfs(e[i].to);
 53     }
 54 }
 55 int lca(int x, int y)///求lca
 56 {
 57     if (deep[x]<deep[y]) swap(x, y);
 58     x = cal(x, deep[x] - deep[y]);
 59     for (int i = 19; i >= 0; i--)
 60         if (fa[x][i] != fa[y][i])
 61         {
 62             x = fa[x][i];
 63             y = fa[y][i];
 64         }
 65     if (x == y)return x;
 66     else return fa[x][0];
 67 }
 68 
 69 void init()
 70 {
 71     cnt = 0;
 72     memset(head, 0, sizeof(head));
 73     memset(vis, 0, sizeof(vis));
 74     memset(dp, 0, sizeof(dp));
 75     memset(deep, 0, sizeof(deep));
 76     memset(fa,0,sizeof(fa));
 77 }
 78 
 79 int main()
 80 {
 81     int n, q;
 82     while (scanf("%d%d", &n, &q) != EOF)
 83     {
 84         init();
 85         for (int i = 1; i<n; i++)
 86         {
 87             int x, y; scanf("%d%d", &x, &y);
 88             insert(x, y);
 89         }
 90         for (int i = 1; i <= n; i++) scanf("%d", &v[i]);
 91         dfs(1);
 92         while (q--)
 93         {
 94             int x, y, k; scanf("%d%d%d", &x, &y, &k);
 95             int pa = lca(x, y);
 96             if (k <= 100)
 97             {
 98                 int ans = dp[x][k];
 99                 int h = (deep[x] - deep[pa]) % k;
100                 int t = k - h;
101                 if (deep[pa] >= t)
102                 {
103                     int l = cal(pa, t);
104                     ans ^= dp[l][k];
105                 }
106                 int r = k - h;
107                 t = deep[y] - deep[pa] - r;
108                 if (t<0) goto endw2;
109                 t %= k;
110                 y = cal(y, t);///
111                 ans ^= dp[y][k];
112                 t = k - r;
113                 if (deep[pa] >= t)
114                 {
115                     int l = cal(pa, t);
116                     ans ^= dp[l][k];
117                 }
118             endw2:;
119                 printf("%d\n", ans);
120             }
121             else
122             {
123                 int ans = 0;
124                 while (1)
125                 {
126                     ans ^= v[x];
127                     if (deep[x] - k<deep[pa]) break;
128                     x = cal(x, k);
129                 }
130                 int l = k - (deep[x] - deep[pa]);
131                 int t = deep[y] - deep[pa] - l;
132                 if (t<0) goto endw;
133                 t %= k;
134                 y = cal(y, t);
135                 while (1)
136                 {
137                     ans ^= v[y];
138                     if (deep[y] - k <= deep[pa]) break;
139                     y = cal(y, k);
140                 }
141             endw:;
142                 printf("%d\n", ans);
143             }
144         }
145     }
146     return 0;
147 }
148 /**
149 8 11
150 1 2
151 2 3
152 2 4
153 1 5
154 5 6
155 5 7
156 4 8
157 3 5 6 2 7 0 1 10
158 1 8 1
159 answer=14
160 */


猜你喜欢

转载自www.cnblogs.com/chen9510/p/10800247.html
xor