Problem:
H - Bit Operation Game
N
頂点の根付き木が与えられる。
頂点には
0
から
N − 1
の番号がついており、
0
番目の頂点が根を表す。
根には
T = 0
が、それ以外の頂点には
T=T&X
T=T&Y
T=T|X
T=T|Y
T=T^X
T=T^Y
のいずれかの操作が書かれている。
ここでの演算子 &, |, ^ はそれぞれビット演算子 and, or, xor, を意味する。
A君とB君はこの木を使って以下のゲームを
M
回行った。
二人は根からスタートし、子頂点を選び進むという操作を、A君から始め葉に到達するまで交互に行う。
通ったノードに書かれている操作を、通った順に適用した時の、最終的な
T
の値がスコアになる。
B君はできるだけスコアを小さくしたいと考えており、またA君は大きくしたいと考えている。
M回のゲームの
X
,
Y
の値が与えられるので、二人が最適な選択をした時の各ゲームのスコアを出力せよ。
Constraints
1  ≤  N  ≤  100000
1  ≤  M  ≤  100000
0  ≤  X, Y < 2^{16}
Input Format
入力は以下の形式で標準入力から与えられる。
N
M
o_1
o_2
...
o_{N−1}
u_1
v_1
u_2
v_2
...
u_{N−1}
v_{N−1}
X_1
Y_1
X_2
Y_2
...
X_M
Y_M
1
行目には木の頂点数
N
と、行われるゲーム数を表す整数
M
が入力される。
2
行目から
N
行目にかけて、
1
...
N−1
番目の頂点に書かれている操作が入力される。
さらに続けて
N−1
行に、各辺により繋がれる
2
頂点の番号が入力される。
最後に
M
回のゲームにおける
X
,
Y
の値が
M
行に渡り入力される。
Output Format
各ゲームでの最終的な
T
の値をそれぞれ
M
行に出力せよ。
Sample Input 1
6 3
T=T|X
T=T|Y
T=T|Y
T=T^Y
T=T&X
0 1
0 2
1 3
1 4
2 5
5 6
3 5
0 0
Sample Output 1
4
6
0
X = 5, Y = 6 の場合、頂点 0 -> 2 -> 5 と進み、T = 5 & 6 = 4 になります
X = 3, Y = 5 の場合、頂点 0 -> 1 -> 4 と進み、T = 3 ^ 5 = 6 になります
X = 0, Y = 0 の場合、どこを通っても T は 0 から変化しません

Submitted solutions:

code_snippet: #include <bits/stdc++.h>
using namespace std;

map<vector<int>, int> memo;
vector<int> op;

using graph = vector<vector<int>>;

int proc(int state, int op) {
    if(state == 0) {
        if(op == 0 || op == 1) {
            return 0;
        } else if(op == 2 || op == 4) {
            return 1;
        } else if(op == 3 || op == 5) {
            return 2;
        }
    } else if(state == 1) {
        if(op == 0 || op == 2) {
            return 1;
        } else if(op == 1) {
            return 4;
        } else if(op == 3) {
            return 3;
        } else if(op == 4) {
            return 0;
        } else if(op == 5) {
            return 5;
        }
    } else if(state == 2) {
        if(op == 0) {
            return 4;
        } else if(op == 1 || op == 3) {
            return 2;
        } else if(op == 2) {
            return 3;
        } else if(op == 4) {
            return 5;
        } else {
            return 0;
        }
    } else if(state == 3) {
        if(op == 0) {
            return 1;
        } else if(op == 1) {
            return 2;
        } else if(op == 2 || op == 3) {
            return 3;
        } else if(op == 4) {
            return 7;
        } else {
            return 6;
        }
    } else if(state == 4) {
        if(op == 0 || op == 1) {
            return 4;
        } else if(op == 2) {
            return 1;
        } else if(op == 3) {
            return 2;
        } else if(op == 4) {
            return 6;
        } else {
            return 7;
        }
    } else if(state == 5) {
        if(op == 0) {
            return 6;
        } else if(op == 1) {
            return 7;
        } else if(op == 2 || op == 3) {
            return 3;
        } else if(op == 4) {
            return 2;
        } else {
            return 1;
        }
    } else if(state == 6) {
        if(op == 0) {
            return 6;
        } else if(op == 1) {
            return 0;
        } else if(op == 2) {
            return 1;
        } else if(op == 3) {
            return 3;
        } else if(op == 4) {
            return 4;
        } else {
            return 3;
        }
    } else {
        if(op == 0) {
            return 0;
        } else if(op == 1) {
            return 7;
        } else if(op == 2) {
            return 3;
        } else if(op == 3) {
            return 2;
        } else if(op == 4) {
            return 3;
        } else {
            return 4;
        }
    }
}

int dfs(int v, graph& g, int prev, int state, int turn, vector<int> const& ord) {
    if(g.size() == 1) {
        return 0;
    }
    if(g[v].size() == 1 && prev != -1) {
        return state;
    }
    int res = -1;
    for(auto to : g[v]) {
        if(to == prev) {
            continue;
        }
        int t = dfs(to, g, v, proc(state, op[to]), turn^1, ord);
        if(turn == 0) {
            if(res == -1 || ord[res] < ord[t]) {
                res = t;
            }
        } else {
            if(res == -1 || ord[t] < ord[res]) {
                res = t;
            }
        }
    }
    return res;
}

int main() {
    int N, M;
    cin >> N >> M;
    op.resize(N);
    for(int i=1; i<N; ++i) {
        string o;
        cin >> o;
        char c1 = o[3], c2 = o[4];
        if(c1 == '&') {
            op[i] = o[4] - 'X';
        } else if(c1 == '|') {
            op[i] = 2 + o[4] - 'X';
        } else {
            op[i] = 4 + o[4] - 'X';
        }
    }
    vector<vector<int>> g(N);
    for(int i=0; i<N-1; ++i) {
        int u, v;
        cin >> u >> v;
        g[u].push_back(v);
        g[v].push_back(u);
    }

    for(int i=0; i<M; ++i) {
        int x, y;
        cin >> x >> y;
        vector<pair<int, int>> v(8);
        vector<int> v2(8);
        v[0] = make_pair(0, 0);
        v[1] = make_pair(x, 1);
        v[2] = make_pair(y, 2);
        v[3] = make_pair(x|y, 3);
        v[4] = make_pair(x&y, 4);
        v[5] = make_pair(x^y, 5);
        v[6] = make_pair(x^(x&y), 6);
        v[7] = make_pair(y^(x&y), 7);
        auto v3 = v;
        sort(v.begin(), v.end());
        for(int i=0; i<8; ++i) {
            v2[v[i].second] = i;
        }
        if(memo.count(v2) == 0) {
            memo[v2] = dfs(0, g, -1, 0, 0, v2);
        }
        cout << v3[memo[v2]].first << endl;
    }
}
accuracy: 1
time_ms: 200
memory_kb: 18348
final_rank: 4

code_snippet: #include <bits/stdc++.h>
using namespace std;
#define all(v) (v).begin(),(v).end()
#define pb(a) push_back(a)
#define rep(i, n) for(int i=0;i<n;i++)
#define foa(e, v) for(auto&& e : v)
using ll = long long;
const ll MOD7 = 1000000007, MOD998 = 998244353, INF = (1LL << 60);
#define dout(a) cout<<fixed<<setprecision(10)<<a<<endl;

int main() {
    cin.tie(0);
    ios::sync_with_stdio(false);

    int n, q; cin >> n >> q;
    vector<string> s(n);
    for(int i = 1; i < n; i ++) cin >> s[i];
    vector<vector<int>> v(n);

    rep(i, n - 1) {
        int a, b; cin >> a >> b;
        v[a].pb(b);
        v[b].pb(a);
    }
    int ans[64][2][2];
    memset(ans, -1, sizeof(ans));

    auto solve = [&](int x, int y, int ordbit) -> void {
        vector<int> nx(n, -1);

        auto eval = [&](int T, int X, int Y, string t) -> int {
            if(t == "T=T|X") return (T|X);
            if(t == "T=T|Y") return (T|Y);
            if(t == "T=T&X") return (T&X);
            if(t == "T=T&Y") return (T&Y);
            if(t == "T=T^X") return (T^X);
            return (T^Y);
        };
        auto dfs = [&](auto dfs, int now, int p, int sum, bool f) -> int {
            int m = (f ? (1 << 20) : -1);
            foa(e, v[now]) {
                if(e == p) continue;
                int ret = dfs(dfs, e, now, eval(sum, x, y, s[e]), f ^ 1);
                if(f) {
                    if(m > ret) {
                        m = ret;
                        nx[now] = e;
                    }
                } else {
                    if(m < ret) {
                        m = ret;
                        nx[now] = e;
                    }
                }
            } 
            return (m == (1 << 20) or m == -1 ? sum : m);
        };
        dfs(dfs, 0, -1, 0, 0);
        x = 12, y = 10;
        
        int now = 0, sum = 0;
        while(nx[now] != -1) {
            now = nx[now];
            sum = eval(sum, x, y, s[now]);
        }
        rep(i, 4) ans[ordbit][x >> i & 1][y >> i & 1] = sum >> i & 1;
        return;
    };

    rep(i, q) {
        int x, y;
        cin >> x >> y;
        int cnt = 0, f01 = 0, f10 = 0, f11 = 0, ordbit = 0;
        for(int j = 15; j >= 0; j --) {
            if(x >> j & 1) {
                if(y >> j & 1) {
                    if(!f11) {
                        ordbit |= 3 << cnt;
                        cnt += 2;
                        f11 = 1;
                    }
                } else {
                    if(!f10) {
                        ordbit |= 2 << cnt;
                        cnt += 2;
                        f10 = 1;
                    }
                }
            } else {
                if(y >> j & 1) {
                    if(!f01) {
                        ordbit |= 1 << cnt;
                        cnt += 2;
                        f01 = 1;
                    }
                }
            }
        }
        if(ans[ordbit][1][1] == -1) {
            solve(x, y, ordbit);
        }
        int res = 0;
        rep(j, 16) {
            res |= (1 << j) * ans[ordbit][x >> j & 1][y >> j & 1];
        }
        cout << res << endl;
    }
    
    

    return 0;
}
accuracy: 1
time_ms: 240
memory_kb: 30804
final_rank: 8

code_snippet: // AOJ #2713 Bit Operation Game
// 2025.3.16

#include <bits/stdc++.h>
using namespace std;

#define gc() getchar_unlocked()
#define pc(c) putchar_unlocked(c)

int Cin() {
	int n = 0; int c = gc();
	do n = 10*n + (c & 0xf), c = gc(); while (c >= '0');
	return n;
}

char temp[100];
string Cins() {
    char *s = temp;
	do *s = gc();
	while (*s++ > ' ');
	*(s-1) = 0;
    string input(temp);
    return input;
}

void Cout(int n) {
	char b[30];
	if (!n) pc('0');
	else {
		if (n < 0) pc('-'), n = -n;
		int i = 0; while (n) b[i++] = n % 10 + '0', n /= 10;
		while (i--) pc(b[i]);
	}
	pc('\n');
}

typedef pair<int, int> Pair;

const int MAX_N = 100000;

int N, M;
int queryX, queryY;
vector<string> ops(MAX_N);
vector<vector<int>> graph(MAX_N);

map<vector<int>, int> memo;

int applyOp(const string &op, int v) {
    int t = queryX;
    if (op[4] == 'Y') t = queryY;
    if (op[3] == '&') return v & t;
    if (op[3] == '|') return v | t;
    return v ^ t;
 }

int dfs(int pos, int par, int dep, int val) {
    if (par != -1) {
        val = applyOp(ops[pos], val);
        if (graph[pos].size() == 1) return val;
    }

    bool isMin = (dep & 1);
    int ans = isMin ? (queryX | queryY) : 0;

    for (int next : graph[pos]) {
        if (next == par) continue;
        int can = dfs(next, pos, dep + 1, val);
        if (isMin) ans = min(ans, can);
        else       ans = max(ans, can);
    }
    return ans;
}

int solve() {
    if (N == 1) return 0;
    vector<Pair> candidates;
    candidates.push_back({queryX, 0});
    candidates.push_back({queryY, 1});
    candidates.push_back({queryX | queryY, 2});
    candidates.push_back({queryX & queryY, 3});
    candidates.push_back({(queryX | queryY) - queryX, 4});
    candidates.push_back({(queryX | queryY) - queryY, 5});
    candidates.push_back({(queryX | queryY) - (queryX & queryY), 6});
    candidates.push_back({0, 7});

    sort(candidates.begin(), candidates.end());
    vector<int> cacheKey;
    for (int i = 0; i < 8; i++) {
        cacheKey.push_back(candidates[i].second);
    }

    if (memo.count(cacheKey)) {
        int cachedId = memo[cacheKey];
        for (int i = 0; i < 8; i++) {
            if (candidates[i].second == cachedId)
                return candidates[i].first;
        }
    }

    int ans = dfs(0, -1, 0, 0);
    for (int i = 0; i < 8; i++) {
        if (ans == candidates[i].first) {
            memo[cacheKey] = candidates[i].second;
            break;
        }
    }
    return ans;
}

int main(){
    N = Cin(), M = Cin();
    for (int i = 1; i < N; i++) ops[i] = Cins();
    graph.assign(N, vector<int>());
    for (int i = 1; i < N; i++) {
        int u = Cin(), v = Cin();
        graph[u].push_back(v);
        graph[v].push_back(u);
    }
    while (M--) {
        queryX = Cin(), queryY = Cin();
        Cout(solve());
    }
    return 0;
}
accuracy: 1
time_ms: 70
memory_kb: 19248
final_rank: 1

code_snippet: #include <bits/stdc++.h>

using namespace std;

#define rep(i, a, b) for (int i = (int)(a); i < (int)(b); i++)
#define rrep(i, a, b) for (int i = (int)(b)-1; i >= (int)(a); i--)
#define ALL(v) (v).begin(), (v).end()
#define UNIQUE(v) sort(ALL(v)), (v).erase(unique(ALL(v)), (v).end())
#define SZ(v) (int)v.size()
#define MIN(v) *min_element(ALL(v))
#define MAX(v) *max_element(ALL(v))
#define LB(v, x) int(lower_bound(ALL(v), (x)) - (v).begin())
#define UB(v, x) int(upper_bound(ALL(v), (x)) - (v).begin())

using uint = unsigned int;
using ll = long long int;
using ull = unsigned long long;
using i128 = __int128_t;
using u128 = __uint128_t;
const int inf = 0x3fffffff;
const ll INF = 0x1fffffffffffffff;

