2016-2017 CT S03E07: Codeforces Trainings Season 3 Episode 7
A. Yet Another Problem with Strings
题意:
给出$n$个字符串$S_i$,要求支持两种操作:
- 在第$i$个字符串后增加一个字符$c$
- 给出一个字符串$T$,询问是否有一个串$S_i$是$T$的子串。
强制在线,保证$\sum S_i, \sum T \leq 2 \cdot 10^5$
思路:
考虑暴力做法即枚举每个$S_i$然后询问$T$中的每个等长的子串是否等于$S_i$。
但是一个小优化是可以把所有长度相同的$S_i$放在一起做,用std::map记录哈希值。
并且注意到$\sum S_i \leq 2 \cdot 10^5$,所以所有的$S_i$只有$\sqrt{2 \cdot 10^5}$种长度。
暴力即可。
B. Pen Pineapple Apple Pen
Solved.
题意:将一个序列合并成一个数。
思路:分类讨论一下, 水。
1 #include<bits/stdc++.h> 2 3 using namespace std; 4 5 const int maxn = 1e5 + 10; 6 7 char str[maxn]; 8 9 bool solve() 10 { 11 int len = strlen(str + 1); 12 if(len == 1) return true; 13 while(len % 2 == 0) len = len >> 1; 14 if(len != 1) return false; 15 len = strlen(str + 1); 16 for(int i = 1; i <= len; i += 2) if(str[i] != 'P' && str[i + 1] != 'P') return false; 17 return true; 18 } 19 20 int main() 21 { 22 int t; 23 scanf("%d", &t); 24 while(t--) 25 { 26 scanf("%s", str + 1); 27 puts(solve() ? "YES" : "NO"); 28 } 29 return 0; 30 }
C. Stickmen
Solved.
题意:找有几个小人
思路:枚举$i, j$两个点作为中间那条线的端点, 再枚举公共点计算贡献。
1 #include<bits/stdc++.h> 2 3 using namespace std; 4 5 typedef long long ll; 6 7 const ll MOD = 1e9 + 7; 8 const int maxn = 1e3; 9 10 int n, m; 11 ll fac[maxn]; 12 ll inv[maxn]; 13 ll invfac[maxn]; 14 int du[maxn]; 15 int mp[maxn][maxn]; 16 17 void Init() 18 { 19 fac[1] = inv[1] = invfac[1] = 1; 20 fac[0] = inv[0] = invfac[0] = 1; 21 for(int i = 2; i < maxn; ++i) 22 { 23 fac[i] = fac[i - 1] * i % MOD; 24 inv[i] = inv[MOD % i] * (MOD - MOD / i) % MOD; 25 invfac[i] = invfac[i - 1] * inv[i] % MOD; 26 } 27 } 28 29 ll C(int n, int m) 30 { 31 if(n < 0 || m < 0) return 0; 32 if(m > n) return 0; 33 return fac[n] * invfac[m] % MOD * invfac[n - m] % MOD; 34 } 35 36 int merge(int x, int y) 37 { 38 int res = 0; 39 for(int i = 1; i <= n; ++i) if(mp[x][i] == 1 && mp[y][i] == 1) res++; 40 return res; 41 } 42 43 int main() 44 { 45 Init(); 46 while(~scanf("%d %d", &n, &m)) 47 { 48 memset(mp, 0, sizeof mp); 49 memset(du, 0, sizeof du); 50 for(int i = 1, x, y; i <= m; ++i) 51 { 52 scanf("%d %d", &x, &y); 53 du[x]++, du[y]++; 54 mp[x][y] = mp[y][x] = 1; 55 } 56 ll ans = 0; 57 for(int i = 1; i <= n; ++i) for(int j = 1; j <= n; ++j) if(mp[i][j] && i != j) 58 { 59 int x = du[i] - 1, y = du[j] - 1; 60 int same = merge(i, j); 61 ans = (ans + C(x, 3) * C(y, 2) % MOD)% MOD; 62 63 ans = (ans - C(x - 1, 2) * C(y - 1, 1) % MOD * same % MOD) % MOD; 64 ans = (ans + C(x - 2, 1) * C(same, 2) % MOD) % MOD; 65 } 66 printf("%lld\n", ans); 67 } 68 return 0; 69 }
D. Strange Queries
Solved.
题意:询问$i \in [L_1, R_1],j \in [L_2, R_2] 有多少对(i, j) 使得 a_i = a_j$
思路:$f[i][j]表示第i个块对前j个块的贡献,f2[i][j]表示a_i对前j个块的贡献$
$整块整块处理,边边角角处理$
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 #define ll long long 5 #define N 50010 6 #define S 150 7 #define unit 450 8 int n, a[N], q; 9 int pos[N], posl[unit], posr[unit]; 10 ll f[unit][unit], f2[N][unit]; 11 int cnt[N]; 12 13 int main() 14 { 15 while (scanf("%d", &n) != EOF) 16 { 17 for (int i = 1; i <= n; ++i) pos[i] = (i - 1) / S + 1; 18 for (int i = 1; i <= n; ++i) 19 { 20 if (i == 1 || pos[i] != pos[i - 1]) 21 posl[pos[i]] = i; 22 // cout << i << " " << pos[i] << endl; 23 posr[pos[i]] = i; 24 // printf("%d %d\n", posl[pos[i]], posr[pos[i]]); 25 } 26 // for (int i = 1; i <= n; ++i) cout << i << " " << pos[i] << endl; 27 // for (int i = 1; i <= n; ++i) 28 // printf("%d %d\n", posl[pos[i]], posr[pos[i]]); 29 memset(f, 0, sizeof f); 30 memset(f2, 0, sizeof f2); 31 memset(cnt, 0, sizeof cnt); 32 for (int i = 1; i <= n; ++i) scanf("%d", a + i); 33 for (int i = 1; i <= pos[n]; ++i) 34 { 35 for (int j = posl[i]; j <= posr[i]; ++j) 36 ++cnt[a[j]]; 37 for (int j = 1; j <= n; ++j) 38 { 39 f[i][pos[j]] += cnt[a[j]]; 40 f2[j][i] += cnt[a[j]]; 41 } 42 for (int j = posl[i]; j <= posr[i]; ++j) 43 --cnt[a[j]]; 44 } 45 for (int i = 1; i <= pos[n]; ++i) 46 for (int j = 1; j <= pos[n]; ++j) 47 f[i][j] += f[i][j - 1]; 48 for (int i = 1; i <= n; ++i) 49 for (int j = 1; j <= pos[n]; ++j) 50 f2[i][j] += f2[i][j - 1]; 51 scanf("%d", &q); 52 int l[2], r[2]; 53 while (q--) 54 { 55 for (int i = 0; i < 2; ++i) 56 scanf("%d%d", l + i, r + i); 57 if (pos[l[1]] == pos[r[1]]) 58 { 59 swap(l[0], l[1]); 60 swap(r[0], r[1]); 61 } 62 ll res = 0; 63 if (pos[l[0]] == pos[r[0]]) 64 { 65 if (pos[l[1]] == pos[r[1]]) 66 { 67 for (int i = l[0]; i <= r[0]; ++i) 68 ++cnt[a[i]]; 69 for (int i = l[1]; i <= r[1]; ++i) 70 res += cnt[a[i]]; 71 for (int i = l[0]; i <= r[0]; ++i) 72 --cnt[a[i]]; 73 } 74 else 75 { 76 int L = pos[l[1]] + 1; 77 int R = pos[r[1]] - 1; 78 for (int i = l[0]; i <= r[0]; ++i) 79 { 80 res += f2[i][R] - f2[i][L - 1]; 81 ++cnt[a[i]]; 82 } 83 for (int i = l[1]; i <= posr[pos[l[1]]]; ++i) 84 res += cnt[a[i]]; 85 for (int i = posl[pos[r[1]]]; i <= r[1]; ++i) 86 res += cnt[a[i]]; 87 for (int i = l[0]; i <= r[0]; ++i) 88 --cnt[a[i]]; 89 } 90 } 91 else 92 { 93 int L[2] = {pos[l[0]] + 1, pos[l[1]] + 1}; 94 int R[2] = {pos[r[0]] - 1, pos[r[1]] - 1}; 95 for (int i = L[0]; i <= R[0]; ++i) 96 res += f[i][R[1]] - f[i][L[1] - 1]; 97 for (int i = l[0]; i <= posr[pos[l[0]]]; ++i) 98 { 99 res += f2[i][R[1]] - f2[i][L[1] - 1]; 100 ++cnt[a[i]]; 101 } 102 for (int i = posl[pos[r[0]]]; i <= r[0]; ++i) 103 { 104 res += f2[i][R[1]] - f2[i][L[1] - 1]; 105 ++cnt[a[i]]; 106 } 107 for (int i = l[1]; i <= posr[pos[l[1]]]; ++i) 108 { 109 res += f2[i][R[0]] - f2[i][L[0] - 1]; 110 res += cnt[a[i]]; 111 } 112 for (int i = posl[pos[r[1]]]; i <= r[1]; ++i) 113 { 114 res += f2[i][R[0]] - f2[i][L[0] - 1]; 115 res += cnt[a[i]]; 116 } 117 for (int i = l[0]; i <= posr[pos[l[0]]]; ++i) 118 --cnt[a[i]]; 119 for (int i = posl[pos[r[0]]]; i <= r[0]; ++i) 120 --cnt[a[i]]; 121 } 122 printf("%lld\n", res); 123 } 124 } 125 return 0; 126 }
E. Bravebeart
Solved.
题意:给出n个人和n匹马, 每个人和每匹马都有自己的能力值, 每个人选择一匹马, 那么每个人的权值就是个人能力值乘上马的权值, 求是否存在一种方案, 使得第一个人的权值最大。
思路:排序, 水
1 #include<bits/stdc++.h> 2 3 using namespace std; 4 5 const int INF = 0x3f3f3f3f; 6 const int maxn = 1e5 + 10; 7 8 int n; 9 int w[maxn], h[maxn]; 10 11 bool solve(int tmp) 12 { 13 for(int i = n - 1; i >= 1; --i) 14 { 15 if(w[i] * h[n - 1 - i + 1] >= tmp) return false; 16 } 17 return true; 18 } 19 20 int main() 21 { 22 int t; 23 scanf("%d", &t); 24 while(t--) 25 { 26 scanf("%d", &n); 27 for(int i = 1; i <= n; ++i) scanf("%d", w + i); 28 for(int i = 1; i <= n; ++i) scanf("%d", h + i); 29 int tmp = w[1]; 30 w[1] = INF; 31 sort(w + 1, w + 1 + n); 32 sort(h + 1, h + 1 + n); 33 tmp *= h[n]; 34 puts(solve(tmp) ? "YES" : "NO"); 35 } 36 return 0; 37 }
F. GukiZ Height
Solved.
题意:$f_i = f_{i - 1} + a_{(i - 1) \% n +1}, g_i = h - \frac{i \cdot (i + 1)}{2}, 求最小的i 使得 f_i >= g_i$
思路:枚举每个余数, 那么分为周期为0和周期>=1, 对于后面一种情况, 二分周期。
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 #define ll long long 5 #define N 100010 6 int n; 7 ll h, a[N]; 8 ll sum[N]; 9 10 bool check(ll x, int remind) 11 { 12 ll day = x * n + remind; 13 return h - (day * (day + 1)) / 2 <= sum[n] * x + sum[remind]; 14 } 15 16 int main() 17 { 18 while (scanf("%d%lld", &n, &h) != EOF) 19 { 20 sum[0] = 0; 21 for (int i = 1; i <= n; ++i) scanf("%lld", a + i); 22 for (int i = 1; i <= n; ++i) sum[i] = sum[i - 1] + a[i]; 23 ll ans = (ll)1e18; 24 for (int i = 1; i <= n; ++i) if(sum[i] >= h - (i * (i + 1) / 2)) ans = min(ans, 1ll * i); 25 for (int i = 1; i <= n; ++i) 26 { 27 ll l = 0, r = (2e9 + 10) / n, res = -1; 28 while (r - l >= 0) 29 { 30 ll mid = (l + r) >> 1; 31 // cout << i << " " << mid << endl; 32 if (check(mid, i)) 33 { 34 r = mid - 1; 35 res = mid; 36 } 37 else 38 l = mid + 1; 39 } 40 // cout << i << " " << res << endl; 41 if (res != -1) 42 ans = min(ans, res * n + i); 43 } 44 printf("%lld\n", ans); 45 } 46 return 0; 47 }
I. Prime Moving
Solved.
题意:将素数$a$通过某系列变化得到素数$b$, 每次变化可以加上或减去一个素数, 同时结果要求是素数。
思路:将2作为中间点, 各种分类
1 #include<bits/stdc++.h> 2 3 using namespace std; 4 5 typedef long long ll; 6 7 const int S = 10; 8 9 ll mult_mod(ll a, ll b, ll c) 10 { 11 a %= c; 12 b %= c; 13 ll ret = 0; 14 ll tmp = a; 15 while(b) 16 { 17 if(b & 1) 18 { 19 ret += tmp; 20 if(ret > c) ret -= c; 21 } 22 tmp <<= 1; 23 if(tmp > c) tmp -= c; 24 b >>= 1; 25 } 26 return ret; 27 } 28 29 ll pow_mod(ll a, ll n, ll mod) 30 { 31 ll ret = 1; 32 ll tmp = a % mod; 33 while(n) 34 { 35 if(n & 1) ret = mult_mod(ret, tmp, mod); 36 tmp = mult_mod(tmp, tmp, mod); 37 n >>= 1; 38 } 39 return ret; 40 } 41 42 bool check(ll a, ll n, ll x, ll t) 43 { 44 ll ret = pow_mod(a, x, n); 45 ll last = ret; 46 for(int i = 1; i <= t; ++i) 47 { 48 ret = mult_mod(ret, ret, n); 49 if(ret == 1 && last != 1 && last != n - 1) return true; 50 last = ret; 51 } 52 if(ret != 1) return true; 53 else return false; 54 } 55 56 bool is_Prime(ll n) 57 { 58 if(n < 2) return false; 59 if(n == 2) return true; 60 if((n & 1) == 0) return false; 61 ll x = n - 1; 62 ll t = 0; 63 while((x & 1) == 0) { x >>= 1; ++t; } 64 srand(time(NULL)); 65 for(int i = 0; i < S; ++i) 66 { 67 ll a = rand() % (n - 1) + 1; 68 if(check(a, n, x, t)) return false; 69 } 70 return true; 71 } 72 73 ll a, b; 74 75 void solve() 76 { 77 if(a == 2) 78 { 79 if(is_Prime(b - 2)) 80 { 81 printf("%lld->%lld\n", a, b); 82 return ; 83 } 84 if(is_Prime(b + 2)) 85 { 86 printf("%lld->%lld->%lld\n", a, b + 2, b); 87 return ; 88 } 89 } 90 else 91 { 92 if(b == a + 2) 93 { 94 printf("%lld->%lld\n", a, b); 95 return ; 96 } 97 if(b == a + 4 && is_Prime(a + 2)) 98 { 99 if(is_Prime(a - 2) && is_Prime(b - 2)) 100 { 101 puts("Poor Benny"); 102 return ; 103 } 104 else 105 { 106 printf("%lld->%lld->%lld\n", a, a + 2, b); 107 return ; 108 } 109 } 110 if(is_Prime(a - 2)) 111 { 112 if(is_Prime(b - 2)) 113 { 114 printf("%lld->%lld->%lld\n", a, 2ll, b); 115 return ; 116 } 117 if(is_Prime(b + 2)) 118 { 119 if(is_Prime(a + 2) && is_Prime(b - 2)) 120 { 121 puts("Poor Benny"); 122 return ; 123 } 124 else 125 { 126 printf("%lld->%lld->%lld->%lld\n", a, 2ll, b + 2, b); 127 return ; 128 } 129 } 130 } 131 if(is_Prime(a + 2)) 132 { 133 if(is_Prime(b - 2)) 134 { 135 printf("%lld->%lld->%lld->%lld\n", a, a + 2, 2ll, b); 136 return ; 137 } 138 if(is_Prime(b + 2)) 139 { 140 printf("%lld->%lld->%lld->%lld->%lld\n", a, a + 2, 2ll, b + 2, b); 141 return ; 142 } 143 } 144 } 145 puts("Unlucky Benny"); 146 } 147 148 int main() 149 { 150 while(~scanf("%lld %lld", &a, &b)) 151 { 152 solve(); 153 } 154 return 0; 155 }
J. Valentina and the Gift Tree
Upsolved
题意:给出一棵树,询问$a -> b的简单路径上组成的序列的最大子段和$
思路:把一条简单路径拆成两条链,单独处理,一条链上用树链剖分处理,合并的时候注意左右端点怎么接
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 #define ll long long 5 #define N 100010 6 #define D 20 7 #define INF 0x3f3f3f3f3f3f3f3f 8 int n, q, g[N]; 9 vector <int> G[N]; 10 11 int sze[N], top[N], fa[D][N], son[N], p[N], fp[N], deep[N], cnt; 12 void DFS(int u) 13 { 14 sze[u] = 1; 15 for (int i = 1; i < D; ++i) 16 fa[i][u] = fa[i - 1][fa[i - 1][u]]; 17 for (auto v : G[u]) if (v != fa[0][u]) 18 { 19 fa[0][v] = u; 20 deep[v] = deep[u] + 1; 21 DFS(v); 22 sze[u] += sze[v]; 23 if (!son[u] || sze[v] > sze[son[u]]) son[u] = v; 24 } 25 } 26 27 void gettop(int u, int sp) 28 { 29 top[u] = sp; 30 p[u] = ++cnt; 31 fp[cnt] = u; 32 if (!son[u]) return; 33 gettop(son[u], sp); 34 for (auto v : G[u]) if (v != fa[0][u] && v != son[u]) 35 gettop(v, v); 36 } 37 38 namespace SEG 39 { 40 struct node 41 { 42 ll lmax, rmax, Max, sum; 43 node () {} 44 void init() 45 { 46 lmax = rmax = Max = sum = -INF; 47 } 48 node operator + (const node &other) const 49 { 50 node res; res.init(); 51 if (lmax == -INF || rmax == -INF) 52 return other; 53 if (other.lmax == -INF || other.rmax == -INF) 54 return *this; 55 res.sum = sum + other.sum; 56 res.lmax = max(lmax, sum + other.lmax); 57 res.rmax = max(other.rmax, other.sum + rmax); 58 res.Max = max(Max, other.Max); 59 res.Max = max(res.Max, rmax + other.lmax); 60 return res; 61 } 62 }a[N << 2], ans[2], tmp; 63 void build(int id, int l, int r) 64 { 65 a[id].init(); 66 if (l == r) 67 { 68 a[id].lmax = a[id].rmax = a[id].sum = a[id].Max = g[fp[l]]; 69 return; 70 } 71 int mid = (l + r) >> 1; 72 build(id << 1, l, mid); 73 build(id << 1 | 1, mid + 1, r); 74 a[id] = a[id << 1] + a[id << 1 | 1]; 75 } 76 void query(int id, int l, int r, int ql, int qr) 77 { 78 if (qr < ql || ql <= 0 || qr <= 0) return; 79 if (l >= ql && r <= qr) 80 { 81 tmp = tmp + a[id]; 82 return; 83 } 84 int mid = (l + r) >> 1; 85 if (ql <= mid) query(id << 1, l, mid, ql, qr); 86 if (qr > mid) query(id << 1 | 1, mid + 1, r, ql, qr); 87 } 88 } 89 90 int lca(int u, int v) 91 { 92 while (top[u] != top[v]) 93 { 94 if (deep[top[u]] < deep[top[v]]) swap(u, v); 95 u = fa[0][top[u]]; 96 } 97 if (deep[u] > deep[v]) swap(u, v); 98 return u; 99 } 100 101 int kth(int u, int k) 102 { 103 for (int i = 0; i < D; ++i) 104 if ((k >> i) & 1) 105 u = fa[i][u]; 106 return u; 107 } 108 109 void query(int u, int v, int vis) 110 { 111 SEG::ans[vis].init(); 112 while (top[u] != top[v]) 113 { 114 if (deep[top[u]] < deep[top[v]]) swap(u, v); 115 SEG::tmp.init(); 116 SEG::query(1, 1, n, p[top[u]], p[u]); 117 SEG::ans[vis] = SEG::tmp + SEG::ans[vis]; 118 u = fa[0][top[u]]; 119 } 120 if (deep[u] > deep[v]) swap(u, v); 121 SEG::tmp.init(); 122 SEG::query(1, 1, n, p[u], p[v]); 123 SEG::ans[vis] = SEG::tmp + SEG::ans[vis]; 124 } 125 126 int main() 127 { 128 while (scanf("%d", &n) != EOF) 129 { 130 for (int i = 1; i <= n; ++i) G[i].clear(); 131 memset(son, 0, sizeof son); cnt = 0; deep[1] = 0; 132 for (int i = 1, u, v; i < n; ++i) 133 { 134 scanf("%d%d", &u, &v); 135 G[u].push_back(v); 136 G[v].push_back(u); 137 } 138 for (int i = 1; i <= n; ++i) scanf("%d", g + i); 139 deep[1] = 0; fa[0][1] = 0; 140 DFS(1); gettop(1, 1); SEG::build(1, 1, n); 141 //if (n == 10) return 0; 142 scanf("%d", &q); 143 int a, b; 144 while (q--) 145 { 146 scanf("%d%d", &a, &b); 147 if (deep[a] > deep[b]) swap(a, b); 148 int Lca = lca(a, b); 149 if (a == Lca) 150 query(a, b, 0); 151 else 152 { 153 query(Lca, a, 0); 154 query(kth(b, deep[b] - deep[Lca] - 1), b, 1); 155 swap(SEG::ans[0].lmax, SEG::ans[0].rmax); 156 SEG::ans[0] = SEG::ans[0] + SEG::ans[1]; 157 } 158 printf("%lld\n", SEG::ans[0].Max); 159 } 160 } 161 return 0; 162 }
LCA
1 #include<bits/stdc++.h> 2 3 using namespace std; 4 5 typedef long long ll; 6 7 const ll MOD = 1e9 + 7; 8 const ll INFLL = 0x3f3f3f3f3f3f3f3f; 9 const int maxn = 1e5 + 10; 10 11 const int DEG = 20; 12 13 struct Edge { 14 int to, nxt; 15 Edge() {} 16 Edge(int to, int nxt) :to(to), nxt(nxt) {} 17 }edge[maxn << 1]; 18 19 struct node { 20 ll lmax, rmax, ans, sum; 21 node() 22 { 23 sum = 0; 24 lmax = rmax = ans = -INFLL; 25 } 26 node(ll tmp) 27 { 28 lmax = rmax = ans = sum = tmp; 29 } 30 node operator + (const node &other) const 31 { 32 node res; 33 res.sum = sum + other.sum; 34 res.lmax = max(lmax, sum + other.lmax); 35 res.rmax = max(other.rmax, other.sum + rmax); 36 res.ans = max(max(ans, other.ans), rmax + other.lmax); 37 return res; 38 } 39 }; 40 41 int n, m; 42 ll arr[maxn]; 43 int head[maxn], tot; 44 node res[maxn][DEG]; 45 int fa[maxn][DEG]; 46 int deg[maxn]; 47 48 void Init() 49 { 50 tot = 0; 51 memset(fa, -1, sizeof fa); 52 memset(head, -1, sizeof head); 53 } 54 55 void addedge(int u, int v) 56 { 57 edge[tot] = Edge(v, head[u]); head[u] = tot++; 58 edge[tot] = Edge(u, head[v]); head[v] = tot++; 59 60 } 61 62 void BFS(int root) 63 { 64 queue<int>q; 65 deg[root] = 0; 66 res[root][0] = node(arr[root]); 67 fa[root][0] = root; 68 q.push(root); 69 while (!q.empty()) 70 { 71 int tmp = q.front(); 72 q.pop(); 73 for (int i = 1; i < DEG; ++i) 74 { 75 fa[tmp][i] = fa[fa[tmp][i - 1]][i - 1]; 76 res[tmp][i] = res[tmp][i - 1] + res[fa[tmp][i - 1]][i - 1]; 77 } 78 for (int i = head[tmp]; ~i; i = edge[i].nxt) 79 { 80 int v = edge[i].to; 81 if (v == fa[tmp][0]) continue; 82 deg[v] = deg[tmp] + 1; 83 fa[v][0] = tmp; 84 res[v][0] = node(arr[v]); 85 q.push(v); 86 } 87 } 88 } 89 90 node LCA(int u, int v) 91 { 92 if (deg[u] > deg[v]) swap(u, v); 93 int hu = deg[u], hv = deg[v]; 94 int tu = u, tv = v; 95 node ansu, ansv; 96 for (int det = hv - hu, i = 0; det; det >>= 1, ++i) 97 { 98 if (det & 1) 99 { 100 ansv = ansv + res[tv][i]; 101 tv = fa[tv][i]; 102 } 103 } 104 for (int i = DEG - 1; i >= 0; --i) 105 { 106 if (fa[tu][i] == fa[tv][i]) continue; 107 ansu = ansu + res[tu][i]; 108 ansv = ansv + res[tv][i]; 109 tu = fa[tu][i]; 110 tv = fa[tv][i]; 111 } 112 while (tu != tv) 113 { 114 ansu = ansu + res[tu][0]; 115 ansv = ansv + res[tv][0]; 116 tu = fa[tu][0]; 117 tv = fa[tv][0]; 118 } 119 swap(ansv.lmax, ansv.rmax); 120 return ansu + res[tu][0] + ansv; 121 } 122 123 void RUN() 124 { 125 while (~scanf("%d", &n)) 126 { 127 Init(); 128 for (int i = 1, u, v; i < n; ++i) 129 { 130 scanf("%d %d", &u, &v); 131 addedge(u, v); 132 } 133 for (int i = 1; i <= n; ++i) scanf("%lld", arr + i); 134 BFS(1); 135 int q; 136 scanf("%d", &q); 137 for (int qq = 1, u, v; qq <= q; ++qq) 138 { 139 scanf("%d %d", &u, &v); 140 printf("%lld\n", LCA(u, v).ans); 141 } 142 } 143 } 144 145 int main() 146 { 147 #ifdef LOCAL_JUDGE 148 freopen("Text.txt", "r", stdin); 149 #endif // LOCAL_JUDGE 150 151 RUN(); 152 153 #ifdef LOCAL_JUDGE 154 fclose(stdin); 155 #endif // LOCAL_JUDGE 156 return 0; 157 }