#include "circuit.h"
#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#pragma GCC optimize("O3,unroll-loops")
#pragma GCC target("avx2,bmi,bmi2,lzcnt,popcnt")
#define ll long long
#define ld long double
#define ull unsigned long long
#define ff first
#define ss second
#define pii pair<int,int>
#define pll pair<long long, long long>
#define vi vector<int>
#define vl vector<long long>
#define pb push_back
#define rep(i, b) for(int i = 0; i < (b); ++i)
#define rep2(i,a,b) for(int i = a; i <= (b); ++i)
#define rep3(i,a,b,c) for(int i = a; i <= (b); i+=c)
#define count_bits(x) __builtin_popcountll((x))
#define all(x) (x).begin(),(x).end()
#define siz(x) (int)(x).size()
#define forall(it,x) for(auto& it:(x))
using namespace __gnu_pbds;
using namespace std;
typedef tree<int, null_type, less<int>, rb_tree_tag,tree_order_statistics_node_update> ordered_set;
//mt19937 mt;void random_start(){mt.seed(chrono::time_point_cast<chrono::milliseconds>(chrono::high_resolution_clock::now()).time_since_epoch().count());}
//ll los(ll a, ll b) {return a + (mt() % (b-a+1));}
const int INF = 1e9+50;
const ll INF_L = 1e18+40;
const ll MOD = 1e9+7;
const int block = 64;
int ans[8001];
vi sons[16001];
int in_vert[16001];
bool is_in[8001];
int P[16001];
int max_path[16001];
int n;
void dfs_zero(int v)
{
if(v >= n)
{
in_vert[v] ^= 1;
return;
}
forall(it,sons[v]) dfs_zero(it);
}
bool try_set(vi x)
{
rep(i,n) is_in[i] = 0;
forall(it,x) is_in[it] = 1;
rep(i,n) in_vert[i] = 0;
rep2(i,n,n*2) in_vert[i] = 1;
rep(i,n)
{
if(ans[i] == 1)
{
in_vert[i] ^= 1;
in_vert[sons[i][0]] ^= 1;
in_vert[sons[i][1]] ^= 1;
}
}
forall(it,x)
{
in_vert[it] ^= 1;
in_vert[sons[it][0]] ^= 1;
in_vert[sons[it][1]] ^= 1;
if(!is_in[sons[it][0]]) dfs_zero(sons[it][0]);
else dfs_zero(sons[it][1]);
}
string q;
rep(i,n*2+1) if(in_vert[i]) q += "1"; else q += "0";
return !((bool)query(q));
}
void dfs_path(int v)
{
max_path[v] = 0;
forall(it,sons[v])
{
dfs_path(it);
max_path[v] = max(max_path[v],max_path[it]);
}
if(v < n) max_path[v]++;
}
string solve(int N, int R, vi U, vi V)
{
n = N;
rep2(i,n,n*2) sons[i] = {};
rep(i,n)
{
ans[i] = -1;
sons[i] = {U[i],V[i]};
P[U[i]] = i;
P[V[i]] = i;
}
int know_cnt = 0;
vi roots;
vi roots2;
while(know_cnt < n)
{
roots = {};
rep(i,n) if(ans[i] == -1 && (P[i] == i || ans[P[i]] != -1)) roots.pb(i);
forall(it,roots) dfs_path(it);
vi group;
while(siz(roots) != 0)
{
forall(it,roots) group.pb(it);
roots2 = {};
forall(it,roots)
{
pii best = {-1,-1};
forall(it2,sons[it]) if(it2 < n) best = max(best,{max_path[it2],it2});
if(best.ss != -1) roots2.pb(best.ss);
}
swap(roots,roots2);
}
while(siz(group) > block) group.pop_back();
if(!try_set(group))
{
know_cnt += siz(group);
forall(it,group) ans[it] = 0;
continue;
}
int l = 0;
int r = siz(group)-2;
int ans2 = siz(group)-1;
while(l <= r)
{
int mid = (l+r)/2;
vi g2;
rep(i,mid+1) g2.pb(group[i]);
if(try_set(g2))
{
ans2 = mid;
r = mid-1;
}
else
{
l = mid+1;
}
}
know_cnt += ans2+1;
rep(i,ans2) ans[group[i]] = 0;
ans[group[ans2]] = 1;
}
string ans2;
rep(i,n) if(ans[i] == 1) ans2 += "|"; else ans2 += "&";
return ans2;
}