template <typename T> inline bool chmax(T &a, T b) {
    if (a < b) {
        a = b;
        return 1;
    }
    return 0;
}
template <typename T> inline bool chmin(T &a, T b) {
    if (a > b) {
        a = b;
        return 1;
    }
    return 0;
}
template <typename T, typename U> T ceil(T x, U y) {
    assert(y != 0);
    if (y < 0)
        x = -x, y = -y;
    return (x > 0 ? (x + y - 1) / y : x / y);
}
template <typename T, typename U> T floor(T x, U y) {
    assert(y != 0);
    if (y < 0)
        x = -x, y = -y;
    return (x > 0 ? x / y : (x - y + 1) / y);
}
template <typename T> int popcnt(T x) {
    return __builtin_popcountll(x);
}
template <typename T> int topbit(T x) {
    return (x == 0 ? -1 : 63 - __builtin_clzll(x));
}
template <typename T> int lowbit(T x) {
    return (x == 0 ? -1 : __builtin_ctzll(x));
}

template <class T, class U>
ostream &operator<<(ostream &os, const pair<T, U> &p) {
    os << "P(" << p.first << ", " << p.second << ")";
    return os;
}
template <typename T> ostream &operator<<(ostream &os, const vector<T> &vec) {
    os << "{";
    for (int i = 0; i < vec.size(); i++) {
        os << vec[i] << (i + 1 == vec.size() ? "" : ", ");
    }
    os << "}";
    return os;
}
template <typename T, typename U>
ostream &operator<<(ostream &os, const map<T, U> &map_var) {
    os << "{";
    for (auto itr = map_var.begin(); itr != map_var.end(); itr++) {
        os << "(" << itr->first << ", " << itr->second << ")";
        itr++;
        if (itr != map_var.end())
            os << ", ";
        itr--;
    }
    os << "}";
    return os;
}
template <typename T> ostream &operator<<(ostream &os, const set<T> &set_var) {
    os << "{";
    for (auto itr = set_var.begin(); itr != set_var.end(); itr++) {
        os << *itr;
        ++itr;
        if (itr != set_var.end())
            os << ", ";
        itr--;
    }
    os << "}";
    return os;
}
#ifdef LOCAL
#define show(...) _show(0, #__VA_ARGS__, __VA_ARGS__)
#else
#define show(...) true
#endif
template <typename T> void _show(int i, T name) {
    cerr << '\n';
}
template <typename T1, typename T2, typename... T3>
void _show(int i, const T1 &a, const T2 &b, const T3 &...c) {
    for (; a[i] != ',' && a[i] != '\0'; i++)
        cerr << a[i];
    cerr << ":" << b << " ";
    _show(i + 1, a, c...);
}

#include <unistd.h>

namespace fastio {
static constexpr uint32_t SZ = 1 << 17;
char ibuf[SZ];
char obuf[SZ];
char out[100];
// pointer of ibuf, obuf


uint32_t pil = 0, pir = 0, por = 0;

struct Pre {
    char num[10000][4];
    constexpr Pre() : num() {
        for (int i = 0; i < 10000; i++) {
            int n = i;
            for (int j = 3; j >= 0; j--) {
                num[i][j] = n % 10 | '0';
                n /= 10;
            }
        }
    }
} constexpr pre;

inline void load() {
    memmove(ibuf, ibuf + pil, pir - pil);
    pir = pir - pil + fread(ibuf + pir - pil, 1, SZ - pir + pil, stdin);
    pil = 0;
    if (pir < SZ)
        ibuf[pir++] = '\n';
}

inline void flush() {
    fwrite(obuf, 1, por, stdout);
    por = 0;
}

void rd(char &c) {
    do {
        if (pil + 1 > pir)
            load();
        c = ibuf[pil++];
    } while (isspace(c));
}

void rd(string &x) {
    x.clear();
    char c;
    do {
        if (pil + 1 > pir)
            load();
        c = ibuf[pil++];
    } while (isspace(c));
    do {
        x += c;
        if (pil == pir)
            load();
        c = ibuf[pil++];
    } while (!isspace(c));
}

template <typename T> void rd_real(T &x) {
    string s;
    rd(s);
    x = stod(s);
}

template <typename T> void rd_integer(T &x) {
    if (pil + 100 > pir)
        load();
    char c;
    do
        c = ibuf[pil++];
    while (c < '-');
    bool minus = 0;
    if constexpr (is_signed<T>::value || is_same_v<T, i128>) {
        if (c == '-') {
            minus = 1, c = ibuf[pil++];
        }
    }
    x = 0;
    while ('0' <= c) {
        x = x * 10 + (c & 15), c = ibuf[pil++];
    }
    if constexpr (is_signed<T>::value || is_same_v<T, i128>) {
        if (minus)
            x = -x;
    }
}

void rd(int &x) {
    rd_integer(x);
}
void rd(ll &x) {
    rd_integer(x);
}
void rd(i128 &x) {
    rd_integer(x);
}
void rd(uint &x) {
    rd_integer(x);
}
void rd(ull &x) {
    rd_integer(x);
}
void rd(u128 &x) {
    rd_integer(x);
}
void rd(double &x) {
    rd_real(x);
}
void rd(long double &x) {
    rd_real(x);
}

template <class T, class U> void rd(pair<T, U> &p) {
    return rd(p.first), rd(p.second);
}
template <size_t N = 0, typename T> void rd_tuple(T &t) {
    if constexpr (N < std::tuple_size<T>::value) {
        auto &x = std::get<N>(t);
        rd(x);
        rd_tuple<N + 1>(t);
    }
}
template <class... T> void rd(tuple<T...> &tpl) {
    rd_tuple(tpl);
}

template <size_t N = 0, typename T> void rd(array<T, N> &x) {
    for (auto &d : x)
        rd(d);
}
template <class T> void rd(vector<T> &x) {
    for (auto &d : x)
        rd(d);
}

void read() {}
template <class H, class... T> void read(H &h, T &...t) {
    rd(h), read(t...);
}

void wt(const char c) {
    if (por == SZ)
        flush();
    obuf[por++] = c;
}
void wt(const string s) {
    for (char c : s)
        wt(c);
}
void wt(const char *s) {
    size_t len = strlen(s);
    for (size_t i = 0; i < len; i++)
        wt(s[i]);
}

template <typename T> void wt_integer(T x) {
    if (por > SZ - 100)
        flush();
    if (x < 0) {
        obuf[por++] = '-', x = -x;
    }
    int outi;
    for (outi = 96; x >= 10000; outi -= 4) {
        memcpy(out + outi, pre.num[x % 10000], 4);
        x /= 10000;
    }
    if (x >= 1000) {
        memcpy(obuf + por, pre.num[x], 4);
        por += 4;
    } else if (x >= 100) {
        memcpy(obuf + por, pre.num[x] + 1, 3);
        por += 3;
    } else if (x >= 10) {
        int q = (x * 103) >> 10;
        obuf[por] = q | '0';
        obuf[por + 1] = (x - q * 10) | '0';
        por += 2;
    } else
        obuf[por++] = x | '0';
    memcpy(obuf + por, out + outi + 4, 96 - outi);
    por += 96 - outi;
}

template <typename T> void wt_real(T x) {
    ostringstream oss;
    oss << fixed << setprecision(15) << double(x);
    string s = oss.str();
    wt(s);
}

void wt(int x) {
    wt_integer(x);
}
void wt(ll x) {
    wt_integer(x);
}
void wt(i128 x) {
    wt_integer(x);
}
void wt(uint x) {
    wt_integer(x);
}
void wt(ull x) {
    wt_integer(x);
}
void wt(u128 x) {
    wt_integer(x);
}
void wt(double x) {
    wt_real(x);
}
void wt(long double x) {
    wt_real(x);
}

template <class T, class U> void wt(const pair<T, U> val) {
    wt(val.first);
    wt(' ');
    wt(val.second);
}
template <size_t N = 0, typename T> void wt_tuple(const T t) {
    if constexpr (N < std::tuple_size<T>::value) {
        if constexpr (N > 0) {
            wt(' ');
        }
        const auto x = std::get<N>(t);
        wt(x);
        wt_tuple<N + 1>(t);
    }
}
template <class... T> void wt(tuple<T...> tpl) {
    wt_tuple(tpl);
}
template <class T, size_t S> void wt(const array<T, S> val) {
    auto n = val.size();
    for (size_t i = 0; i < n; i++) {
        if (i)
            wt(' ');
        wt(val[i]);
    }
}
template <class T> void wt(const vector<T> val) {
    auto n = val.size();
    for (size_t i = 0; i < n; i++) {
        if (i)
            wt(' ');
        wt(val[i]);
    }
}

void print() {
    wt('\n');
}
template <class Head, class... Tail> void print(Head &&head, Tail &&...tail) {
    wt(head);
    if (sizeof...(Tail))
        wt(' ');
    print(forward<Tail>(tail)...);
}
void __attribute__((destructor)) _d() {
    flush();
}
} // namespace fastio


using fastio::flush;
using fastio::print;
using fastio::read;

inline void first(bool i = true) {
    print(i ? "first" : "second");
}
inline void Alice(bool i = true) {
    print(i ? "Alice" : "Bob");
}
inline void Takahashi(bool i = true) {
    print(i ? "Takahashi" : "Aoki");
}
inline void yes(bool i = true) {
    print(i ? "yes" : "no");
}
inline void Yes(bool i = true) {
    print(i ? "Yes" : "No");
}
inline void No() {
    print("No");
}
inline void YES(bool i = true) {
    print(i ? "YES" : "NO");
}
inline void NO() {
    print("NO");
}
inline void Yay(bool i = true) {
    print(i ? "Yay!" : ":(");
}
inline void Possible(bool i = true) {
    print(i ? "Possible" : "Impossible");
}
inline void POSSIBLE(bool i = true) {
    print(i ? "POSSIBLE" : "IMPOSSIBLE");
}

/**
 * @brief Fast IO
 */

int Op(string S, int T, int X, int Y) {
    if (S == "T=0") return 0;
    if (S == "T=T|X") return T|X;
    if (S == "T=T^X") return T^X;
    if (S == "T=T&X") return T&X;
    if (S == "T=T|Y") return T|Y;
    if (S == "T=T^Y") return T^Y;
    if (S == "T=T&Y") return T&Y;
    return -1;
}

int N;
vector<string> S;
vector<vector<int>> G;

void ch(int& A, int B, int turn) {
    if (turn == 0) chmax(A,B);
    else chmin(A,B);
}

int DFS(int P, int T, int turn, int X, int Y) {
    int NT = Op(S[P],T,X,Y);
    if (G[P].empty()) return NT;
    int Ret;
    if (turn == 0) Ret = -inf;
    else Ret = inf;
    for (int NP : G[P]) {
        ch(Ret,DFS(NP,NT,1-turn,X,Y),turn);
    }
    return Ret;
}

int main() {
    int Q;
    cin >> N >> Q;
    S.resize(N);
    S[0] = "T=0";
    rep(i,1,N) cin >> S[i];
    G.resize(N);
    rep(i,0,N-1) {
        int a, b;
        cin >> a >> b;
        G[a].push_back(b), G[b].push_back(a);
    }
    queue<int> QQ;
    vector<bool> used(N,false);
    used[0] = true;
    QQ.push(0);
    while(!QQ.empty()) {
        int P = QQ.front();
        QQ.pop();
        rep(i,0,G[P].size()) {
            if (used[G[P][i]]) {
                swap(G[P][i], G[P].back());
                G[P].pop_back();
                break;
            }
        }
        rep(i,0,G[P].size()) used[G[P][i]] = true, QQ.push(G[P][i]);
    }
    vector<int> A = {0,1,2};
    vector<int> ANS(27);
    do {
        int X = 0, Y = 0;
        Y += 1<<(2-A[0]);
        X += 1<<(2-A[1]);
        X += 1<<(2-A[2]);
        Y += 1<<(2-A[2]);
        ANS[A[0]*9+A[1]*3+A[2]] = DFS(0,0,0,X,Y);
        int D = DFS(0,0,0,X,Y);
    } while(next_permutation(A.begin(), A.end()));
    rep(i,0,Q) {
        int x, y;
        cin >> x >> y;
        vector<int> X(16), Y(16);
        rrep(j,0,16) {
            X[j] = x % 2;
            x /= 2;
            Y[j] = y % 2;
            y /= 2;
        }
        vector<int> Z(3,-1);
        int Cur = 0;
        rep(j,0,16) {
            if (X[j] == 0 && Y[j] == 0) continue;
            int x = X[j] * 2 + Y[j] - 1;
            if (Z[x] == -1) {
                Z[x] = Cur;
                Cur++;
            }
        }
        rep(j,0,3) {
            if (Z[j] == -1) {
                Z[j] = Cur;
                Cur++;
            }
        }
        int Ret = ANS[Z[0]*9+Z[1]*3+Z[2]];
        int V[4];
        V[0] = 0;
        rep(j,0,3) {
            V[j+1] = (Ret >> (2-Z[j])) & 1;
        }
        int SUM = 0;
        rep(j,0,16) {
            SUM += (1<<(15-j)) * V[X[j]*2+Y[j]];
        }
        cout << SUM << endl;
    }
}
accuracy: 1
time_ms: 250
memory_kb: 22608
final_rank: 7

code_snippet: #include<iostream>
#include<vector>
#include<algorithm>
#include<map>
#include<string>
#include<numeric>
using namespace std;
int main(){
  ios::sync_with_stdio(false);
  cin.tie(nullptr);
  int n,m;
  cin>>n>>m;
  vector<string>o(n);
  for(int i=1;i<n;i++)cin>>o[i];
  vector<vector<int>>to(n);
  for(int i=0;i<n-1;i++){
    int u,v;
    cin>>u>>v;
    to[u].push_back(v);
    to[v].push_back(u);
  }
  vector<int>ord(8);
  auto dfs=[&](auto self,int x,int p,int now,int dep)->int {
    if(to[x].size()==1&&to[x][0]==p)return now;
    int ret=-1;
    for(auto i:to[x])if(i!=p){
	int op=o[i][4]=='X'?3:6;
	int nx=now;
	if(o[i][3]=='&')nx&=op;
	else if(o[i][3]=='|')nx|=op;
	else if(o[i][3]=='^')nx^=op;
	else exit(1);
	int nv=self(self,i,x,nx,dep^1);
	if(ret==-1)ret=nv;
	else if(dep==0){
	  if(ord[ret]<ord[nv])ret=nv;
	}
	else if(dep==1){
	  if(ord[ret]>ord[nv])ret=nv;
	}
      }
    return ret;
  };
  map<vector<int>,int>mp;
  for(int i=0;i<m;i++){
    int x,y;
    cin>>x>>y;
    vector<int>a{x&(~y),x&y,(~x)&y};
    vector<int>b(8,0);
    for(int j=0;j<8;j++){
      for(int k=0;k<3;k++)if(j>>k&1)b[j]|=a[k];
    }
    vector<int>id(8);
    iota(id.begin(),id.end(),0);
    sort(id.begin(),id.end(),[&](int l,int r){return b[l]<b[r];});
    for(int j=0;j<8;j++)ord[id[j]]=j;
    if(mp.find(ord)==mp.end())mp[ord]=dfs(dfs,0,-1,0,0);
    int s=mp[ord];
    int ans=0;
    for(int j=0;j<3;j++)if(s>>j&1)ans|=a[j];
    cout<<ans<<endl;
  }
}
accuracy: 1
time_ms: 120
memory_kb: 22568
final_rank: 2

