1. 程式人生 > 實用技巧 >樹上倍增學習總結

樹上倍增學習總結

樹上倍增:

  沒講的,直接上題

【SCOI2016】幸運數字(題目):

  倍增時合併一下線性基即可

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<iostream>
  4 #include<algorithm>
  5 using namespace std;
  6 
  7 typedef long long LL;
  8 
  9 const int N = 20010;
 10 
 11 int n, q;
 12 LL G[N], dep[N], ans[N];
 13
LL fa[N][21], p[N][21][62]; 14 int h[N], num[N << 1], nex[N << 1], dqx; 15 16 inline void add(int a, int b) 17 { 18 num[dqx] = b; 19 nex[dqx] = h[a]; 20 h[a] = dqx++; 21 } 22 23 inline void get_p(LL *a, LL val) 24 { 25 for (int i = 61; i >= 0; i--) 26 {
27 if ((val >> i) & 1) 28 { 29 if (!a[i]) 30 { 31 a[i] = val; 32 break; 33 } 34 val ^= a[i]; 35 } 36 } 37 } 38 39 void dfs(int u, int f) 40 { 41 fa[u][0] = f; 42 dep[u] = dep[f] + 1
; 43 for (int i = h[u]; ~i; i = nex[i]) 44 { 45 int j = num[i]; 46 if (j == f) continue; 47 dfs(j, u); 48 } 49 } 50 51 void merge(LL* a, LL* b) 52 { 53 for (int i = 61; i >= 0; i--) 54 { 55 if (b[i]) get_p(a, b[i]); 56 } 57 } 58 59 void get_lca() 60 { 61 for (int j = 1; j < 20; j++) 62 { 63 for (int i = 1; i <= n; i++) 64 { 65 fa[i][j] = fa[fa[i][j - 1]][j - 1]; 66 memcpy(p[i][j], p[i][j - 1], sizeof(p[i][j - 1])); 67 merge(p[i][j], p[fa[i][j - 1]][j - 1]); 68 } 69 } 70 } 71 72 inline void LCA(int u, int v) 73 { 74 if (dep[u] < dep[v]) swap(u, v); 75 76 for (int i = 20; i >= 0; i--) 77 { 78 if (dep[fa[u][i]] >= dep[v]) 79 { 80 merge(ans, p[u][i]); 81 u = fa[u][i]; 82 } 83 } 84 85 if (u == v) 86 { 87 merge(ans, p[u][0]); 88 return; 89 } 90 91 for (int i = 20; i >= 0; i--) 92 { 93 if (fa[u][i] != fa[v][i]) 94 { 95 merge(ans, p[u][i]), merge(ans, p[v][i]); 96 u = fa[u][i], v = fa[v][i]; 97 } 98 } 99 100 merge(ans, p[u][0]); 101 merge(ans, p[v][0]); 102 merge(ans, p[fa[u][0]][0]); 103 } 104 105 int main() 106 { 107 scanf("%d%d", &n, &q); 108 for (int i = 1; i <= n; i++) 109 { 110 scanf("%lld", &G[i]); 111 get_p(p[i][0], G[i]); 112 } 113 114 memset(h, -1, sizeof(h)); 115 for (int i = 1; i <= n - 1; i++) 116 { 117 int a, b; 118 scanf("%d%d", &a, &b); 119 add(a, b), add(b, a); 120 } 121 122 dfs(1, 0); 123 get_lca(); 124 125 for (int i = 1; i <= q; i++) 126 { 127 memset(ans, 0, sizeof(ans)); 128 129 int a, b; 130 scanf("%d%d", &a, &b); 131 LCA(a, b); 132 LL res = 0; 133 134 for (int j = 61; j >= 0; j--) res = max(res, res ^ (LL)ans[j]); 135 printf("%lld\n", res); 136 } 137 }
View Code