2017 ICPC網絡賽(西安)--- Xor

題目鏈接html

 

Problemnode

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: ios

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).spa

Output Format

For each query, output an integer in one line, without any additional space.code

樣例輸入

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,每次跳動使用倍增的信息(快速跳動)。

注:這道題是2017年打西安網絡賽時沒過的題,當時其實代碼寫的很接近了,測數據都沒問題,一直檢查不出來,我也一直惦記着這道題。本科畢業後讀研,又看過一次仍是沒找出緣由,今天五一放假,沒啥事兒,我又看了一遍當時寫的代碼,忽然發現沒初始化fa數組,心想難道是計蒜客網站編譯器不是默認未初始化的值爲0?加上fa的初始化後提交了一把,過了!!!
My God! 心心念唸的這道題居然是這個緣由沒過,氣呀。不過,今天總算是找到緣由了,哈哈~ 又一次想起來西安正式賽的時候,一道銅牌題沒過「LOL BP」致使沒拿到銀牌,惋惜的是當時的銀牌題都過了,唉~ 與銀失之交臂。如今是研究生了,不多刷題了,之後要少看劇,多看看相關的圖形學的專業書,充實本身,找個好工做。

代碼以下:
  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 */
相關文章
相關標籤/搜索