code_snippet: #include<iostream>
#include<vector>
#include<algorithm>
#include<map>
#include<string>
#include<numeric>
using namespace std;
int main(){
  int n,m;
  cin>>n>>m;
  vector<string>o(n);
  for(int i=1;i<n;i++)cin>>o[i];
  vector<vector<int>>to(n);
  for(int i=0;i<n-1;i++){
    int u,v;
    cin>>u>>v;
    to[u].push_back(v);
    to[v].push_back(u);
  }
  vector<int>ord(8);
  auto dfs=[&](auto self,int x,int p,int now,int dep)->int {
    if(to[x].size()==1&&to[x][0]==p)return now;
    int ret=-1;
    for(auto i:to[x])if(i!=p){
	int op=o[i][4]=='X'?3:6;
	int nx=now;
	if(o[i][3]=='&')nx&=op;
	else if(o[i][3]=='|')nx|=op;
	else if(o[i][3]=='^')nx^=op;
	else exit(1);
	int nv=self(self,i,x,nx,dep^1);
	if(ret==-1)ret=nv;
	else if(dep==0){
	  if(ord[ret]<ord[nx])ret=nv;
	}
	else if(dep==1){
	  if(ord[ret]>ord[nx])ret=nv;
	}
      }
    return ret;
  };
  map<vector<int>,int>mp;
  for(int i=0;i<m;i++){
    int x,y;
    cin>>x>>y;
    vector<int>a{x&~y,x&y,~x&y};
    vector<int>b(8,0);
    for(int j=0;j<8;j++){
      for(int k=0;k<3;k++)if(j>>k&1)b[j]|=a[k];
    }
    vector<int>id(8);
    iota(id.begin(),id.end(),0);
    sort(id.begin(),id.end(),[&](int l,int r){return b[l]<b[r];});
    for(int j=0;j<8;j++)ord[id[j]]=j;
    if(mp.find(ord)==mp.end())mp[ord]=dfs(dfs,0,-1,0,0);
    int s=mp[ord];
    int ans=0;
    for(int j=0;j<3;j++)if(s>>j&1)ans|=a[j];
    cout<<ans<<endl;
  }
}
accuracy: 0.0196078431372549
time_ms: 160
memory_kb: 11548
final_rank: 17

code_snippet: #include<iostream>
#include<vector>
#include<algorithm>
#include<map>
#include<string>
#include<numeric>
using namespace std;
int main(){
  int n,m;
  cin>>n>>m;
  vector<string>o(n);
  for(int i=1;i<n;i++)cin>>o[i];
  vector<vector<int>>to(n);
  for(int i=0;i<n-1;i++){
    int u,v;
    cin>>u>>v;
    to[u].push_back(v);
    to[v].push_back(u);
  }
  vector<int>ord(8);
  auto dfs=[&](auto self,int x,int p,int now,int dep)->int {
    if(to[x].size()==1&&to[x][0]==p)return now;
    int ret=-1;
    for(auto i:to[x])if(i!=p){
	int op=o[i][4]=='X'?3:6;
	int nx=now;
	if(o[i][3]=='&')nx&=op;
	else if(o[i][3]=='|')nx|=op;
	else nx^=op;
	int nv=self(self,i,x,nx,dep^1);
	if(ret==-1)ret=nv;
	else if(dep==0){
	  if(ord[ret]<ord[nx])ret=nv;
	}
	else if(dep==1){
	  if(ord[ret]>ord[nx])ret=nv;
	}
      }
    return ret;
  };
  map<vector<int>,int>mp;
  for(int i=0;i<m;i++){
    int x,y;
    cin>>x>>y;
    vector<int>a{x&~y,x&y,~x&y};
    vector<int>b(8);
    for(int j=0;j<8;j++){
      for(int k=0;k<3;k++)if(j>>k&1)b[j]|=a[k];
    }
    vector<int>id(8);
    iota(id.begin(),id.end(),0);
    sort(id.begin(),id.end(),[&](int l,int r){return b[l]<b[r];});
    for(int j=0;j<8;j++)ord[id[j]]=j;
    if(mp.find(ord)==mp.end())mp[ord]=dfs(dfs,0,-1,0,0);
    int s=mp[ord];
    int ans=0;
    for(int j=0;j<3;j++)if(s>>j&1)ans|=a[j];
    cout<<ans<<endl;
  }
}
accuracy: 0.0196078431372549
time_ms: 160
memory_kb: 11620
final_rank: 18

code_snippet: #include <bits/stdc++.h>
using namespace std;

int N, U[1 << 19], V[1 << 19], Type[1 << 19], Level[1 << 19]; string S[1 << 19];
int Q, X[1 << 19], Y[1 << 19];
bool Win1[256][1 << 17];
bool Win2[256][1 << 17];
vector<int> G[1 << 19];
vector<int> H[1 << 19];

void solve(int mask, int pos) {
    if (H[pos].size() == 0) {
        if ((mask & (1 << Level[pos])) != 0) {
            Win1[mask][pos] = true;
            Win2[mask][pos] = false;
        }
        else {
            Win1[mask][pos] = false;
            Win2[mask][pos] = true;
        }
        return;
    }
    for (int to : H[pos]) {
        solve(mask, to);
        if (Win2[mask][to] == false) Win1[mask][pos] = true;
        if (Win1[mask][to] == false) Win2[mask][pos] = true;
    }
}

void dfs(int pos, int pre, int cur) {
    if (cur ==   0) Level[pos] = 0;
    if (cur ==  24) Level[pos] = 1;
    if (cur ==  96) Level[pos] = 2;
    if (cur == 120) Level[pos] = 3;
    if (cur == 773) Level[pos] = 4;
    if (cur == 797) Level[pos] = 5;
    if (cur == 869) Level[pos] = 6;
    if (cur == 893) Level[pos] = 7;

    // DFS
    for (int to : G[pos]) {
        if (to == pre) continue;
        int nex = 0;
        if (Type[to] == 1) nex = (cur & 869);
        if (Type[to] == 2) nex = (cur & 120);
        if (Type[to] == 3) nex = (cur | 869);
        if (Type[to] == 4) nex = (cur | 120);
        if (Type[to] == 5) nex = (cur ^ 869);
        if (Type[to] == 6) nex = (cur ^ 120);
        dfs(to, pos, nex);
        H[pos].push_back(to);
    }
}

int main() {
    // Step 1. Input
    cin >> N >> Q;
    for (int i = 1; i <= N - 1; i++) cin >> S[i];
    for (int i = 1; i <= N - 1; i++) cin >> U[i] >> V[i];
    for (int i = 1; i <= Q; i++) cin >> X[i] >> Y[i];

    // Step 2. Get Type
    for (int i = 1; i <= N - 1; i++) {
        if (S[i] == "T=T&X") Type[i] = 1;
        if (S[i] == "T=T&Y") Type[i] = 2;
        if (S[i] == "T=T|X") Type[i] = 3;
        if (S[i] == "T=T|Y") Type[i] = 4;
        if (S[i] == "T=T^X") Type[i] = 5;
        if (S[i] == "T=T^Y") Type[i] = 6;
    }

    // Step 3. Get Graph
    for (int i = 1; i <= N - 1; i++) {
        G[U[i]].push_back(V[i]);
        G[V[i]].push_back(U[i]);
    }
    dfs(0, -1, 0);

    // Step 4. Zentansaku
    for (int i = 0; i < 256; i++) {
        solve(i, 0);
    }

    // Step 5. Get Query
    for (int i = 1; i <= Q; i++) {
        vector<pair<int, int>> Vec;
        Vec.push_back(make_pair(0 & X[i], 0));
        Vec.push_back(make_pair(((0 | X[i]) & Y[i]) ^ Y[i], 1));
        Vec.push_back(make_pair(((0 | X[i]) & Y[i]), 2));
        Vec.push_back(make_pair(0 | Y[i], 3));
        Vec.push_back(make_pair(((0 | X[i]) & Y[i]) ^ X[i], 4));
        Vec.push_back(make_pair(((0 | X[i]) ^ Y[i]), 5));
        Vec.push_back(make_pair(0 | X[i], 6));
        Vec.push_back(make_pair(((0 | X[i]) | Y[i]), 7));
        sort(Vec.begin(), Vec.end());
        int mask = 255, ans = Vec[0].first;
        for (int j = 0; j < (int)Vec.size() - 1; j++) {
            mask -= (1 << (Vec[j].second));
            if (Win1[mask][0] == true) ans = Vec[j + 1].first;
        }
        cout << ans << endl;
    }
    return 0;
}
accuracy: 1
time_ms: 600
memory_kb: 137820
final_rank: 12

code_snippet: #include <bits/stdc++.h>
using namespace std;

int N, U[1 << 19], V[1 << 19], Type[1 << 19], Level[1 << 19]; string S[1 << 19];
int Q, X[1 << 19], Y[1 << 19];
bool Win[256][1 << 17];
vector<int> G[1 << 19];
vector<int> H[1 << 19];

void solve(int mask, int pos) {
    if (H[pos].size() == 0) {
        if ((mask & (1 << Level[pos])) != 0) Win[mask][pos] = true;
        else Win[mask][pos] = false;
        return;
    }
    for (int to : H[pos]) {
        solve(mask, to);
        if (Win[mask][to] == false) Win[mask][pos] = true;
    }
}

void dfs(int pos, int pre, int cur) {
    if (cur ==   0) Level[pos] = 0;
    if (cur ==  24) Level[pos] = 1;
    if (cur ==  96) Level[pos] = 2;
    if (cur == 120) Level[pos] = 3;
    if (cur == 773) Level[pos] = 4;
    if (cur == 797) Level[pos] = 5;
    if (cur == 869) Level[pos] = 6;
    if (cur == 893) Level[pos] = 7;

    // DFS
    for (int to : G[pos]) {
        if (to == pre) continue;
        int nex = 0;
        if (Type[to] == 1) nex = (cur & 869);
        if (Type[to] == 2) nex = (cur & 120);
        if (Type[to] == 3) nex = (cur | 869);
        if (Type[to] == 4) nex = (cur | 120);
        if (Type[to] == 5) nex = (cur ^ 869);
        if (Type[to] == 6) nex = (cur ^ 120);
        dfs(to, pos, nex);
        H[pos].push_back(to);
    }
}

int main() {
    // Step 1. Input
    cin >> N >> Q;
    for (int i = 1; i <= N - 1; i++) cin >> S[i];
    for (int i = 1; i <= N - 1; i++) cin >> U[i] >> V[i];
    for (int i = 1; i <= Q; i++) cin >> X[i] >> Y[i];

    // Step 2. Get Type
    for (int i = 1; i <= N - 1; i++) {
        if (S[i] == "T=T&X") Type[i] = 1;
        if (S[i] == "T=T&Y") Type[i] = 2;
        if (S[i] == "T=T|X") Type[i] = 3;
        if (S[i] == "T=T|Y") Type[i] = 4;
        if (S[i] == "T=T^X") Type[i] = 5;
        if (S[i] == "T=T^Y") Type[i] = 6;
    }

    // Step 3. Get Graph
    for (int i = 1; i <= N - 1; i++) {
        G[U[i]].push_back(V[i]);
        G[V[i]].push_back(U[i]);
    }
    dfs(0, -1, 0);

    // Step 4. Zentansaku
    for (int i = 0; i < 256; i++) {
        solve(i, 0);
    }

    // Step 5. Get Query
    for (int i = 1; i <= Q; i++) {
        vector<pair<int, int>> Vec;
        Vec.push_back(make_pair(0 & X[i], 0));
        Vec.push_back(make_pair(((0 | X[i]) & Y[i]) ^ Y[i], 1));
        Vec.push_back(make_pair(((0 | X[i]) & Y[i]), 2));
        Vec.push_back(make_pair(0 | Y[i], 3));
        Vec.push_back(make_pair(((0 | X[i]) & Y[i]) ^ X[i], 4));
        Vec.push_back(make_pair(((0 | X[i]) ^ Y[i]), 5));
        Vec.push_back(make_pair(0 | X[i], 6));
        Vec.push_back(make_pair(((0 | X[i]) | Y[i]), 7));
        sort(Vec.begin(), Vec.end());
        int mask = 255, ans = Vec[0].first;
        for (int j = 0; j < (int)Vec.size() - 1; j++) {
            mask -= (1 << (Vec[j].second));
            if (Win[mask][0] == true) ans = Vec[j + 1].first;
        }
        cout << ans << endl;
    }
    return 0;
}
accuracy: 0.0196078431372549
time_ms: 310
memory_kb: 94000
final_rank: 20

code_snippet: #include <string>
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;

vector<int> get_perm(int x, int y) {
	vector<int> appear(4, -1);
	for (int i = 0; i < 16; i++) {
		int z = ((x >> i) & 1) + ((y >> i) & 1) * 2;
		appear[z] = i;
	}
	vector<int> perm = { 0, 1, 2, 3 };
	sort(perm.begin(), perm.end(), [&](int va, int vb) {
		return appear[va] != appear[vb] ? appear[va] < appear[vb] : va < vb;
	});
	return perm;
}

int main() {
	// step #1. input
	cin.tie(0);
	ios::sync_with_stdio(false);
	int N, M;
	cin >> N >> M;
	vector<int> OP(N, -1);
	for (int i = 1; i < N; i++) {
		string str;
		cin >> str;
		if (str == "T=T&X") OP[i] = 0;
		if (str == "T=T&Y") OP[i] = 1;
		if (str == "T=T|X") OP[i] = 2;
		if (str == "T=T|Y") OP[i] = 3;
		if (str == "T=T^X") OP[i] = 4;
		if (str == "T=T^Y") OP[i] = 5;
	}
	vector<vector<int> > G(N);
	for (int i = 0; i < N - 1; i++) {
		int a, b;
		cin >> a >> b;
		G[a].push_back(b);
		G[b].push_back(a);
	}
	vector<int> X(M), Y(M);
	for (int i = 0; i < M; i++) {
		cin >> X[i] >> Y[i];
	}

	// step #2. dynamic programming
	vector<int> baseperm = { 0, 1, 2, 3 };
	vector<vector<int> > perms;
	do {
		perms.push_back(baseperm);
	} while (next_permutation(baseperm.begin(), baseperm.end()));
	vector<int> permx(24), permy(24);
	for (int i = 0; i < 24; i++) {
		for (int j = 0; j < 4; j++) {
			permx[i] |= ((perms[i][j] >> 0) & 1) << j;
			permy[i] |= ((perms[i][j] >> 1) & 1) << j;
		}
	}
	vector<vector<int> > dp(N);
	auto calc = [&](auto& self, int pos, int pre, int turn) -> void {
		dp[pos] = vector<int>(384, turn == 0 ? 0 : 15);
		bool leaf = true;
		for (int i : G[pos]) {
			if (i != pre) {
				leaf = false;
				self(self, i, pos, turn ^ 1);
				for (int j = 0; j < 24; j++) {
					for (int k = 0; k < 16; k++) {
						int res;
						switch (OP[i]) {
							case 0: res = dp[i][j * 16 + (k & permx[j])]; break;
							case 1: res = dp[i][j * 16 + (k & permy[j])]; break;
							case 2: res = dp[i][j * 16 + (k | permx[j])]; break;
							case 3: res = dp[i][j * 16 + (k | permy[j])]; break;
							case 4: res = dp[i][j * 16 + (k ^ permx[j])]; break;
							case 5: res = dp[i][j * 16 + (k ^ permy[j])]; break;
						}
						if (turn == 0) {
							dp[pos][j * 16 + k] = max(dp[pos][j * 16 + k], res);
						}
						else {
							dp[pos][j * 16 + k] = min(dp[pos][j * 16 + k], res);
						}
					}
				}
			}
		}
		if (leaf) {
			for (int i = 0; i < 384; i++) {
				dp[pos][i] = i % 16;
			}
		}
	};
	calc(calc, 0, -1, 0);

	// step #3. answer queries
	for (int i = 0; i < M; i++) {
		vector<int> p = get_perm(X[i], Y[i]);
		int idx = find(perms.begin(), perms.end(), p) - perms.begin();
		int res = dp[0][idx * 16 + 0];
		int answer = 0;
		for (int j = 0; j < 16; j++) {
			int code = ((X[i] >> j) & 1) + ((Y[i] >> j) & 1) * 2;
			int pos = find(perms[idx].begin(), perms[idx].end(), code) - perms[idx].begin();
			answer += ((res >> pos) & 1) << j;
		}
		cout << answer << '\n';
	}

	return 0;
}
accuracy: 1
time_ms: 210
memory_kb: 174672
final_rank: 14

