Idea: arsen1y
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int INF = (int) 1e18;
int32_t main() {
std::ios::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
int _;
cin >> _;
while (_--) {
int n;
cin >> n;
vector <int> a(n);
int mx = -INF;
int mn = INF;
for (int i = 0; i < n; ++i) {
cin >> a[i];
mx = max(mx, a[i]);
mn = min(mn, a[i]);
}
cout << mx - mn + 1 << "\n";
}
return 0;
}
Idea: eyfxrby
Try to find a property that does not change during operations.
#include <bits/stdc++.h>
using namespace std;
int main() {
int t;
cin >> t;
while (t--) {
int n, k; cin >> n >> k;
string s; cin >> s;
vector<int> cnt(k, 0);
for (int i = 0; i < n; i++) cnt[i % k] += s[i] - '0';
bool ok = true;
for (int r = 0; r < k; r++) {
if (cnt[r] % 2) {
ok = false;
break;
}
}
cout << (ok ? "YES" : "NO") << '\n';
}
}
Idea: arsen1y
It can be shown that it is advantageous to do only divisions first, and then only additions.
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int INF = (int) 1e18;
int32_t main() {
int _;
cin >> _;
while (_--) {
int a, b, x;
cin >> a >> b >> x;
int ans = INF;
int i = 0;
while (a != b) {
if (b > a) {
swap(a, b);
}
ans = min(ans, abs(a - b) + i);
a /= x;
i++;
}
ans = min(ans, i);
cout << ans << "\n";
}
return 0;
}
2236D - Совершенно новое татарское телешоу
Idea: dvb1r
What happens if Arseny chooses the maximum of the array as his first move?
If the count of maximum is odd, then Dabir wins, otherwise Egor wins.
Try to look at the second maximum.
#include <bits/stdc++.h>
using namespace std;
void solve();
int main() {
int t; cin >> t;
while (t--) solve();
return 0;
}
void solve() {
int n, k; cin >> n >> k;
vector<int> A(n);
for (auto& x : A) cin >> x;
sort(A.begin(), A.end());
vector<pair<int, int>> a = {{A[0], 1}};
for (int i = 1; i < n; ++i) {
if (A[i] == A[i - 1]) a.back().second++;
else a.emplace_back(A[i], 1);
}
while (a.size() > 0) {
n = a.size();
if (a[n - 1].second % 2 == 0) {
cout << "YES\n";
return;
}
if (n == 1) {
cout << "NO\n";
return;
}
if (a[n - 1].first - a[n - 2].first <= k) {
cout << "YES\n";
return;
}
a.pop_back();
}
}
Idea: arsen1y
The cut segments of the array do not need to be checked for non-intersection.
Try to save information about all the good segments, and only then find the answer.
#include <bits/stdc++.h>
using namespace std;
void solve();
int main() {
int t = 1; cin >> t;
while (t--) solve();
return 0;
}
void solve() {
int n; cin >> n;
vector<int> a(n);
for (auto& x : a) cin >> x, --x;
vector<vector<bool>> able(n, vector<bool>(n));
for (int i = 0; i < n; ++i) {
vector<int> us(n);
int mn = a[i], mx = a[i];
for (int j = i; j < n; ++j) {
if (us[a[j]]) break;
us[a[j]] = 1;
mn = min(mn, a[j]), mx = max(mx, a[j]);
if (mx - mn == j - i) able[mn][mx] = 1;
}
}
for (int ans = n; ans > 0; --ans) {
for (int i = 0; i + 2 * ans <= n; ++i) {
if (able[i][i + ans - 1] && able[i + ans][i + 2 * ans - 1]) {
cout << ans << '\n';
return;
}
}
}
cout << "0\n";
}
2236F1 - Выборы в Саранске (простая версия)
Idea: eyfxrby
What can we say about $$$gcd(p_i, p_j)$$$ for any pair $$$(i, j)$$$?
$$$gcd(p_i, p_j) = 1$$$.
Let's take a simple number $$$pr$$$. How many elements of the array $$$p$$$ can be divisible by this $$$pr$$$?
No more than one.
#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <bits/stdc++.h>
#include <immintrin.h>
using namespace __gnu_pbds;
using namespace std;
#define eps 1e-7
#define MOD2 119 * (1ll << 23) + 1
#define int long long
#define mp make_pair
#define pll pair <long long, long long>
#define next return
#define skip continue
#define all(a) a.begin(), a.end()
#define rall(a) a.rbegin(), a.rend()
#define f first
#define max_of max_element
#define min_of min_element
#define s second
// const int MAX_MEM = 4e8;
// int mpos = 0;
// alignas(long long) char mem[MAX_MEM];
// inline void * operator new(size_t n) {
// if (n & 7) n += 8 - (n & 7);
// char *res = mem + mpos;
// mpos += n;
// return (void *)res;
// }
// void operator delete(void *) {}
int scan() {
int x;
cin >> x;
return x;
}
string read() {
string s;
cin >> s;
return s;
}
const int N = 1e6 + 5, MOD = 1e9 + 7;
int lp[N], a[N], x, n, v[101];
vector<int> pr, divs[N];
int bin_pow(int x, int n) {
int res = 1;
while (n) {
if ((n & 1)) res = res * x % MOD;
n >>= 1;
x = x * x % MOD;
}
return res;
}
int solveF1_AUTHOR() {
map <int, int> cnt;
int cur_x;
int mx = *max_element(a + 1, a + n + 1);
set <int> setik;
for (int i = 1; i <= n; i++) {
int val = a[i];
cur_x = val;
while (cur_x > 1) {
setik.insert(lp[cur_x]);
cnt[lp[cur_x]]++;
cur_x /= lp[cur_x];
}
}
int ans = 1;
for (auto prime: setik) {
int sum = 1;
//cout << prime << ' ' << cnt[prime] << '\n';
ans = (ans * (cnt[prime] + 1)) % MOD;
}
return ans;
}
int32_t main() {
lp[1] = 1;
for (int i = 2; i < N; i++) {
if (lp[i] == 0) {
pr.push_back(i);
lp[i] = i;
}
for (int j = 0; j < (int) pr.size() && pr[j] <= lp[i] && i * pr[j] < N; j++) {
lp[i * pr[j]] = pr[j];
}
}
int t = scan();
while (t--) {
n = scan(); x = scan();
for (int i = 1; i <= n; i++) a[i] = scan();
cout << solveF1_AUTHOR() << '\n';
}
}
2236F2 - Выборы в Саранске (сложная версия)
Idea: eyfxrby
Try to fix the prime number $$$pr$$$. How can we transform the condition of the perfect array $$$p$$$ using $$$v_{pr}$$$?
$$$x \cdot lcm(p_1, p_2, \ldots, p_n) = p_1 \cdot p_2 * \ldots \cdot p_n \lt = \gt max(v_{pr}(p_i)) + v_{pr}(x) = \sum(v_{pr}(p_i)$$$)
Consider what a simple $$$pr$$$ might be. What types of $$$pr$$$ can it be classified into?
$$$x$$$ is divisible by $$$pr$$$, and $$$x$$$ is not divisible by $$$pr$$$.
Think about how to solve each of the cases in hint 2.
#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <bits/stdc++.h>
#include <immintrin.h>
using namespace __gnu_pbds;
using namespace std;
#define eps 1e-7
#define MOD2 119 * (1ll << 23) + 1
#define int long long
#define mp make_pair
#define pll pair <long long, long long>
#define next return
#define skip continue
#define all(a) a.begin(), a.end()
#define rall(a) a.rbegin(), a.rend()
#define f first
#define max_of max_element
#define min_of min_element
#define s second
int scan() {
int x;
cin >> x;
return x;
}
string read() {
string s;
cin >> s;
return s;
}
const int N = 1e6 + 2, MOD = 1e9 + 7;
int lp[N], a[N], x, n, v[N];
vector<int> pr, divs[N];
int MAX_V = -1E9;
int solve_for_prime(int vp) {
int mx_pref = 0;
int S = 0;
for (int i = 1; i <= n; i++) S += v[i];
S = min(S, 36ll);
int dp[MAX_V + 1][MAX_V + S + 2];
int old_pref_sum[MAX_V + 1][MAX_V + S + 2];
int old_pref_sum2[MAX_V + 1][MAX_V + S + 2];
memset(dp, 0, sizeof dp);
memset(old_pref_sum, 0, sizeof old_pref_sum);
memset(old_pref_sum2, 0, sizeof old_pref_sum2);
int sum = 0;
dp[0][0] = 1;
for (int i = 0; i <= n; i++) {
for (int sum_vp = 0; sum_vp <= S && i > 0; sum_vp++) {
for (int new_max = 1; new_max <= min(sum_vp, v[i]); new_max++) {
dp[new_max][sum_vp] += old_pref_sum2[new_max - 1][sum_vp - new_max];
if (dp[new_max][sum_vp] >= MOD) dp[new_max][sum_vp] -= MOD;
}
for (int old_max = 0; old_max <= min(mx_pref, sum_vp); old_max++) {
dp[old_max][sum_vp] += (old_pref_sum[old_max][sum_vp] + MOD - (sum_vp - min(old_max, v[i]) - 1 < 0 ? 0 :
old_pref_sum[old_max][sum_vp - min(old_max, v[i]) - 1])) % MOD;
//if (dp[old_max][sum_vp] >= MOD) dp[old_max][sum_vp] -= MOD;
}
}
for (int old_max = 0; old_max <= MAX_V; old_max++) {
for (int j = 0; j <= MAX_V + S; j++) {
old_pref_sum[old_max][j] = 0;
old_pref_sum[old_max][j] = (!j ? dp[old_max][j] : old_pref_sum[old_max][j - 1] + dp[old_max][j]);
if (old_pref_sum[old_max][j] >= MOD) old_pref_sum[old_max][j] -= MOD;
}
}
for (int j = 0; j <= MAX_V + S; j++) {
for (int old_max = 0; old_max <= MAX_V; old_max++) {
old_pref_sum2[old_max][j] = 0;
old_pref_sum2[old_max][j] = (!old_max ? dp[old_max][j] : old_pref_sum2[old_max - 1][j] + dp[old_max][j]);
if (old_pref_sum2[old_max][j] >= MOD) old_pref_sum2[old_max][j] -= MOD;
if(i != n) dp[old_max][j] = 0;
}
}
mx_pref = max(mx_pref, v[i]);
}
int ret = 0;
for (int mx = 1; vp + mx <= S && mx <= MAX_V; mx++) {
ret = (ret + dp[mx][vp + mx]);
if (ret >= MOD) ret -= MOD;
}
return ret;
}
int solveF2_AUTHOR() {
map<int, int> cnt_pr;
int cur_x = x;
while (cur_x > 1) {
int next_div = lp[cur_x];
cnt_pr[next_div]++;
cur_x /= next_div;
}
int ans = 1;
for (auto [prime, cnt]: cnt_pr) {
MAX_V = -1e9;
for (int i = 1; i <= n; i++) {
cur_x = a[i];
v[i] = 0;
while (cur_x % prime == 0) {
v[i]++;
cur_x /= prime;
}
MAX_V = max(MAX_V, v[i]);
}
ans = (ans * solve_for_prime(cnt)) % MOD;
}
map <int, int> cnt;
int mx = *max_element(a + 1, a + n + 1);
set <int> setik;
for (int i = 1; i <= n; i++) {
int val = a[i];
cur_x = val;
while (cur_x > 1) {
cnt[lp[cur_x]]++;
setik.insert(lp[cur_x]);
cur_x /= lp[cur_x];
}
}
for (auto prime: setik) {
//if (2 * prime > mx) break;
int sum = 1;
if (x % prime != 0) ans = (ans * (cnt[prime] + 1)) % MOD;
}
return ans;
}
int32_t main() {
for (int i = 2; i < N; i++) {
if (lp[i] == 0) {
pr.push_back(i);
lp[i] = i;
}
for (int j = 0; j < (int) pr.size() && pr[j] <= lp[i] && i * pr[j] < N; j++) {
lp[i * pr[j]] = pr[j];
}
}
int t = scan();
while (t--) {
n = scan(), x = scan();
for (int i = 1; i <= n; i++) a[i] = scan();
cout << solveF2_AUTHOR() << '\n';
}
}
//#pragma GCC optimize("Ofast")
//#pragma GCC optimize("O3,unroll-loops")
#include <bits/stdc++.h>
#include <experimental/random>
#include <ext/pb_ds/assoc_container.hpp>
using namespace std;
using namespace __gnu_pbds;
using ll = long long;
using ld = long double;
using ordered_set = tree<ll, null_type, less<ll>, rb_tree_tag, tree_order_statistics_node_update>;
using str = string;
const ll INF = 1e18, MOD = 1e9 + 7;
template<class T> using pq_min = priority_queue<T, vector<T>, greater<T>>;
template<class T> using pq_max = priority_queue<T, vector<T>, less<T>>;
#define int long long
void solve();
vector<int> P;
const int Mx = 1e4;
signed main() {
vector<bool> us(Mx);
for (int i = 2; i < Mx; ++i) {
if (!us[i]) {
P.push_back(i);
for (int j = i * i; j < Mx; j += i) {
us[j] = true;
}
}
}
#ifdef LOCAL
freopen("input.txt", "r", stdin);
freopen("output.txt", "w", stdout);
#endif
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
ll q = 1;
cin >> q;
while (q--) {
solve();
cout << "\n";
}
}
void solve() {
int n, x;
cin >> n >> x;
map<int, int> cnt;
for (auto w: P) {
if (w * w > x) {
break;
}
while (x % w == 0) {
x /= w;
cnt[w]++;
}
}
if (x > 1) {
cnt[x]++;
}
vector<int> a(n);
for (int i = 0; i < n; ++i) {
cin >> a[i];
}
map<int, vector<int>> w1;
for (int i = 0; i < n; ++i) {
for (auto w: P) {
if (w * w > a[i]) {
break;
}
int sum = 0;
while (a[i] % w == 0) {
a[i] /= w;
sum++;
}
if (sum > 0) {
w1[w].push_back(sum);
}
}
if (a[i] > 1) {
w1[a[i]].push_back(1);
}
}
int Ans = 1;
for (auto [id, e]: w1) {
int mx = 0;
for (auto s: e) {
mx = max(mx, s);
}
vector<vector<int>> dp(cnt[id] + 1, vector<int>(mx + 1));
dp[0][0] = 1;
for (auto w: e) {
vector<vector<int>> dp1(cnt[id] + 1, vector<int>(mx + 1));
for (int i = 0; i <= w; ++i) {
for (int j = 0; j <= cnt[id]; ++j) {
for (int k = 0; k <= mx; ++k) {
if (j + min(i, k) <= cnt[id]) {
dp1[j + min(i, k)][max(i, k)] += dp[j][k];
dp1[j + min(i, k)][max(i, k)] %= MOD;
}
}
}
}
swap(dp, dp1);
}
int s = 0;
for (int i = 0; i <= mx; ++i) {
s += dp[cnt[id]][i];
}
s %= MOD;
Ans *= s;
Ans %= MOD;
cnt[id] = 0;
}
for (auto s: cnt) {
if (s.second > 0) {
Ans = 0;
}
}
cout << Ans;
}
Idea: dvb1r
In fact, the XOR of non-negative numbers is always less or equal their sum, and you can think about why.
Using the fact that the XOR of a set of numbers is equal to the sum of those numbers, how many non-zero numbers can there be in this set?
No more than $$$log(A)$$$, since each bit must occur at most once.
For each vertex, pre-calculate the closest ancestor on the vertical path that violates the good segment condition.
Reduce the problem to a path of length at most $$$2 * log(A)$$$, and calculate the rest using the pre-calculation from hint 3.
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
void solve();
int main() {
int t = 1;
cin >> t;
while (t --> 0) solve();
return 0;
}
struct Graph {
vector<int> tin, tout, d;
vector<vector<pair<int, ll>>> up;
int timer;
void dfs(int v, const vector<vector<int>>& g, const vector<int>& arr, int p = -1) {
tin[v] = timer++;
up[0][v] = {p, arr[v]};
for (int l = 1; l < 20; ++l) {
if (up[l - 1][v].first == -1) {
up[l][v] = {-1, 0};
continue;
}
up[l][v].first = up[l - 1][up[l - 1][v].first].first;
up[l][v].second = up[l - 1][up[l - 1][v].first].second + up[l - 1][v].second;
}
for (int u : g[v]) {
if (u == p) continue;
d[u] = d[v] + 1;
dfs(u, g, arr, v);
}
tout[v] = timer;
}
Graph(const vector<vector<int>>& g, const vector<int>& a) : tin(g.size()), tout(g.size()), d(g.size()), up(20, vector<pair<int, ll>>(g.size())) {
timer = 0;
dfs(0, g, a);
}
bool anc(int p, int v) {
return tin[p] <= tin[v] && tout[p] >= tout[v];
}
int getLenVertical(int u, int v) {
if (!anc(u, v)) swap(u, v);
assert(anc(u, v));
return d[v] - d[u] - 1;
}
pair<int, ll> LA(int v, int k) {
if (k <= 0) return {v, 0};
ll sum = 0;
for (int i = 0; i < 20; ++i) {
if (k >> i & 1) sum += up[i][v].second, v = up[i][v].first;
}
return {v, sum};
}
int LCA(int u, int v) {
if (anc(u, v)) return u;
for (int l = 19; l >= 0; --l) {
if (up[l][u].first == -1 || anc(up[l][u].first, v)) continue;
u = up[l][u].first;
}
return up[0][u].first;
}
bool lower(int a, int b) {
return tin[a] < tin[b];
}
};
ll sum(int r) { return r * 1ll * (r + 1) / 2; }
ll sumSeg(int l, int r) {
return sum(r) - sum(l - 1);
}
void solve() {
int n, q; cin >> n >> q;
vector<int> a(n);
for (int i = 0; i < n; ++i) cin >> a[i];
vector<vector<int>> g(n);
for (int i = 1; i < n; ++i) {
int u, v; cin >> u >> v;
--u, --v;
g[u].emplace_back(v);
g[v].emplace_back(u);
}
vector<int> parent(n), d(n);
auto dfs = [&](auto& self, int v, int p = -1) -> void {
parent[v] = p;
for (int u : g[v]) {
if (u == p) continue;
d[u] = d[v] + 1;
self(self, u, v);
}
};
dfs(dfs, 0);
vector<int> compressed_parent = parent;
vector<vector<int>> cG(n);
for (int v = 0; v < n; ++v) {
vector<int> path;
while (compressed_parent[v] > 0 && a[compressed_parent[v]] == 0) {
path.emplace_back(compressed_parent[v]);
compressed_parent[v] = compressed_parent[compressed_parent[v]];
}
for (auto& x : path) compressed_parent[x] = compressed_parent[v];
if (a[v] == 0 || !v) continue;
cG[compressed_parent[v]].emplace_back(v);
}
vector<int> next_collision(n), sum_collision(n);
for (int v = 0; v < n; ++v) {
if (!a[v]) continue;
next_collision[v] = v;
int xr = a[v], sm = a[v];
while (xr == sm && next_collision[v] > -1) {
next_collision[v] = compressed_parent[next_collision[v]];
if (next_collision[v] == -1) break;
xr ^= a[next_collision[v]];
sm += a[next_collision[v]];
}
}
for (int v = 0; v < n; ++v) {
if (!a[v]) {
if (!v) next_collision[v] = -1;
else next_collision[v] = next_collision[compressed_parent[v]];
}
sum_collision[v] = d[v];
if (next_collision[v] > -1) sum_collision[v] -= d[next_collision[v]];
else sum_collision[v]++;
}
Graph def(g, sum_collision);
Graph compressed(cG, sum_collision);
while (q--) {
int u, v; cin >> u >> v;
--u, --v;
if (def.lower(v, u)) swap(u, v);
int z = def.LCA(u, v);
int cv = (a[v] || !v ? v : compressed_parent[v]), cu = (a[u] || !u ? u : compressed_parent[u]), cz = (a[z] || !z ? z : compressed_parent[z]);
ll ans = 0;
vector<int> L, R, Lspaces = {0}, Rspaces = {0};
if (compressed.d[cv] > compressed.d[cz] + 23) {
int unt = compressed.LA(cv, compressed.d[cv] - (compressed.d[cz] + 23)).first;
auto [to, sm] = def.LA(v, d[v] - d[unt]);
ans += sm, v = to;
}
if (compressed.d[cu] > compressed.d[cz] + 23) {
int unt = compressed.LA(cu, compressed.d[cu] - (compressed.d[cz] + 23)).first;
auto [to, sm] = def.LA(u, d[u] - d[unt]);
ans += sm, u = to;
}
while (u != z) {
int to = compressed_parent[u];
if (def.anc(to, z)) to = z;
L.emplace_back(u);
Lspaces.emplace_back(def.getLenVertical(u, to));
u = to;
}
while (v != z) {
int to = compressed_parent[v];
if (def.anc(to, z)) to = z;
R.emplace_back(v);
Rspaces.emplace_back(def.getLenVertical(v, to));
v = to;
}
L.emplace_back(z);
std::reverse(R.begin(), R.end());
std::reverse(Rspaces.begin(), Rspaces.end());
for (auto& x : R) L.emplace_back(x);
for (auto& x : Rspaces) Lspaces.emplace_back(x);
int j = 0, xr = 0, sum = 0;
ll cnt = 0;
for (int i = 0; i < L.size(); ++i) {
while (j < L.size() && xr == sum) {
xr ^= a[L[j]], sum += a[L[j]];
cnt += Lspaces[j] + 1;
j++;
}
if (xr != sum) cnt--;
ans += sumSeg(cnt - Lspaces[i], cnt);
if (xr != sum) cnt++;
xr ^= a[L[i]], sum -= a[L[i]];
cnt -= Lspaces[i] + 1;
}
cout << ans << '\n';
}
}
//#pragma GCC optimize("Ofast")
//#pragma GCC optimize("O3,unroll-loops")
#include <bits/stdc++.h>
#include <experimental/random>
#include <ext/pb_ds/assoc_container.hpp>
using namespace std;
using namespace __gnu_pbds;
using ll = long long;
using ld = long double;
using ordered_set = tree<ll, null_type, less<ll>, rb_tree_tag, tree_order_statistics_node_update>;
using str = string;
const ll INF = 1e18, MOD = 1e9 + 7;
template<class T> using pq_min = priority_queue<T, vector<T>, greater<T>>;
template<class T> using pq_max = priority_queue<T, vector<T>, less<T>>;
#define int long long
void solve();
signed main() {
#ifdef LOCAL
freopen("input.txt", "r", stdin);
freopen("output.txt", "w", stdout);
#endif
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
ll q = 1;
cin >> q;
while (q--) {
solve();
//cout << "\n";
}
}
vector<vector<int>> g;
vector<int> a;
int h;
vector<bool> us;
int cnt1;
vector<int> T;
void dfs1(int v, int pr) {
T.push_back(v);
cnt1++;
for (auto to: g[v]) {
if (to != pr && !us[to]) {
dfs1(to, v);
}
}
}
int dfs(int v, int pr) {
bool p = true;
int cnt = 1;
for (auto to: g[v]) {
if (to != pr && !us[to]) {
auto u = dfs(to, v);
if (u > cnt1 / 2) {
p = false;
}
cnt += u;
}
}
if (p && (cnt1 — cnt) <= cnt1 / 2) {
h = v;
}
return cnt;
}
int E = 0;
vector<int> ans;
vector<vector<int>> mn;
vector<int> col;
vector<int> sz;
vector<int> W;
void dfs(int v, int pr, vector<int> s, int an, int o, int mx) {
sz[v] = o;
col[v] = E;
W[v] = W[pr];
for (int i = 0; i < 20; ++i) {
mn[v][i] = mn[pr][i];
}
for (int i = 0; i < 20; ++i) {
if ((a[v] >> i) & 1) {
if (mn[v][i] != INF) {
W[v] = min(W[v], o);
}
mn[v][i] = min(mn[v][i], o);
mx = max(mx, s[i]);
s[i] = o;
}
}
an += o — mx;
ans[v] = an;
for (auto to: g[v]) {
if (to != pr && !us[to]) {
dfs(to, v, s, an, o + 1, mx);
}
}
}
vector<vector<pair<int, int>>> que;
vector<int> ANS;
void rec(int v) {
T.clear();
cnt1 = 0;
dfs1(v, -1);
dfs(v, -1);
v = h;
us[v] = true;
mn[v] = vector<int>(20, INF);
int S = E;
W[v] = INF;
for (auto to: g[v]) {
if (!us[to]) {
E++;
vector<int> s(20, 0);
dfs(to, v, s, 0, 1, 0);
}
}
ans[v] = 0;
++E;
col[v] = E;
for (auto x: T) {
for (auto [y, id]: que[x]) {
if (col[x] != col[y] && col[x] > S && col[y] > S) {
ANS[id] = ans[x] + ans[y];
if (x == v) {
int MN = min(W[y], sz[y] + 1);
for (int i = 0; i < 20; ++i) {
if ((a[v] >> i) & 1) {
MN = min(MN, mn[y][i]);
}
}
ANS[id] += MN;
} else if (y == v) {
int MN = min(W[x], sz[x] + 1);
for (int i = 0; i < 20; ++i) {
if ((a[v] >> i) & 1) {
MN = min(MN, mn[x][i]);
}
}
ANS[id] += MN;
} else {
vector<pair<int, int>> upd;
for (int i = 0; i < 20; ++i) {
if (mn[x][i] != INF) {
upd.push_back({mn[x][i], i});
}
}
int e = min(W[y], sz[y] + 1);
for (int i = 0; i < 20; ++i) {
if ((a[v] >> i) & 1) {
e = min(e, mn[y][i]);
}
}
sort(upd.begin(), upd.end());
int p = 0;
bool flag = true;
for (int i = 0; i < upd.size(); ++i) {
if (upd[i].first >= W[x]) {
ANS[id] += (W[x] — p) * e;
flag = false;
break;
}
ANS[id] += (upd[i].first — p) * e;
if ((a[v] >> upd[i].second) & 1) {
flag = false;
break;
}
e = min(e, mn[y][upd[i].second]);
p = upd[i].first;
}
if (flag) {
ANS[id] += (min(W[x], sz[x] + 1) — p) * e;
}
}
}
}
}
for (int i = 0; i < g[v].size(); ++i) {
int to = g[v][i];
if (!us[to]) {
rec(to);
}
}
}
void solve() {
int n, q;
cin >> n >> q;
sz.clear();
W.clear();
W.resize(n);
sz.resize(n);
ans.clear();
ANS.clear();
ANS.resize(q, -1);
mn.clear();
ans.resize(n);
mn.resize(n, vector<int>(20));
a.clear();
us.clear();
us.resize(n);
a.resize(n);
for (int i = 0; i < n; ++i) {
cin >> a[i];
}
g.clear();
col.clear();
col.resize(n);
que.clear();
que.resize(n);
g.resize(n);
for (int i = 0; i < n — 1; ++i) {
int u, v;
cin >> u >> v;
--u;
--v;
g[u].push_back(v);
g[v].push_back(u);
}
for (int i = 0; i < q; ++i) {
int x, y;
cin >> x >> y;
--x;
--y;
que[x].push_back({y, i});
}
rec(0);
for (int i = 0; i < q; ++i) {
if (ANS[i] == -1) {
exit(-1);
}
cout << ANS[i] << "\n";
}
}