code_snippet: #pragma GCC optimize("Ofast")
#include <iostream>
#include <vector>
#include <algorithm>
#include <map>
#include <queue>
#include <cstdio>
#include <ctime>
#include <assert.h>
#include <chrono>
#include <random>
#include <numeric>
#include <set>
#include <deque>
#include <stack>
#include <sstream>
#include <utility>
#include <cstring>
#include <unordered_map>
#include <unordered_set>
#include <tuple>
#include <array>
#include <bitset>
using namespace std;
typedef long long int ll;
typedef unsigned long long ull;

mt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count());
ll myRand(ll B) {
    return (ull)rng() % B;
}
inline double time() {
    return static_cast<long double>(chrono::duration_cast<chrono::nanoseconds>(chrono::steady_clock::now().time_since_epoch()).count()) * 1e-9;
}

int main(){
    cin.tie(nullptr);
    ios::sync_with_stdio(false);
    int n,m; cin >> n >> m;
    vector<int> state(n);
    for(int i=1;i<n;i++){
        string s; cin >> s;
        if(s == "T=T&X") state[i] = 0;
        else if(s == "T=T&Y") state[i] = 1;
        else if(s == "T=T|X") state[i] = 2;
        else if(s == "T=T|Y") state[i] = 3;
        else if(s == "T=T^X") state[i] = 4;
        else if(s == "T=T^Y") state[i] = 5;
    }
    vector<vector<int>> g(n);
    for(int i=1;i<n;i++){
        int x,y; cin >> x >> y;
        g[x].push_back(y);
        g[y].push_back(x);
    }
    vector<int> res(m);
    map<vector<int>,vector<int>> mp;
    vector<int> X(m),Y(m);
    for(int i=0;i<m;i++){
        cin >> X[i] >> Y[i];
        array<int, 4> cnt;
        vector<int> v;
        cnt[0] = cnt[1] = cnt[2] = cnt[3] = 0;
        for(int j=15;j>=0;j--){
            int bit = ((X[i]>>j)&1)*2 + ((Y[i]>>j)&1);
            if(cnt[bit] == 0){
                v.push_back(bit);
                cnt[bit]++;
            }
        }
        // ここは適当で良い
        for(int i=0;i<4;i++){
            if(cnt[i] == 0){
                v.push_back(i);
            }
        }
        mp[v].push_back(i);
    }
    vector<int> p = {0,1,2,3};
    do{
        if(mp.find(p) == mp.end()) continue;
        vector<int> dp(n);
        auto dfs=[&](auto dfs,int s,int pr,int f,int cur)->void{
            int res = cur;
            if(s){
                for(int i=3;i>=0;i--){
                    int x = (p[3-i]>>1)&1, y = (p[3-i])&1;
                    if(state[s] == 0){
                        if(x == 0 and res&(1<<i)) res ^= (1<<i);
                    }
                    else if(state[s] == 1){
                        if(y == 0 and res&(1<<i)) res ^= (1<<i);
                    }
                    else if(state[s] == 2){
                        if(x) res |= (1<<i);
                    }
                    else if(state[s] == 3){
                        if(y) res |= (1<<i);
                    }
                    else if(state[s] == 4){
                        if(x) res ^= (1<<i);
                    }
                    else{
                        if(y) res ^= (1<<i);
                    }
                }
            }
            cur = res;
            bool ff = false;
            // cout << s << " " << cur << endl;
            for(int t:g[s]){
                if(t == pr) continue;
                if(!ff) res = -1, ff = true;
                dfs(dfs,t,s,f^1,cur);
                if(res == -1) res = dp[t];
                if(f == 0){
                    res = max(res, dp[t]);
                }
                else{
                    res = min(res, dp[t]);
                }
            }
            dp[s] = res;
        };
        dfs(dfs,0,-1,0,0);
        // for(int i=0;i<4;i++){
            // cout << p[i] << " ";
        // }
        // cout << endl;
        // for(int i=0;i<n;i++){
            // cout << dp[i] << endl;
        // }
        array<int, 4> tr;
        for(int i=0;i<4;i++){
            tr[p[i]] = 3-i; // のbitを見れば良い
        }
        for(int idx:mp[p]){
            int x = X[idx], y = Y[idx];
            for(int i=0;i<=15;i++){
                int bit = ((x>>i)&1)*2 + ((y>>i)&1);
                if(dp[0]&(1<<tr[bit]))res[idx] |= (1<<i);
            }
        }
    }while(next_permutation(p.begin(), p.end()));
    for(int i=0;i<m;i++){
        cout << res[i] << "\n";
    }
}
accuracy: 1
time_ms: 140
memory_kb: 25292
final_rank: 6

code_snippet: #pragma GCC optimize("Ofast")
#include <iostream>
#include <vector>
#include <algorithm>
#include <map>
#include <queue>
#include <cstdio>
#include <ctime>
#include <assert.h>
#include <chrono>
#include <random>
#include <numeric>
#include <set>
#include <deque>
#include <stack>
#include <sstream>
#include <utility>
#include <cstring>
#include <unordered_map>
#include <unordered_set>
#include <tuple>
#include <array>
#include <bitset>
using namespace std;
typedef long long int ll;
typedef unsigned long long ull;

mt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count());
ll myRand(ll B) {
    return (ull)rng() % B;
}
inline double time() {
    return static_cast<long double>(chrono::duration_cast<chrono::nanoseconds>(chrono::steady_clock::now().time_since_epoch()).count()) * 1e-9;
}

int main(){
    cin.tie(nullptr);
    ios::sync_with_stdio(false);
    int n,m; cin >> n >> m;
    vector<int> state(n);
    for(int i=1;i<n;i++){
        string s; cin >> s;
        if(s == "T=T&X") state[i] = 0;
        else if(s == "T=T&Y") state[i] = 1;
        else if(s == "T=T|X") state[i] = 2;
        else if(s == "T=T|Y") state[i] = 3;
        else if(s == "T=T^X") state[i] = 4;
        else if(s == "T=T^Y") state[i] = 5;
    }
    vector<vector<int>> g(n);
    for(int i=1;i<n;i++){
        int x,y; cin >> x >> y;
        g[x].push_back(y);
        g[y].push_back(x);
    }
    vector<int> res(m);
    map<vector<int>,vector<int>> mp;
    vector<int> X(m),Y(m);
    for(int i=0;i<m;i++){
        cin >> X[i] >> Y[i];
        array<int, 4> cnt;
        vector<int> v;
        cnt[0] = cnt[1] = cnt[2] = cnt[3] = 0;
        for(int j=15;j>=0;j--){
            int bit = ((X[i]>>j)&1)*2 + ((Y[i]>>j)&1);
            if(cnt[bit] == 0){
                v.push_back(bit);
                cnt[bit]++;
            }
        }
        // ここは適当で良い
        for(int i=0;i<4;i++){
            if(cnt[i] == 0){
                v.push_back(i);
            }
        }
        mp[v].push_back(i);
    }
    vector<int> p = {0,1,2,3};
    do{
        if(mp.find(p) == mp.end()) continue;
        vector<int> dp(n);
        auto dfs=[&](auto dfs,int s,int pr,int f,int cur)->void{
            int res = cur;
            if(s){
                for(int i=3;i>=0;i--){
                    int x = (p[3-i]>>1)&1, y = (p[3-i])&1;
                    if(state[s] == 0){
                        if(x == 0 and res&(1<<i)) res ^= (1<<i);
                    }
                    else if(state[s] == 1){
                        if(y == 0 and res&(1<<i)) res ^= (1<<i);
                    }
                    else if(state[s] == 2){
                        if(x) res |= (1<<i);
                    }
                    else if(state[s] == 3){
                        if(y) res |= (1<<i);
                    }
                    else if(state[s] == 4){
                        if(x) res ^= (1<<i);
                    }
                    else{
                        if(y) res ^= (1<<i);
                    }
                }
            }
            cur = res;
            bool ff = false;
            // cout << s << " " << cur << endl;
            for(int t:g[s]){
                if(t == pr) continue;
                if(!ff) res = -1, ff = true;
                dfs(dfs,t,s,f^1,cur);
                if(res == -1) res = dp[t];
                if(f == 0){
                    res = max(res, dp[t]);
                }
                else{
                    res = min(res, dp[t]);
                }
            }
            dp[s] = res;
        };
        dfs(dfs,0,-1,0,0);
        // for(int i=0;i<4;i++){
            // cout << p[i] << " ";
        // }
        // cout << endl;
        // for(int i=0;i<n;i++){
            // cout << dp[i] << endl;
        // }
        array<int, 4> tr;
        for(int i=0;i<4;i++){
            tr[p[i]] = 3-i; // のbitを見れば良い
        }
        for(int idx:mp[p]){
            int x = X[idx], y = Y[idx];
            for(int i=0;i<15;i++){
                int bit = ((x>>i)&1)*2 + ((y>>i)&1);
                if(dp[0]&(1<<tr[bit]))res[idx] |= (1<<i);
            }
        }
    }while(next_permutation(p.begin(), p.end()));
    for(int i=0;i<m;i++){
        cout << res[i] << "\n";
    }
}
accuracy: 0.0196078431372549
time_ms: 90
memory_kb: 11188
final_rank: 15

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll = long long;
#define rep(i, s, t) for (int i = (int)(s); i < (int)(t); ++i)

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);
    cout << fixed << setprecision(15);

    int N, M;
    cin >> N >> M;
    vector<string> o(N);
    rep(i,1,N) cin >> o[i];
    vector<vector<int>> G(N);
    rep(i,0,N-1) {
        int u, v;
        cin >> u >> v;
        G[u].push_back(v);
        G[v].push_back(u);
    }
    vector<int> xx = {0, 0, 1, 1};
    vector<int> yy = {0, 1, 0, 1};
    vector<int> perm = {0, 1, 2, 3};
    map<pair<int, int>, int> mp;

    auto dfs = [&](auto& dfs, int v, int p, int d, int x, int y, int val) -> int {
        if (v == 0) val = 0;
        else {
            int z;
            if (o[v][4] == 'X') z = x;
            else z = y;
            if (o[v][3] == '&') val &= z;
            else if (o[v][3] == '|') val |= z;
            else val ^= z;
        }
        int ma = -1, mi = 1e9;
        for (int c : G[v]) {
            if (c == p) continue;
            auto a = dfs(dfs, c, v, d + 1, x, y, val);
            ma = max(ma, a);
            mi = min(mi, a);
        }
        if (ma == -1) return val;
        return d & 1 ? mi : ma;
    };

    do {
        int x = 0, y = 0;
        rep(i,0,4) x |= xx[perm[i]]<<i, y |= yy[perm[i]]<<i;
        mp[{x,y}] = dfs(dfs, 0, -1, 0, x, y, 0);
    } while (next_permutation(perm.begin(), perm.end()));

    while (M--) {
        int x, y;
        cin >> x >> y;
        set<pair<int, int>> st;
        int u = 0, v = 0;
        for (int i = 15; i >= 0; --i) {
            auto a = x>>i&1;
            auto b = y>>i&1;
            if (st.count({a,b})) continue;
            u |= a<<(3-st.size());
            v |= b<<(3-st.size());
            st.insert({a,b});
        }
        rep(i,0,2) rep(j,0,2) {
            if (!st.count({i,j})) {
                u |= i<<(3-st.size());
                v |= j<<(3-st.size());
                st.insert({u,v});
            }
        }

        auto z = mp[{u,v}];
        int ans = 0;
        rep(i,0,16) {
            rep(j,0,4) {
                if ((x>>i&1)==(u>>j&1) && (y>>i&1)==(v>>j&1)) {
                    ans |= (z>>j&1)<<i;
                }
            }
        }
        cout << ans << "\n";
    }
}
accuracy: 1
time_ms: 130
memory_kb: 22480
final_rank: 3

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll = long long;
#define rep(i, s, t) for (int i = (int)(s); i < (int)(t); ++i)

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);
    cout << fixed << setprecision(15);

    int N, M;
    cin >> N >> M;
    vector<string> o(N);
    rep(i,1,N) cin >> o[i];
    vector<vector<int>> G(N);
    rep(i,0,N-1) {
        int u, v;
        cin >> u >> v;
        G[u].push_back(v);
        G[v].push_back(u);
    }
    vector<int> xx = {0, 0, 1, 1};
    vector<int> yy = {0, 1, 0, 1};
    vector<int> perm = {0, 1, 2, 3};
    map<pair<int, int>, int> mp;

    auto dfs = [&](auto& dfs, int v, int p, int d, int x, int y, int val) -> int {
        if (v == 0) val = 0;
        else {
            int z;
            if (o[v][4] == 'X') z = x;
            else z = y;
            if (o[v][3] == '&') val &= z;
            else if (o[v][3] == '|') val |= z;
            else val ^= z;
        }
        int ma = -1, mi = 1e9;
        for (int c : G[v]) {
            if (c == p) continue;
            auto a = dfs(dfs, c, v, d + 1, x, y, val);
            ma = max(ma, a);
            mi = min(mi, a);
        }
        if (ma == -1) return val;
        return d & 1 ? mi : ma;
    };

    do {
        int x = 0, y = 0;
        rep(i,0,4) x |= xx[perm[i]]<<i, y |= yy[perm[i]]<<i;
        mp[{x,y}] = dfs(dfs, 0, -1, 0, x, y, 0);
    } while (next_permutation(perm.begin(), perm.end()));

    while (M--) {
        int x, y;
        cin >> x >> y;
        set<pair<int, int>> st;
        int u = 0, v = 0;
        rep(i,0,16) {
            auto a = x>>i&1;
            auto b = y>>i&1;
            if (st.count({a,b})) continue;
            u |= a<<st.size();
            v |= b<<st.size();
            st.insert({a,b});
        }
        rep(i,0,2) rep(j,0,2) {
            if (!st.count({i,j})) {
                u |= i<<st.size();
                v |= j<<st.size();
                st.insert({u,v});
            }
        }

        auto z = mp[{u,v}];
        int ans = 0;
        rep(i,0,16) {
            rep(j,0,4) {
                if ((x>>i&1)==(u>>j&1) && (y>>i&1)==(v>>j&1)) {
                    ans |= (z>>j&1)<<i;
                }
            }
        }
        cout << ans << "\n";
    }
}
accuracy: 0.0196078431372549
time_ms: 100
memory_kb: 11732
final_rank: 16

code_snippet: #include <bits/stdc++.h>
using namespace std;

using ll = long long;
using PII = pair<ll, ll>;

#define FOR(i, a, n) for (ll i = (ll)a; i < (ll)n; ++i)
#define REP(i, n) FOR(i, 0, n)
#define ALL(x) x.begin(), x.end()
#define POPCOUNT(x) __builtin_popcount(x)
template <typename T> void chmin(T &a, const T &b) { a = min(a, b); }
template <typename T> void chmax(T &a, const T &b) { a = max(a, b); }

const ll INF = 1LL << 60;

struct FastIO {
    FastIO() {
        cin.tie(0);
        ios::sync_with_stdio(0);
    }
} fastiofastio;

const ll MOD = 1e9 + 7;

// BEGIN CUT
ll modpow(ll x, ll y, ll m) {
    ll a = 1, p = x;
    while (y > 0) {
        if (y % 2 == 0) {
            p = (p * p) % m;
            y /= 2;
        } else {
            a = (a * p) % m;
            y--;
        }
    }
    return a;
}
// END CUT

ll gcd(ll a, ll b) { return b ? gcd(b, a % b) : a; }
ll lcm(ll a, ll b) { return a / gcd(a, b) * b; }

int op[100000];
// 0: None
// 1: T=T&X
// 2: T=T&Y
// 3: T=T|X
// 4: T=T|Y
// 5: T=T^X
// 6: T=T^Y
int memo[8][8];
vector<int> G[100000];

int solve(int v, int par, int now, int X, int Y, int d) {
    int mi = 1 << 30, ma = -(1 << 30);
    int cnt = 0;
    for (int to : G[v]) {
        if (to == par)
            continue;
        int nxt = now;
        if (op[to] == 1)
            nxt &= X;
        else if (op[to] == 2)
            nxt &= Y;
        else if (op[to] == 3)
            nxt |= X;
        else if (op[to] == 4)
            nxt |= Y;
        else if (op[to] == 5)
            nxt ^= X;
        else
            nxt ^= Y;
        int ret = solve(to, v, nxt, X, Y, d + 1);
        if (d % 2 == 0)
            ma = max(ma, ret);
        else
            mi = min(mi, ret);
        cnt++;
    }
    if (cnt == 0)
        return now;
    if (d % 2 == 0)
        return ma;
    return mi;
}

int main() {
    int N, M;
    cin >> N >> M;
    for (int i = 1; i < N; i++) {
        string s;
        cin >> s;
        if (s == "T=T&X")
            op[i] = 1;
        else if (s == "T=T&Y")
            op[i] = 2;
        else if (s == "T=T|X")
            op[i] = 3;
        else if (s == "T=T|Y")
            op[i] = 4;
        else if (s == "T=T^X")
            op[i] = 5;
        else
            op[i] = 6;
    }
    for (int i = 0; i < N - 1; i++) {
        int u, v;
        cin >> u >> v;
        G[u].push_back(v);
        G[v].push_back(u);
    }
    for (int i = 0; i < 8; i++) {
        for (int j = 0; j < 8; j++) {
            memo[i][j] = solve(0, -1, 0, i, j, 0);
        }
    }
    for (int i = 0; i < M; i++) {
        int X, Y;
        cin >> X >> Y;
        int sum[2][2] = {};
        bool used[2][2] = {};
        int x = 0, y = 0;
        for (int j = 15; j >= 0; j--) {
            int a = (X >> j) & 1;
            int b = (Y >> j) & 1;
            if (a == 0 && b == 0)
                continue;
            if (!used[a][b]) {
                used[a][b] = 1;
                x <<= 1;
                y <<= 1;
                x |= a;
                y |= b;
            }
            sum[a][b] += (1 << j);
        }
        int ret = 0;
        for (int j = 0; j < 3; j++) {
            int a = (x >> j) & 1;
            int b = (y >> j) & 1;
            if ((memo[x][y] >> j) & 1) {
                ret += sum[a][b];
            }
        }
        cout << ret << '\n';
    }
}
accuracy: 1
time_ms: 200
memory_kb: 18620
final_rank: 5

code_snippet: #pragma GCC ta g("avx2")
#pragma GCC optimize("Ofast")
#pragma GCC optimize("unroll-loops")
#include <bits/stdc++.h>
using namespace std;
#define DEBUG
#ifdef DEBUG
template <class T, class U>
ostream &operator<<(ostream &os, const pair<T, U> &p) {
    os << '(' << p.first << ',' << p.second << ')';
    return os;
}
template <class T> ostream &operator<<(ostream &os, const vector<T> &v) {
    os << '{';
    for(int i = 0; i < (int)v.size(); i++) {
        if(i) { os << ','; }
        os << v[i];
    }
    os << '}';
    return os;
}
void debugg() { cerr << endl; }
template <class T, class... Args>
void debugg(const T &x, const Args &... args) {
    cerr << " " << x;
    debugg(args...);
}
#define debug(...)                                                             \
    cerr << __LINE__ << " [" << #__VA_ARGS__ << "]: ", debugg(__VA_ARGS__)
#define dump(x) cerr << __LINE__ << " " << #x << " = " << (x) << endl
#else
#define debug(...) (void(0))
#define dump(x) (void(0))
#endif
using namespace std;
typedef long long ll;
typedef vector<ll> vl;
typedef vector<vl> vvl;
typedef vector<char> vc;
typedef vector<string> vs;
typedef vector<bool> vb;
typedef vector<double> vd;
typedef pair<ll,ll> P;
typedef pair<int,int> pii;
typedef vector<P> vpl;
typedef tuple<ll,ll,ll> tapu;
#define rep(i,n) for(int i=0; i<(n); i++)
#define REP(i,a,b) for(int i=(a); i<(b); i++)
#define all(x) (x).begin(), (x).end()
#define rall(x) (x).rbegin(), (x).rend()
template<typename T1,typename T2> inline bool chmin(T1 &a,T2 b){
	if(a>b){
		a = b; return true;
	}
	else return false;
}
template<typename T1,typename T2> inline bool chmax(T1 &a,T2 b){
	if(a<b){
		a = b; return true;
	}
	else return false;
}
template<typename T> inline void print(T &a){
    int sz = a.size();
    for(auto itr = a.begin(); itr != a.end(); itr++){
		cout << *itr;
        sz--;
        if(sz) cout << " ";
	}
    cout << "\n";
}
template<typename T1,typename T2> inline void print2(T1 a, T2 b){
	cout << a << " " << b << "\n";
}
template<typename T1,typename T2,typename T3> inline void print3(T1 a, T2 b, T3 c){
	cout << a << " " << b << " " << c << "\n";
}
void mark() {cout << "#" << "\n";}
ll pcount(ll x) {return __builtin_popcountll(x);}
//#include <atcoder/maxflow>
//using namespace atcoder;
const int inf = (1<<30)-1;
const ll linf = 1LL<<61;
const int MAX = 510000;
int dy[8] = {0,1,0,-1,1,-1,-1,1};
int dx[8] = {-1,0,1,0,1,-1,1,-1};
const double pi = acos(-1);
const double eps = 1e-9;
const int mod = 1e9 + 7;
//const int mod = 998244353;

int main(){
    int n,m; cin >> n >> m;
    vs s(n); rep(i,n-1) cin >> s[i+1];
    vvl G(n);
    rep(i,n-1){
        int u,v; cin >> u >> v;
        G[u].push_back(v);
        G[v].push_back(u);
    }
    vl nxt(4); rep(i,4) nxt[i] = i;
    int now = 0;
    vvl memo(24);
    do{
        memo[now] = nxt;
        now++;
    }while(next_permutation(all(nxt)));
    auto get_score = [&](int bit, int id){
        int res = 0;
        rep(i,4){
            if(bit>>memo[id][i]&1) res += 1<<i;
        }
        return res;
    };
    vvl b(n,vl(24,0));
    auto dfs = [&](auto &&dfs, int u, int p, int d, vl vec) -> void {
        bool leaf = true;
        if(u > 0){
            int t = s[u][4]=='X'?1:2;
            if(s[u][3] == '|'){
                vec[3] = 1; vec[t] = 1;
            }
            if(s[u][3] == '&'){
                vec[0] = 0; vec[3-t] = 0;
            }
            if(s[u][3] == '^'){
                vec[3] = 1-vec[3]; vec[t] = 1-vec[t];
            }
        }
        vector<int> score(24,(d&1)?15:0);
        for(auto v : G[u]){
            if(v == p) continue;
            leaf = false;
            dfs(dfs,v,u,1-d,vec);
            if(d == 0){
                rep(i,24){
                    if(chmax(score[i],get_score(b[v][i],i))){
                        b[u][i] = b[v][i];
                    }
                }
            }else{
                rep(i,24){
                    if(chmin(score[i],get_score(b[v][i],i))){
                        b[u][i] = b[v][i];
                    }
                }
            }
        }
        if(leaf){
            int bit = 0;
            rep(i,4) if(vec[i]) bit += 1<<i;
            rep(i,24) b[u][i] = bit;
        }
    };
    vl ini(4,0);
    dfs(dfs,0,-1,0,ini);
    while(m--){
        int x,y; cin >> x >> y;
        vl a(4,0);
        rep(i,16){
            a[(y>>i&1)*2+(x>>i&1)] += 1<<i;
        }
        int id = 0;
        rep(i,24){
            bool f = true;
            rep(j,3){
                if(a[memo[i][j]] > a[memo[i][j+1]]) f = false;
            }
            if(f){
                id = i;
                break;
            }
        }
        int ans = 0;
        rep(i,4) if(b[0][id]>>i&1) ans += a[i];
        cout << ans << "\n";
    }
}
accuracy: 1
time_ms: 180
memory_kb: 65580
final_rank: 10

code_snippet: #pragma GCC ta g("avx2")
#pragma GCC optimize("Ofast")
#pragma GCC optimize("unroll-loops")
#include <bits/stdc++.h>
using namespace std;
#define DEBUG
#ifdef DEBUG
template <class T, class U>
ostream &operator<<(ostream &os, const pair<T, U> &p) {
    os << '(' << p.first << ',' << p.second << ')';
    return os;
}
template <class T> ostream &operator<<(ostream &os, const vector<T> &v) {
    os << '{';
    for(int i = 0; i < (int)v.size(); i++) {
        if(i) { os << ','; }
        os << v[i];
    }
    os << '}';
    return os;
}
void debugg() { cerr << endl; }
template <class T, class... Args>
void debugg(const T &x, const Args &... args) {
    cerr << " " << x;
    debugg(args...);
}
#define debug(...)                                                             \
    cerr << __LINE__ << " [" << #__VA_ARGS__ << "]: ", debugg(__VA_ARGS__)
#define dump(x) cerr << __LINE__ << " " << #x << " = " << (x) << endl
#else
#define debug(...) (void(0))
#define dump(x) (void(0))
#endif
using namespace std;
typedef long long ll;
typedef vector<ll> vl;
typedef vector<vl> vvl;
typedef vector<char> vc;
typedef vector<string> vs;
typedef vector<bool> vb;
typedef vector<double> vd;
typedef pair<ll,ll> P;
typedef pair<int,int> pii;
typedef vector<P> vpl;
typedef tuple<ll,ll,ll> tapu;
#define rep(i,n) for(int i=0; i<(n); i++)
#define REP(i,a,b) for(int i=(a); i<(b); i++)
#define all(x) (x).begin(), (x).end()
#define rall(x) (x).rbegin(), (x).rend()
template<typename T1,typename T2> inline bool chmin(T1 &a,T2 b){
	if(a>b){
		a = b; return true;
	}
	else return false;
}
template<typename T1,typename T2> inline bool chmax(T1 &a,T2 b){
	if(a<b){
		a = b; return true;
	}
	else return false;
}
template<typename T> inline void print(T &a){
    int sz = a.size();
    for(auto itr = a.begin(); itr != a.end(); itr++){
		cout << *itr;
        sz--;
        if(sz) cout << " ";
	}
    cout << "\n";
}
template<typename T1,typename T2> inline void print2(T1 a, T2 b){
	cout << a << " " << b << "\n";
}
template<typename T1,typename T2,typename T3> inline void print3(T1 a, T2 b, T3 c){
	cout << a << " " << b << " " << c << "\n";
}
void mark() {cout << "#" << "\n";}
ll pcount(ll x) {return __builtin_popcountll(x);}
//#include <atcoder/maxflow>
//using namespace atcoder;
const int inf = (1<<30)-1;
const ll linf = 1LL<<61;
const int MAX = 510000;
int dy[8] = {0,1,0,-1,1,-1,-1,1};
int dx[8] = {-1,0,1,0,1,-1,1,-1};
const double pi = acos(-1);
const double eps = 1e-9;
const int mod = 1e9 + 7;
//const int mod = 998244353;

int main(){
    int n,m; cin >> n >> m;
    vs s(n); rep(i,n-1) cin >> s[i+1];
    vvl G(n);
    rep(i,n-1){
        int u,v; cin >> u >> v;
        G[u].push_back(v);
        G[v].push_back(u);
    }
    vvl b(n,vl(16,0));
    auto dfs = [&](auto &&dfs, int u, int p, int d, vl vec) -> void {
        if(d & 1) rep(j,16) b[u][j] = 1;
        bool leaf = true;
        if(u > 0){
            int t = s[u][4]=='X'?1:2;
            if(s[u][3] == '|'){
                vec[3] = 1; vec[t] = 1;
            }
            if(s[u][3] == '&'){
                vec[0] = 0; vec[3-t] = 0;
            }
            if(s[u][3] == '^'){
                vec[3] = 1-vec[3]; vec[t] = 1-vec[t];
            }
        }
        for(auto v : G[u]){
            if(v == p) continue;
            leaf = false;
            dfs(dfs,v,u,1-d,vec);
            if(d == 0){
                rep(i,16) b[u][i] |= b[v][i];
            }else{
                rep(i,16) b[u][i] &= b[v][i];
            }
        }
        if(leaf){
            rep(bit,1<<4){
                b[u][bit] = 1;
                rep(i,4){
                    if(bit>>i&1) b[u][bit] &= vec[i];
                }
            }
        }
    };
    vl ini(4,0);
    dfs(dfs,0,-1,0,ini);
    while(m--){
        int x,y; cin >> x >> y;
        vl a(4,0);
        rep(i,16){
            a[(y>>i&1)*2+(x>>i&1)] += 1<<i;
        }
        int ans = 0;
        rep(bit,1<<4){
            if(!b[0][bit]) continue;
            int s = 0;
            rep(i,4) if(bit>>i&1) s += a[i];
            chmax(ans,s);
        }
        cout << ans << "\n";
    }
}
accuracy: 0.0196078431372549
time_ms: 160
memory_kb: 28732
final_rank: 19

code_snippet: #include "iostream"
#include "climits"
#include "list"
#include "queue"
#include "stack"
#include "set"
#include "functional"
#include "algorithm"
#include "string"
#include "map"
#include "unordered_map"
#include "unordered_set"
#include "iomanip"
#include "cmath"
#include "random"
#include "bitset"
#include "cstdio"
#include "numeric"
#include "cassert"
#include "ctime"

using namespace std;

//constexpr long long MOD = 1000000007;
constexpr long long MOD = 998244353;
constexpr double EPS = 1e-8;

//int N, M, K, T, H, W, L, R;
long long int N, M, K, T, H, W, L, R;

int func(vector<vector<int>>& edge, vector<int>& s, vector<int>& p, int idx, int depth = 0, int node = 0, int parent = -1) {
	int ret = 0;
	if (depth)ret = 7;
	else ret = 0;
	bool leaf = true;
	for (auto i : edge[node]) {
		if (i == parent)continue;
		leaf = false;
		int nx = idx;
		if (s[i] == 1) {
			nx &= 3;
		}
		else if (s[i] == 2) {
			nx &= 5;
		}
		else if (s[i] == 3) {
			nx |= 3;
		}
		else if (s[i] == 4) {
			nx |= 5;
		}
		else if (s[i] == 5) {
			nx ^= 3;
		}
		else if (s[i] == 6) {
			nx ^= 5;
		}
		auto box = func(edge, s, p, nx, depth ^ 1, i, node);
		if (depth & 1) {
			if (p[ret] > p[box]) {
				ret = box;
			}
		}
		else {
			if (p[ret] < p[box]) {
				ret = box;
			}
		}
	}
	if (leaf) {
		ret = idx;
	}
	return ret;
}

int main() {
	ios::sync_with_stdio(false);
	cin.tie(0);

	// 0 a&b (a&b)^a a (a|b)^a  b a^b  a|b
	vector<int>p(8);
	map<vector<int>, int>mp;
	for (int i = 0; i < p.size(); i++) {
		p[i] = i;
	}
	cin >> N >> K;
	vector<int>s(N, 0);
	for (int i = 1; i < N; i++) {
		string t;
		cin >> t;
		if (t == "T=T&X") {
			s[i] = 1;
		}
		else if (t == "T=T&Y") {
			s[i] = 2;
		}
		else if (t == "T=T|X") {
			s[i] = 3;
		}
		else if (t == "T=T|Y") {
			s[i] = 4;
		}
		else if (t == "T=T^X") {
			s[i] = 5;
		}
		else if (t == "T=T^Y") {
			s[i] = 6;
		}
	}
	vector<vector<int>>edge(N);
	for (int i = 1; i < N; i++) {
		cin >> L >> R;
		edge[L].push_back(R);
		edge[R].push_back(L);
	}
	do {
		if (p.front())break;
		if (p.back() != 7)continue;
		if (p[1] == 6)continue;
		if (p[2] == 6)continue;
		if (p[4] == 6)continue;
		mp[p] = func(edge, s, p, 0);
	} while (next_permutation(p.begin(), p.end()));
	while (K--) {
		cin >> L >> R;
		vector<pair<int, int>>q;
		q.push_back({ 0,0 });
		q.push_back({ L & R,1 });
		q.push_back({ (L & R) ^ L , 2 });
		q.push_back({ L, 3 });
		q.push_back({ (L | R) ^ L,4 });
		q.push_back({ R,5 });
		q.push_back({ L ^ R,6 });
		q.push_back({ L | R,7 });
		sort(q.begin(), q.end());
		vector<int>r(8);
		for (int i = 0; i < 8; i++) {
			r[q[i].second] = i;
		}
		auto box = mp[r];
		if (box == 0) {
			cout << 0 << "\n";
		}
		else if (box == 1) {
			cout << (L & R) << "\n";
		}
		else if (box == 2) {
			cout << ((L & R) ^ L) << "\n";
		}
		else if (box == 3) {
			cout << L << "\n";
		}
		else if (box == 4) {
			cout << ((L | R) ^ L) << "\n";
		}
		else if (box == 5) {
			cout << R << "\n";
		}
		else if (box == 6) {
			cout << (L ^ R) << "\n";
		}
		else if (box == 7) {
			cout << (L | R) << "\n";
		}
	}
}
accuracy: 1
time_ms: 1020
memory_kb: 19984
final_rank: 11

code_snippet: #include "iostream"
#include "climits"
#include "list"
#include "queue"
#include "stack"
#include "set"
#include "functional"
#include "algorithm"
#include "string"
#include "map"
#include "unordered_map"
#include "unordered_set"
#include "iomanip"
#include "cmath"
#include "random"
#include "bitset"
#include "cstdio"
#include "numeric"
#include "cassert"
#include "ctime"

using namespace std;

//constexpr long long MOD = 1000000007;
constexpr long long MOD = 998244353;
constexpr double EPS = 1e-8;

//int N, M, K, T, H, W, L, R;
long long int N, M, K, T, H, W, L, R;

int func(vector<vector<int>>& edge, vector<int>& s, vector<int>& p, int idx, int depth = 0, int node = 0, int parent = -1) {
	int ret = 0;
	if (depth & 1)ret = 7;
	else ret = 0;
	bool leaf = true;
	for (auto i : edge[node]) {
		if (i == parent)continue;
		leaf = false;
		int nx = idx;
		if (s[i] == 1) {
			nx &= 3;
		}
		if (s[i] == 2) {
			nx &= 5;
		}
		if (s[i] == 3) {
			nx |= 3;
		}
		if (s[i] == 4) {
			nx |= 5;
		}
		if (s[i] == 5) {
			nx ^= 3;
		}
		if (s[i] == 6) {
			nx ^= 5;
		}
		auto box = func(edge, s, p, nx, depth+1,i, node);
		if (depth & 1) {
			if (p[ret] > p[box]) {
				ret = box;
			}
		}
		else {
			if (p[ret] < p[box]) {
				ret = box;
			}
		}
	}
	if (leaf) {
		ret = idx;
	}
//	cout << ret << endl;
	return ret;
}

int main() {
	ios::sync_with_stdio(false);
	cin.tie(0);

	// 0 a&b (a&b)^a a (a|b)^a  b a^b  a|b
	vector<int>p(8);
	map<vector<int>, int>mp;
	for (int i = 0; i < p.size(); i++) {
		p[i] = i;
	}
	cin >> N >> K;
	vector<int>s(N, 0);
	for (int i = 1; i < N; i++) {
		string t;
		cin >> t;
		if (t == "T=T&X") {
			s[i] = 1;
		}
		if (t == "T=T&Y") {
			s[i] = 2;
		}
		if (t == "T=T|X") {
			s[i] = 3;
		}
		if (t == "T=T|Y") {
			s[i] = 4;
		}
		if (t == "T=T^X") {
			s[i] = 5;
		}
		if (t == "T=T^Y") {
			s[i] = 6;
		}
	}
	vector<vector<int>>edge(N);
	for (int i = 1; i < N; i++) {
		cin >> L >> R;
		edge[L].push_back(R);
		edge[R].push_back(L);
	}
	do {
		if (p.front())break;
		if (p.back() != 7)continue;
		mp[p] = func(edge, s, p, 0);
	//	for (auto i : p)cout << i << " ";
	//	cout << endl;
	//	cout << mp[p] << endl;
	} while (next_permutation(p.begin(), p.end()));
	while (K--) {
		cin >> L >> R;
		vector<pair<int, int>>q;
		q.push_back({ 0,0 });
		q.push_back({ L & R,1 });
		q.push_back({ (L & R) ^ L , 2 });
		q.push_back({ L, 3 });
		q.push_back({ (L | R) ^ L,4 });
		q.push_back({ R,5 });
		q.push_back({ L ^ R,6 });
		q.push_back({ L | R,7 });
		sort(q.begin(), q.end());
		vector<int>r(8);
		for (int i = 0; i < 8; i++) {
			r[q[i].second] = i;
		}
		auto box = mp[r];
		if (box == 0) {
			cout << 0 << "\n";
		}
		else if (box == 1) {
			cout << (L & R) << "\n";
		}
		else if (box == 2) {
			cout << ((L & R) ^ L) << "\n";
		}
		else if (box == 3) {
			cout << L << "\n";
		}
		else if (box == 4) {
			cout << ((L | R) ^ L) << "\n";
		}
		else if (box == 5) {
			cout << R << "\n";
		}
		else if (box == 6) {
			cout << (L ^ R) << "\n";
		}
		else if (box == 7) {
			cout << (L | R) << "\n";
		}
	}
}
accuracy: 1
time_ms: 1970
memory_kb: 19976
final_rank: 13

code_snippet: /*	author:  Kite_kuma
	created: 2021.08.16 12:53:59 */

// #ifdef LOCAL
// #define _GLIBCXX_DEBUG
// #endif
#include <bits/stdc++.h>
using namespace std;

#pragma region macros

#define foa(s, v) for(auto &s : v)
#define all(v) (v).begin(), (v).end()
#define rall(v) (v).rbegin(), (v).rend()
#define popcnt(n) __builtin_popcountll((long long)n)

#define REPname(a, b, c, d, e, ...) e
#define rep(...) REPname(__VA_ARGS__, REP3, REP2, REP1, REP0)(__VA_ARGS__)
#define REP0(x) for(int Counter_in_rep_macro = 0; Counter_in_rep_macro < (x); ++Counter_in_rep_macro)
#define REP1(i, x) for(int i = 0; i < (x); ++i)
#define REP2(i, l, r) for(int i = (l); i < (r); ++i)
#define REP3(i, l, r, c) for(int i = (l); i < (r); i += (c))

#define DREPname(a, b, c, d, e, ...) e
#define drep(...) DREPname(__VA_ARGS__, DREP3, DREP2, DREP1)(__VA_ARGS__)
#define DREP1(i, x) for(int i = (x)-1; i >= 0; --i)
#define DREP2(i, l, r) for(int i = (r)-1; i >= (l); --i)
#define DREP3(i, l, r, c) for(int i = (r)-1; i >= (l); i -= (c))

#pragma endregion

#pragma region aliases

using ll = long long;
using ld = long double;
using ull = unsigned long long;
using vi = std::vector<int>;
using vvi = std::vector<std::vector<int>>;
using vvvi = std::vector<std::vector<std::vector<int>>>;
using vll = std::vector<ll>;
using vvll = std::vector<vll>;
using vvvll = std::vector<vvll>;
using pii = std::pair<int, int>;
using pll = std::pair<long long, long long>;
template <class T = ll>
using V = std::vector<T>;
template <class T = ll>
using VV = V<V<T>>;
template <class T = ll>
using VVV = V<V<V<T>>>;
template <class T = ll>
using pqup = std::priority_queue<T, std::vector<T>, std::greater<T>>;
template <class T = ll>
using pqdn = std::priority_queue<T>;

#pragma endregion

#pragma region constants

const int inf = 1e9;
const long long INF = 1e18;
const long double pi = acos(-1);
const char dl = '\n';
const char sp = ' ';
int dx[8] = {1, 0, -1, 0, 1, -1, -1, 1};
int dy[8] = {0, 1, 0, -1, 1, 1, -1, -1};

const int mod_1000000007 = 1000000007;
const int mod_998244353 = 998244353;

#pragma endregion

#pragma region basic_operation

template <class T0, class T1, class T2>
inline bool in_range(T0 x, T1 lef, T2 rig) {
	return ((lef <= x) && (x < rig));
}

template <class T>
inline bool chmin(T &a, T b) {
	if(a > b) {
		a = b;
		return true;
	}
	return false;
}
template <class T>
inline bool chmax(T &a, T b) {
	if(a < b) {
		a = b;
		return true;
	}
	return false;
}

void Yes(bool f = 1) { std::cout << (f ? "Yes" : "No") << '\n'; }
void No() { std::cout << "No\n"; }
void YES(bool f = 1) { std::cout << (f ? "YES" : "NO") << '\n'; }
void NO() { std::cout << "NO\n"; }

template <class T>
void drop(T answer) {
	std::cout << answer << '\n';
	exit(0);
}

void err(bool flag = true) {
	if(!flag) return;
	std::cout << -1 << '\n';
	exit(0);
}

template <class T>
void vout(std::vector<T> const &v, bool vertically = 0) {
	if(vertically) {
		for(auto const &a : v) {
			std::cout << a << '\n';
		}
		return;
	}
	for(auto it = v.begin(); it != v.end(); it++) {
		std::cout << (*it);
		if(it != v.end() - 1) {
			std::cout << ' ';
		}
	}
	std::cout << '\n';
	return;
}

inline void print() { std::cout << '\n'; }
template <class T>
inline void print(T x) {
	std::cout << x << '\n';
	return;
}
template <typename Head, typename... Tail>
void print(Head H, Tail... T) {
	std::cout << H << " ";
	print(T...);
}

template <class T>
void add(std::vector<T> &v, T val) {
	for(auto &a : v) a += val;
	return;
}

template <class T>
T dup(T a, T b) {
	assert(b != 0);
	return (a + b - 1) / b;
}

template <class T>
T greatest_lower_multiple(T x, T d) {
	if(d == 0) return 0;
	if(d < 0) d *= -1;
	T y = x % d;
	if(y < 0) y += d;
	return x - y;
}

template <class T>
T least_upper_multiple(T x, T d) {
	return -greatest_lower_multiple(-x, d);
}

long long POW(long long a, long long n) {
	long long res = 1;
	while(n > 0) {
		if(n & 1) res = res * a;
		a = a * a;
		n >>= 1;
	}
	return res;
}

long long modpow(long long a, long long n, long long mod) {  // a^n mod
	assert(n >= 0 && mod);
	if(mod == 1) return 0LL;
	long long res = 1;
	a %= mod;
	while(n > 0) {
		if(n & 1) res = res * a % mod;
		a = a * a % mod;
		n >>= 1;
	}
	return res < 0 ? res + mod : res;
}

// return x which satisfies a * x % mod == gcd(a, mod)
// not (mod | a)
long long modinv(long long a, long long mod) {
	long long b = mod, u = 1, v = 0;
	while(b) {
		long long t = a / b;
		a -= t * b;
		std::swap(a, b);
		u -= t * v;
		std::swap(u, v);
	}
	u %= mod;
	if(u < 0) u += mod;
	return u;
}

template <class T>
int lb(const std::vector<T> &a, const T x) {
	return std::distance(a.begin(), std::lower_bound(a.begin(), a.end(), x));
}
template <class T>
int ub(const std::vector<T> &a, const T x) {
	return std::distance(a.begin(), std::upper_bound(a.begin(), a.end(), x));
}
template <class T>
void unq_sort(std::vector<T> &a) {
	std::sort(a.begin(), a.end());
	a.erase(std::unique(a.begin(), a.end()), a.end());
}
template <class T>
std::vector<int> press(std::vector<T> &a) {
	auto vec = a;
	unq_sort(vec);
	std::vector<int> ret;
	for(auto &v : a) ret.push_back(lb(vec, v));
	return ret;
}

#pragma endregion

#pragma region input
#define VEC(type, name, size) \
	vector<type> name(size);  \
	scanner::INPUT(name)
#define VVEC(type, name, h, w)                     \
	vector<vector<type>> name(h, vector<type>(w)); \
	scanner::INPUT(name)
#define INT(...)     \
	int __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define LL(...)            \
	long long __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define STR(...)        \
	string __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define CHR(...)      \
	char __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define DBL(...)        \
	double __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define LD(...)              \
	long double __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define TPL3(type0, type1, type2, name)   \
	std::tuple<type0, type1, type2> name; \
	scanner::INPUT(name);
#define TPL4(type0, type1, type2, type3, name)   \
	std::tuple<type0, type1, type2, type3> name; \
	scanner::INPUT(name);

namespace scanner {
template <class T>
void scan(T &a) {
	std::cin >> a;
}

template <class T, class L>
void scan(std::pair<T, L> &p) {
	scan(p.first);
	scan(p.second);
}

template <class T0, class T1, class T2>
void scan(std::tuple<T0, T1, T2> &p) {
	T0 t0;
	T1 t1;
	T2 t2;
	scan(t0);
	scan(t1);
	scan(t2);
	p = std::make_tuple(t0, t1, t2);
}

template <class T0, class T1, class T2, class T3>
void scan(std::tuple<T0, T1, T2, T3> &p) {
	T0 t0;
	T1 t1;
	T2 t2;
	T3 t3;
	scan(t0);
	scan(t1);
	scan(t2);
	scan(t3);
	p = std::make_tuple(t0, t1, t2, t3);
}

template <class T>
void scan(std::vector<T> &a) {
	for(auto &i : a) scan(i);
}

void INPUT() {}
template <class Head, class... Tail>
void INPUT(Head &head, Tail &... tail) {
	scan(head);
	INPUT(tail...);
}
}  // namespace scanner

template <typename T1, typename T2>
std::istream &operator>>(std::istream &is, std::pair<T1, T2> &p) {
	is >> p.first >> p.second;
	return is;
}
#pragma endregion

#pragma region debug

#pragma region output
template <typename T1, typename T2>
std::ostream &std::operator<<(std::ostream &os, const std::pair<T1, T2> &p) {
	os << p.first << " " << p.second;
	return os;
}
template <class T>
std::ostream &std::operator<<(std::ostream &os, const std::vector<T> &v) {
	for(int i = 0; i < (int)v.size(); i++) {
		if(i) os << " ";
		os << v[i];
	}
	return os;
}
#pragma endregion

#pragma region view

namespace viewer {
void view(const long long e) {
	if(e == INF)
		std::cerr << "INF";
	else if(e == -INF)
		std::cerr << "-INF";
	else
		std::cerr << e;
}

void view(const int e) {
	if(e == inf)
		std::cerr << "inf";
	else if(e == -inf)
		std::cerr << "-inf";
	else
		std::cerr << e;
}

template <typename T>
void view(const T e) {
	std::cerr << e;
}

template <typename T, typename U>
void view(const std::pair<T, U> &p) {
	std::cerr << "(";
	view(p.first);
	std::cerr << ", ";
	view(p.second);
	std::cerr << ")";
}

template <class T0, class T1, class T2>
void view(const std::tuple<T0, T1, T2> &p) {
	std::cerr << "(";
	view(std::get<0>(p));
	std::cerr << ", ";
	view(std::get<1>(p));
	std::cerr << ", ";
	view(std::get<2>(p));
	std::cerr << ")";
}

template <class T0, class T1, class T2, class T3>
void view(const std::tuple<T0, T1, T2, T3> &p) {
	std::cerr << "(";
	view(std::get<0>(p));
	std::cerr << ", ";
	view(std::get<1>(p));
	std::cerr << ", ";
	view(std::get<2>(p));
	std::cerr << ", ";
	view(std::get<3>(p));
	std::cerr << ")";
}

template <typename T>
void view(const std::set<T> &s) {
	if(s.empty()) {
		std::cerr << "{ }";
		return;
	}
	std::cerr << "{ ";
	for(auto &t : s) {
		view(t);
		std::cerr << ", ";
	}
	std::cerr << "\b\b }";
}

template <typename T>
void view(const std::unordered_set<T> &s) {
	if(s.empty()) {
		std::cerr << "{ }";
		return;
	}
	std::cerr << "{ ";
	for(auto &t : s) {
		view(t);
		std::cerr << ", ";
	}
	std::cerr << "\b\b }";
}

template <typename T>
void view(const std::vector<T> &v) {
	if(v.empty()) {
		std::cerr << "{ }";
		return;
	}
	std::cerr << "{ ";
	for(const auto &e : v) {
		view(e);
		std::cerr << ", ";
	}
	std::cerr << "\b\b }";
}

template <typename T>
void view(const std::vector<std::vector<T>> &vv) {
	std::cerr << "{\n";
	for(const auto &v : vv) {
		std::cerr << "\t";
		view(v);
		std::cerr << '\n';
	}
	std::cerr << "}";
}

template <typename T, typename U>
void view(const std::vector<std::pair<T, U>> &v) {
	std::cerr << "{\n";
	for(const auto &c : v) {
		std::cerr << "\t(";
		view(c.first);
		std::cerr << ", ";
		view(c.second);
		std::cerr << ")\n";
	}
	std::cerr << "}";
}

template <class T0, class T1, class T2>
void view(const std::vector<std::tuple<T0, T1, T2>> &v) {
	if(v.empty()) {
		std::cerr << "{ }";
		return;
	}
	std::cerr << '{';
	for(const auto &t : v) {
		std::cerr << "\n\t";
		view(t);
		std::cerr << ",";
	}
	std::cerr << "\n}";
}

template <class T0, class T1, class T2, class T3>
void view(const std::vector<std::tuple<T0, T1, T2, T3>> &v) {
	if(v.empty()) {
		std::cerr << "{ }";
		return;
	}
	std::cerr << '{';
	for(const auto &t : v) {
		std::cerr << "\n\t";
		view(t);
		std::cerr << ",";
	}
	std::cerr << "\n}";
}

template <typename T, typename U>
void view(const std::map<T, U> &m) {
	std::cerr << "{\n";
	for(const auto &t : m) {
		std::cerr << "\t[";
		view(t.first);
		std::cerr << "] : ";
		view(t.second);
		std::cerr << '\n';
	}
	std::cerr << "}";
}

template <typename T, typename U>
void view(const std::unordered_map<T, U> &m) {
	std::cerr << "{\n";
	for(const auto &t : m) {
		std::cerr << "\t[";
		view(t.first);
		std::cerr << "] : ";
		view(t.second);
		std::cerr << '\n';
	}
	std::cerr << "}";
}
}  // namespace viewer

#pragma endregion

// when debugging : g++ foo.cpp -DLOCAL
#ifdef LOCAL
void debug_out() {}
template <typename Head, typename... Tail>
void debug_out(Head H, Tail... T) {
	viewer::view(H);
	std::cerr << ", ";
	debug_out(T...);
}
#define debug(...)                                                \
	do {                                                          \
		std::cerr << __LINE__ << " [" << #__VA_ARGS__ << "] : ["; \
		debug_out(__VA_ARGS__);                                   \
		std::cerr << "\b\b]\n";                                   \
	} while(0)
#define dump(x)                                      \
	do {                                             \
		std::cerr << __LINE__ << " " << #x << " : "; \
		viewer::view(x);                             \
		std::cerr << '\n';                           \
	} while(0)

#else
#define debug(...) (void(0))
#define dump(x) (void(0))
#endif

#pragma endregion

#pragma region graph

struct Edge {
	int to;
	long long cost;
	Edge() = default;
	Edge(int to_, long long cost_) : to(to_), cost(cost_) {}
	bool operator<(const Edge &a) const { return cost < a.cost; }
	bool operator>(const Edge &a) const { return cost > a.cost; }
	friend std::ostream &operator<<(std::ostream &s, Edge &a) {
		s << "to: " << a.to << ", cost: " << a.cost;
		return s;
	}
};

class Graph {
	std::vector<std::vector<Edge>> edges;

public:
	inline const std::vector<Edge> &operator[](int k) const { return edges[k]; }
	inline std::vector<Edge> &operator[](int k) { return edges[k]; }

	int size() const { return edges.size(); }
	void resize(const int n) { edges.resize(n); }

	Graph() = default;
	Graph(int n) : edges(n) {}
	Graph(int n, int e, bool weight = 0, bool directed = 0, int idx = 1) : edges(n) { input(e, weight, directed, idx); }
	const long long INF = 3e18;

	void input(int e = -1, bool weight = 0, bool directed = false, int idx = 1) {
		if(e == -1) e = size() - 1;
		while(e--) {
			int u, v;
			long long cost = 1;
			std::cin >> u >> v;
			if(weight) std::cin >> cost;
			u -= idx, v -= idx;
			edges[u].emplace_back(v, cost);
			if(!directed) edges[v].emplace_back(u, cost);
		}
	}

	void add_edge(int u, int v, long long cost = 1, bool directed = false, int idx = 0) {
		u -= idx, v -= idx;
		edges[u].emplace_back(v, cost);
		if(!directed) edges[v].emplace_back(u, cost);
	}

	// Ο(V+E)
	std::vector<long long> bfs(int s) {
		std::vector<long long> dist(size(), INF);
		std::queue<int> que;
		dist[s] = 0;
		que.push(s);
		while(!que.empty()) {
			int v = que.front();
			que.pop();
			for(auto &e : edges[v]) {
				if(dist[e.to] != INF) continue;
				dist[e.to] = dist[v] + e.cost;
				que.push(e.to);
			}
		}
		return dist;
	}

	// Ο(V+E)
	// constraint: cost of each edge is zero or one
	std::vector<long long> zero_one_bfs(int s) {
		std::vector<long long> dist(size(), INF);
		std::deque<int> deq;
		dist[s] = 0;
		deq.push_back(s);
		while(!deq.empty()) {
			int v = deq.front();
			deq.pop_front();
			for(auto &e : edges[v]) {
				assert(0LL <= e.cost and e.cost < 2LL);
				if(e.cost and dist[e.to] > dist[v] + 1) {
					dist[e.to] = dist[v] + 1;
					deq.push_back(e.to);
				} else if(!e.cost and dist[e.to] > dist[v]) {
					dist[e.to] = dist[v];
					deq.push_front(e.to);
				}
			}
		}
		return dist;
	}

	// Ο((E+V)logV)
	// cannot reach: INF
	std::vector<long long> dijkstra(int s) {  // verified
		std::vector<long long> dist(size(), INF);
		const auto compare = [](const std::pair<long long, int> &a, const std::pair<long long, int> &b) { return a.first > b.first; };
		std::priority_queue<std::pair<long long, int>, std::vector<std::pair<long long, int>>, decltype(compare)> que{compare};
		dist[s] = 0;
		que.emplace(0, s);
		while(!que.empty()) {
			std::pair<long long, int> p = que.top();
			que.pop();
			int v = p.second;
			if(dist[v] < p.first) continue;
			for(auto &e : edges[v]) {
				if(dist[e.to] > dist[v] + e.cost) {
					dist[e.to] = dist[v] + e.cost;
					que.emplace(dist[e.to], e.to);
				}
			}
		}
		return dist;
	}

	// Ο(VE)
	// cannot reach: INF
	// negative cycle: -INF
	std::vector<long long> bellman_ford(int s) {  // verified
		int n = size();
		std::vector<long long> res(n, INF);
		res[s] = 0;
		for(int loop = 0; loop < n - 1; loop++) {
			for(int v = 0; v < n; v++) {
				if(res[v] == INF) continue;
				for(auto &e : edges[v]) {
					res[e.to] = std::min(res[e.to], res[v] + e.cost);
				}
			}
		}
		std::queue<int> que;
		std::vector<int> chk(n);
		for(int v = 0; v < n; v++) {
			if(res[v] == INF) continue;
			for(auto &e : edges[v]) {
				if(res[e.to] > res[v] + e.cost and !chk[e.to]) {
					que.push(e.to);
					chk[e.to] = 1;
				}
			}
		}
		while(!que.empty()) {
			int now = que.front();
			que.pop();
			for(auto &e : edges[now]) {
				if(!chk[e.to]) {
					chk[e.to] = 1;
					que.push(e.to);
				}
			}
		}
		for(int i = 0; i < n; i++)
			if(chk[i]) res[i] = -INF;
		return res;
	}

	// Ο(V^3)
	std::vector<std::vector<long long>> warshall_floyd() {  // verified
		int n = size();
		std::vector<std::vector<long long>> dist(n, std::vector<long long>(n, INF));
		for(int i = 0; i < n; i++) dist[i][i] = 0;
		for(int i = 0; i < n; i++)
			for(auto &e : edges[i]) dist[i][e.to] = std::min(dist[i][e.to], e.cost);
		for(int k = 0; k < n; k++)
			for(int i = 0; i < n; i++) {
				if(dist[i][k] == INF) continue;
				for(int j = 0; j < n; j++) {
					if(dist[k][j] == INF) continue;
					dist[i][j] = std::min(dist[i][j], dist[i][k] + dist[k][j]);
				}
			}
		return dist;
	}

	// Ο(V) (using DFS)
	// if a directed cycle exists, return {}
	std::vector<int> topological_sort() {  // verified
		std::vector<int> res;
		int n = size();
		std::vector<int> used(n, 0);
		bool not_DAG = false;
		auto dfs = [&](auto self, int k) -> void {
			if(not_DAG) return;
			if(used[k]) {
				if(used[k] == 1) not_DAG = true;
				return;
			}
			used[k] = 1;
			for(auto &e : edges[k]) self(self, e.to);
			used[k] = 2;
			res.push_back(k);
		};
		for(int i = 0; i < n; i++) dfs(dfs, i);
		if(not_DAG) return std::vector<int>{};
		std::reverse(res.begin(), res.end());
		return res;
	}

	bool is_DAG() { return !topological_sort().empty(); }  // verified

	// Ο(V)
	// array of the distance from each vertex to the most distant vertex
	std::vector<long long> height() {  // verified
		auto vec1 = bfs(0);
		int v1 = -1, v2 = -1;
		long long dia = -1;
		for(int i = 0; i < int(size()); i++)
			if(dia < vec1[i]) dia = vec1[i], v1 = i;
		vec1 = bfs(v1);
		dia = -1;
		for(int i = 0; i < int(size()); i++)
			if(dia < vec1[i]) dia = vec1[i], v2 = i;
		auto vec2 = bfs(v2);
		for(int i = 0; i < int(size()); i++) {
			if(vec1[i] < vec2[i]) vec1[i] = vec2[i];
		}
		return vec1;
	}

	// O(V+E)
	// vector<(int)(0 or 1)>
	// if it is not bipartite, return {}
	std::vector<int> bipartite_grouping() {
		std::vector<int> colors(size(), -1);
		auto dfs = [&](auto self, int now, int col) -> bool {
			colors[now] = col;
			for(auto &e : edges[now]) {
				if(col == colors[e.to]) return false;
				if(colors[e.to] == -1 and !self(self, e.to, !col)) return false;
			}
			return true;
		};
		for(int i = 0; i < int(size()); i++)
			if(!colors[i] and !dfs(dfs, i, 0)) return std::vector<int>{};
		return colors;
	}

	bool is_bipartite() { return !bipartite_grouping().empty(); }

	// Ο(V+E)
	// ((v1, v2), diameter)
	std::pair<std::pair<int, int>, long long> diameter() {  // verified
		auto vec = bfs(0);
		int v1 = -1, v2 = -1;
		long long dia = -1;
		for(int i = 0; i < int(size()); i++)
			if(dia < vec[i]) dia = vec[i], v1 = i;
		vec = bfs(v1);
		dia = -1;
		for(int i = 0; i < int(size()); i++)
			if(dia < vec[i]) dia = vec[i], v2 = i;
		std::pair<std::pair<int, int>, long long> res = {{v1, v2}, dia};
		return res;
	}

	// Ο(ElogV)
	long long prim() {  // verified
		long long res = 0;
		std::priority_queue<Edge, std::vector<Edge>, std::greater<Edge>> que;
		for(auto &e : edges[0]) que.push(e);
		std::vector<int> chk(size());
		chk[0] = 1;
		int cnt = 1;
		while(cnt < size()) {
			auto e = que.top();
			que.pop();
			if(chk[e.to]) continue;
			cnt++;
			res += e.cost;
			chk[e.to] = 1;
			for(auto &e2 : edges[e.to]) que.push(e2);
		}
		return res;
	}

	// Ο(ElogE)
	long long kruskal() {  // verified
		std::vector<std::tuple<int, int, long long>> Edges;
		for(int i = 0; i < int(size()); i++)
			for(auto &e : edges[i]) Edges.emplace_back(i, e.to, e.cost);
		std::sort(Edges.begin(), Edges.end(), [](const std::tuple<int, int, long long> &a, const std::tuple<int, int, long long> &b) {
			return std::get<2>(a) < std::get<2>(b);
		});
		std::vector<int> uf_data(size(), -1);
		auto root = [&uf_data](auto self, int x) -> int {
			if(uf_data[x] < 0) return x;
			return uf_data[x] = self(self, uf_data[x]);
		};
		auto unite = [&uf_data, &root](int u, int v) -> bool {
			u = root(root, u), v = root(root, v);
			if(u == v) return false;
			if(uf_data[u] > uf_data[v]) std::swap(u, v);
			uf_data[u] += uf_data[v];
			uf_data[v] = u;
			return true;
		};
		long long ret = 0;
		for(auto &e : Edges)
			if(unite(std::get<0>(e), std::get<1>(e))) ret += std::get<2>(e);
		return ret;
	}

	// O(V)
	std::vector<int> centroid() {
		int n = size();
		std::vector<int> centroid, sz(n);
		auto dfs = [&](auto self, int now, int per) -> void {
			sz[now] = 1;
			bool is_centroid = true;
			for(auto &e : edges[now]) {
				if(e.to != per) {
					self(self, e.to, now);
					sz[now] += sz[e.to];
					if(sz[e.to] > n / 2) is_centroid = false;
				}
			}
			if(n - sz[now] > n / 2) is_centroid = false;
			if(is_centroid) centroid.push_back(now);
		};
		dfs(dfs, 0, -1);
		return centroid;
	}

	// Ο(V+E)
	// directed graph from root to leaf
	Graph root_to_leaf(int root = 0) {
		Graph res(size());
		std::vector<int> chk(size(), 0);
		chk[root] = 1;
		auto dfs = [&](auto self, int now) -> void {
			for(auto &e : edges[now]) {
				if(chk[e.to] == 1) continue;
				chk[e.to] = 1;
				res.add_edge(now, e.to, e.cost, 1, 0);
				self(self, e.to);
			}
		};
		dfs(dfs, root);
		return res;
	}

	// Ο(V+E)
	// directed graph from leaf to root
	Graph leaf_to_root(int root = 0) {
		Graph res(size());
		std::vector<int> chk(size(), 0);
		chk[root] = 1;
		auto dfs = [&](auto self, int now) -> void {
			for(auto &e : edges[now]) {
				if(chk[e.to] == 1) continue;
				chk[e.to] = 1;
				res.add_edge(e.to, now, e.cost, 1, 0);
				self(self, e.to);
			}
		};
		dfs(dfs, root);
		return res;
	}

	// long long Chu_Liu_Edmonds(int root = 0) {}
};

struct tree_doubling {
private:
	std::vector<std::vector<int>> parent;
	std::vector<int> depth;
	std::vector<long long> dist;
	int max_jump = 1;

	void build() {
		for(int i = 0; i < max_jump - 1; i++) {
			for(int v = 0; v < (int)dist.size(); v++) {
				if(parent[i][v] == -1)
					parent[i + 1][v] = -1;
				else
					parent[i + 1][v] = parent[i][parent[i][v]];
			}
		}
	}

public:
	tree_doubling() = default;
	tree_doubling(const Graph &g, const int root = 0) : dist(g.size()), depth(g.size()) {
		int n = g.size();
		while((1 << max_jump) < n) max_jump++;
		parent.assign(max_jump, std::vector<int>(n, -1));
		auto dfs = [&](auto self, int now, int per, int d, long long cost) -> void {
			parent[0][now] = per;
			depth[now] = d;
			dist[now] = cost;
			for(auto &e : g[now])
				if(e.to != per) self(self, e.to, now, d + 1, cost + e.cost);
		};
		dfs(dfs, root, -1, 0, 0LL);
		build();
	}

	int lowest_common_ancestor(int u, int v) {
		if(depth[u] < depth[v]) std::swap(u, v);
		int k = parent.size();
		for(int i = 0; i < k; i++)
			if((depth[u] - depth[v]) >> i & 1) u = parent[i][u];
		if(u == v) return u;
		for(int i = k - 1; i >= 0; i--)
			if(parent[i][u] != parent[i][v]) u = parent[i][u], v = parent[i][v];
		return parent[0][u];
	}

	long long length_of_path(const int u, const int v) { return dist[u] + dist[v] - dist[lowest_common_ancestor(u, v)] * 2; }

	int level_ancestor(int v, int level) {
		assert(level >= 0);
		for(int jump = 0; jump < max_jump and level; jump++) {
			if(level & 1) v = parent[jump][v];
			level >>= 1;
		}
		return v;
	}
};

struct strongly_connected_components {
private:
	enum { CHECKED = -1,
		   UNCHECKED = -2 };
	const Graph &graph_given;
	Graph graph_reversed;
	std::vector<int> order, group_number; /* at the beginning of the building, 'group_number' is used as 'checked' */

	void dfs(int now) {
		if(group_number[now] != UNCHECKED) return;
		group_number[now] = CHECKED;
		for(auto &e : graph_given[now]) dfs(e.to);
		order.push_back(now);
	}

	void rdfs(int now, int group_count) {
		if(group_number[now] != UNCHECKED) return;
		group_number[now] = group_count;
		for(auto &e : graph_reversed[now]) rdfs(e.to, group_count);
	}

	void build(bool create_compressed_graph) {
		for(int i = 0; i < (int)graph_given.size(); i++) dfs(i);
		reverse(order.begin(), order.end());
		group_number.assign(graph_given.size(), UNCHECKED);
		int group = 0;
		for(auto &i : order)
			if(group_number[i] == UNCHECKED) rdfs(i, group), group++;
		graph_compressed.resize(group);
		groups.resize(group);
		for(int i = 0; i < (int)graph_given.size(); i++) groups[group_number[i]].push_back(i);
		if(create_compressed_graph) {
			std::vector<int> edges(group, -1);
			for(int i = 0; i < group; i++)
				for(auto &vertex : groups[i])
					for(auto &e : graph_given[vertex])
						if(group_number[e.to] != i and edges[group_number[e.to]] != i) {
							edges[group_number[e.to]] = i;
							graph_compressed[i].emplace_back(group_number[e.to], 1);
						}
		}
		return;
	}

public:
	std::vector<std::vector<int>> groups;
	Graph graph_compressed;

	strongly_connected_components(const Graph &g_, bool create_compressed_graph = false)
	  : graph_given(g_), graph_reversed(g_.size()), group_number(g_.size(), UNCHECKED) {
		for(size_t i = 0; i < g_.size(); i++)
			for(auto &e : graph_given[i]) graph_reversed[e.to].emplace_back(i, 1);
		build(create_compressed_graph);
	}

	const int &operator[](const int k) { return group_number[k]; }
};

struct low_link {
private:
	const Graph &graph_given;
	int order_next;

	void build() {
		int n = graph_given.size();
		order.resize(n, -1);
		low.resize(n);
		order_next = 0;
		for(int i = 0; i < n; i++)
			if(order[i] == -1) dfs(i);
	}

	void dfs(int now, int par = -1) {
		low[now] = order[now] = order_next++;
		bool is_articulation = false;
		int cnt = 0, cnt_par = 0;
		for(const auto &ed : graph_given[now]) {
			const int &nxt = ed.to;
			if(order[nxt] == -1) {
				cnt++;
				dfs(nxt, now);
				if(order[now] < low[nxt]) bridge.push_back(std::minmax(now, nxt));
				if(order[now] <= low[nxt]) is_articulation = true;
				low[now] = std::min(low[now], low[nxt]);
			} else if(nxt != par or cnt_par++ == 1) {
				low[now] = std::min(low[now], order[nxt]);
			}
		}
		if(par == -1 and cnt < 2) is_articulation = false;
		if(is_articulation) articulation.push_back(now);
		return;
	}

public:
	std::vector<int> order, low, articulation;
	std::vector<std::pair<int, int>> bridge;
	low_link() = default;
	low_link(const Graph &g_) : graph_given(g_) { build(); }
};

struct twoedge_connected_components {
private:
	const Graph &graph_given;
	int group_next;
	low_link li;
	std::vector<int> group_number;

	void build(bool create_compressed_graph) {
		int n = graph_given.size();
		group_number.resize(n, -1);
		group_next = 0;
		for(int i = 0; i < n; i++)
			if(group_number[i] == -1) dfs(i);
		groups.resize(group_next);
		for(int i = 0; i < graph_given.size(); i++) groups[group_number[i]].push_back(i);

		if(create_compressed_graph) {
			graph_compressed.resize(group_next);
			for(const auto &[u, v] : li.bridge) {
				int x = group_number[u], y = group_number[v];
				graph_compressed.add_edge(x, y);
			}
		}
	}

	void dfs(int now, int par = -1) {
		if(par != -1 and li.order[par] >= li.low[now])
			group_number[now] = group_number[par];
		else
			group_number[now] = group_next++;
		for(const auto &e : graph_given[now])
			if(group_number[e.to] == -1) dfs(e.to, now);
	}

public:
	Graph graph_compressed;
	std::vector<std::vector<int>> groups;
	twoedge_connected_components(const Graph &g_, bool create_compressed_graph = false) : graph_given(g_), li(g_) {
		build(create_compressed_graph);
	}

	const int &operator[](const int k) { return group_number[k]; }
};

#pragma endregion

int main() {
	std::ios::sync_with_stdio(false);
	std::cin.tie(nullptr);
	std::cout << std::fixed << std::setprecision(15);
	srand((unsigned)time(NULL));

	int n, m;
	cin >> n >> m;

	VEC(string, s, n - 1);

	Graph G(n);

	rep(n - 1) {
		INT(a, b);
		G.add_edge(a, b);
	}

	auto g = G.root_to_leaf(0);

	const int x = 3;
	const int y = 5;

	const int root = 0;
	vi val(n);

	auto calc_val = [&](auto dfs, int now, int res_par = 0) -> void {
		int ret = res_par;
		if(now) {
			auto &t = s[now - 1];
			int op = (t[4] == 'X' ? x : y);
			if(t[3] == '&') {
				ret &= op;
			} else if(t[3] == '|') {
				ret |= op;
			} else if(t[3] == '^') {
				ret ^= op;
			}
		}
		val[now] = ret;
		foa(e, g[now]) {
			dfs(dfs, e.to, ret);
		}
		return;
	};
	calc_val(calc_val, 0, 0);
	debug(val);

	vi updn(8);
	auto dfs = [&](auto dfs, int now = 0, int senteban = true) -> int {
		if(g[now].size() == 0) return updn[val[now]];
		int ret = senteban ? -2 : 2;
		foa(e, g[now]) {
			int res = dfs(dfs, e.to, !senteban);
			if(senteban) chmax(ret, res);
			if(!senteban) chmin(ret, res);
		}
		assert(abs(ret) < 2);
		return ret;
	};

	map<vector<int>, int> res;

	auto chk = [&](vi w) {
		if(find(w.begin(), w.end(), 0) == w.end()) return false;
		rep(i, 8) rep(j, 8) if(i == (j & i) and w[j] < w[i]) if(w[j] < w[i]) return false;
		return true;
	};

	auto f = [&](auto f, int i) -> void {
		if(i == 8) {
			if(chk(updn)) res[updn] = int(dfs(dfs) >= 0);
			return;
		}
		rep(nxt, -1, 2) {
			updn[i] = nxt;
			f(f, i + 1);
		}
		return;
	};
	f(f, 0);

	vi ans;
	rep(m) {
		int u, v;
		cin >> u >> v;
		array<int, 8> arr;
		arr[0] = 0;
		arr[1] = u & v;
		arr[2] = u & (u ^ v);
		arr[3] = u;
		arr[4] = v & (u ^ v);
		arr[5] = v;
		arr[6] = u ^ v;
		arr[7] = u | v;

		int tmp = -inf;
		rep(det, 8) {
			rep(i, 8) { updn[i] = arr[i] < arr[det] ? -1 : arr[i] == arr[det] ? 0 : 1; }
			assert(res.count(updn));
			debug(res[updn]);
			if(res[updn]) {
				chmax(tmp, arr[det]);
			}
		}
		ans.push_back(tmp);
	}
	assert(ans.size() == m);
	vout(ans, 1);

	return 0;
}
accuracy: 1
time_ms: 310
memory_kb: 29528
final_rank: 9