Problem:
G: XOR Walk
問題
$N$ 頂点 $M$ 辺からなる連結な無向グラフがあり、頂点 ${a_i,b_i}$ の間に辺が存在します。各頂点には整数が一つ書かれており、頂点 $i$ に書かれた整数は $c_i$ です。
このグラフについて、$Q$ 個のクエリが与えられます。$q = 1,\ldots,Q$ 番目のクエリでは、以下の問題に答えてください。
ウォーク $W=(v_1,\ldots,v_k)$ のコスト $f(W)$ を $c_{v_1},\ldots,c_{v_k}$ の排他的論理和とします。$W$ が頂点 $S_q$ から頂点 $G_q$ へのウォーク全てを動くとき、$\displaystyle \max_{W} f(W)$ を求めてください。
なお、頂点列 $(v_1,\ldots,v_k)$ が次の条件を満たすとき、頂点 $S$ から頂点 $G$ へのウォークであると言います。
$k$ は正の整数である。
$i = 2,\dots,k$ に対して、$v_{i-1},v_i$ の間に辺が存在する。
$v_1 = S$, $v_k = G$
入力形式
$N$ $M$ $Q$
$c_1$ $c_2$ $\dots$ $c_N$
$a_1$ $b_1$
$\vdots$
$a_{M}$ $b_{M}$
$S_1$ $G_1$
$\vdots$
$S_Q$ $G_Q$
制約
$2 \leq N \leq 100{,}000$
$N-1 \leq M \leq 300{,}000$
$1 \leq Q \leq 100{,}000$
$0 \leq c_i \leq 2^{60} - 1$
$1 \leq a_i, b_i \leq N$
$a_i \neq b_i$
$\lbrace a_i,b_i\rbrace \neq \lbrace a_j,b_j\rbrace$ ($i \neq j$ のとき)
$1 \leq S_q, G_q \leq N$
$S_q \neq G_q$
与えられるグラフは連結
入力は全て整数
出力形式
出力は $Q$ 行からなります。
$i (1 \leq i \leq Q)$ 行目には $i$ 番目のクエリについての答えを出力してください。
入力例 1
3 2 1
3 2 1
1 2
2 3
1 2
出力例 1
3
ウォーク $(1,2,3,2,1,2)$ のコストは $3$ であり、これが最大値です。
入力例 2
2 1 2
1 1
1 2
1 2
1 2
出力例 2
0
0

Submitted solutions:

code_snippet: // AOJ #3244 XOR Walk
// 2025.4.17

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using ull = unsigned long long;

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

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

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

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

int main(){
    int N = Cin(), M = Cin(), Q = Cin();
    vector<ull> c(N+1), d(N+1);
    for(int i=1; i<=N; i++) c[i] = Cinll();

    vector<vector<int>> g(N+1);
    vector<pair<int,int>> E(M);
    for(int i=0;i<M;i++){
        int a = Cin(), b = Cin();
        E[i]={a,b};
        g[a].push_back(b);
        g[b].push_back(a);
    }

    vector<int> par(N+1,0), vis(N+1,0);
    queue<int> q;
    q.push(1);
    vis[1]=1;
    d[1]=0;
    while(!q.empty()){
        int u=q.front(); q.pop();
        for(int v:g[u]){
            if(!vis[v]){
                vis[v]=1;
                par[v]=u;
                d[v]=d[u]^c[u];
                q.push(v);
            }
        }
    }

    const int B=61;
    ull bse[B]={0};
    auto add_basis=[&](ull x){
        for(int i=B-1;i>=0;i--){
            if(!(x>>i&1)) continue;
            if(!bse[i]){
                bse[i]=x;
                break;
            }
            x ^= bse[i];
        }
    };

    for(auto [u,v]:E){
        if(par[v]==u){
            add_basis(d[v] ^ c[v] ^ d[u]);
        }
        else if(par[u]==v){
            add_basis(d[u] ^ c[u] ^ d[v]);
        }
        else{
            add_basis(d[u] ^ c[u] ^ d[v]);
            add_basis(d[v] ^ c[v] ^ d[u]);
        }
    }

    while(Q--){
        int S = Cin(), G = Cin();
        ull x = d[S] ^ d[G] ^ c[G];
        for(int i=B-1;i>=0;i--){
            if((x ^ bse[i]) > x) x ^= bse[i];
        }
        Cout(x);;
    }

    return 0;
}
accuracy: 1
time_ms: 130
memory_kb: 15668
final_rank: 5

code_snippet: #ifndef HIDDEN_IN_VS // 折りたたみ用

// 警告の抑制
#define _CRT_SECURE_NO_WARNINGS

// ライブラリの読み込み
#include <bits/stdc++.h>
using namespace std;

// 型名の短縮
using ll = long long; using ull = unsigned long long; // -2^63 ～ 2^63 = 9e18（int は -2^31 ～ 2^31 = 2e9）
using pii = pair<int, int>;	using pll = pair<ll, ll>;	using pil = pair<int, ll>;	using pli = pair<ll, int>;
using vi = vector<int>;		using vvi = vector<vi>;		using vvvi = vector<vvi>;	using vvvvi = vector<vvvi>;
using vl = vector<ll>;		using vvl = vector<vl>;		using vvvl = vector<vvl>;	using vvvvl = vector<vvvl>;
using vb = vector<bool>;	using vvb = vector<vb>;		using vvvb = vector<vvb>;
using vc = vector<char>;	using vvc = vector<vc>;		using vvvc = vector<vvc>;
using vd = vector<double>;	using vvd = vector<vd>;		using vvvd = vector<vvd>;
template <class T> using priority_queue_rev = priority_queue<T, vector<T>, greater<T>>;
using Graph = vvi;

// 定数の定義
const double PI = acos(-1);
int DX[4] = { 1, 0, -1, 0 }; // 4 近傍（下，右，上，左）
int DY[4] = { 0, 1, 0, -1 };
int INF = 1001001001; ll INFL = 4004004003094073385LL; // (int)INFL = INF, (int)(-INFL) = -INF;

// 入出力高速化
struct fast_io { fast_io() { cin.tie(nullptr); ios::sync_with_stdio(false); cout << fixed << setprecision(18); } } fastIOtmp;

// 汎用マクロの定義
#define all(a) (a).begin(), (a).end()
#define sz(x) ((int)(x).size())
#define lbpos(a, x) (int)distance((a).begin(), std::lower_bound(all(a), (x)))
#define ubpos(a, x) (int)distance((a).begin(), std::upper_bound(all(a), (x)))
#define Yes(b) {cout << ((b) ? "Yes\n" : "No\n");}
#define rep(i, n) for(int i = 0, i##_len = int(n); i < i##_len; ++i) // 0 から n-1 まで昇順
#define repi(i, s, t) for(int i = int(s), i##_end = int(t); i <= i##_end; ++i) // s から t まで昇順
#define repir(i, s, t) for(int i = int(s), i##_end = int(t); i >= i##_end; --i) // s から t まで降順
#define repe(v, a) for(const auto& v : (a)) // a の全要素（変更不可能）
#define repea(v, a) for(auto& v : (a)) // a の全要素（変更可能）
#define repb(set, d) for(int set = 0, set##_ub = 1 << int(d); set < set##_ub; ++set) // d ビット全探索（昇順）
#define repis(i, set) for(int i = lsb(set), bset##i = set; i < 32; bset##i -= 1 << i, i = lsb(bset##i)) // set の全要素（昇順）
#define repp(a) sort(all(a)); for(bool a##_perm = true; a##_perm; a##_perm = next_permutation(all(a))) // a の順列全て（昇順）
#define uniq(a) {sort(all(a)); (a).erase(unique(all(a)), (a).end());} // 重複除去
#define EXIT(a) {cout << (a) << endl; exit(0);} // 強制終了
#define inQ(x, y, u, l, d, r) ((u) <= (x) && (l) <= (y) && (x) < (d) && (y) < (r)) // 半開矩形内判定

// 汎用関数の定義
template <class T> inline ll powi(T n, int k) { ll v = 1; rep(i, k) v *= n; return v; }
template <class T> inline bool chmax(T& M, const T& x) { if (M < x) { M = x; return true; } return false; } // 最大値を更新（更新されたら true を返す）
template <class T> inline bool chmin(T& m, const T& x) { if (m > x) { m = x; return true; } return false; } // 最小値を更新（更新されたら true を返す）
template <class T> inline T getb(T set, int i) { return (set >> i) & T(1); }
template <class T> inline T smod(T n, T m) { n %= m; if (n < 0) n += m; return n; } // 非負mod

// 演算子オーバーロード
template <class T, class U> inline istream& operator>>(istream& is, pair<T, U>& p) { is >> p.first >> p.second; return is; }
template <class T> inline istream& operator>>(istream& is, vector<T>& v) { repea(x, v) is >> x; return is; }
template <class T> inline vector<T>& operator--(vector<T>& v) { repea(x, v) --x; return v; }
template <class T> inline vector<T>& operator++(vector<T>& v) { repea(x, v) ++x; return v; }

#endif // 折りたたみ用


//#if __has_include(<atcoder/all>)
//#include <atcoder/all>
//using namespace atcoder;
//
//#ifdef _MSC_VER
//#include "localACL.hpp"
//#endif
//
//using mint = modint998244353;
////using mint = static_modint<1000000007>;
////using mint = modint; // mint::set_mod(m);
//
//namespace atcoder {
//	inline istream& operator>>(istream& is, mint& x) { ll x_; is >> x_; x = x_; return is; }
//	inline ostream& operator<<(ostream& os, const mint& x) { os << x.val(); return os; }
//}
//using vm = vector<mint>; using vvm = vector<vm>; using vvvm = vector<vvm>; using vvvvm = vector<vvvm>; using pim = pair<int, mint>;
//#endif


#ifdef _MSC_VER // 手元環境（Visual Studio）
#include "local.hpp"
#else // 提出用（gcc）
inline int popcount(int n) { return __builtin_popcount(n); }
inline int popcount(ll n) { return __builtin_popcountll(n); }
inline int lsb(int n) { return n != 0 ? __builtin_ctz(n) : 32; }
inline int lsb(ll n) { return n != 0 ? __builtin_ctzll(n) : 64; }
inline int msb(int n) { return n != 0 ? (31 - __builtin_clz(n)) : -1; }
inline int msb(ll n) { return n != 0 ? (63 - __builtin_clzll(n)) : -1; }
#define dump(...)
#define dumpel(...)
#define dump_math(v)
#define input_from_file(f)
#define output_to_file(f)
#define Assert(b) { if (!(b)) { vc MLE(1<<30); EXIT(MLE.back()); } } // RE の代わりに MLE を出す
#endif


//【グラフの入力】O(n + m)
/*
* (始点, 終点) の組からなる入力を受け取り，n 頂点 m 辺のグラフを構築して返す．
*
* n : グラフの頂点の数
* m : グラフの辺の数（省略すれば n-1）
* directed : 有向グラフか（省略すれば false）
* zero_indexed : 入力が 0-indexed か（省略すれば false）
*/
Graph read_Graph(int n, int m = -1, bool directed = false, bool zero_indexed = false) {
	// verify : https://atcoder.jp/contests/tessoku-book/tasks/tessoku_book_bi

	Graph g(n);
	if (m == -1) m = n - 1;

	rep(j, m) {
		int a, b;
		cin >> a >> b;
		if (!zero_indexed) { --a; --b; }

		g[a].push_back(b);
		if (!directed && a != b) g[b].push_back(a);
	}

	return g;
}


//【二部グラフ判定（連結）】O(n + m)
/*
* 連結無向グラフが二部グラフかどうか判定する．
* 二部グラフならその彩色例を col に格納する（色は 0, 1 で表す）
*/
template <class G>
bool bipartite_graphQ(const G& g, vi& col) {
	// verify : https://atcoder.jp/contests/code-festival-2017-qualb/tasks/code_festival_2017_qualb_c

	int n = sz(g);

	// 頂点の色（0,1 は色を，-1 は未探索を表す）
	col = vi(n, -1);

	// 再帰用の関数
	function<bool(int)> dfs = [&](int s) {
		repe(t, g[s]) {
			// 未彩色の頂点の場合
			if (col[t] == -1) {
				// s と異なる色で t を彩色する．
				col[t] = 1 - col[s];

				// t から先を彩色しにいき，二部グラフでないならすぐに帰る．
				if (!dfs(t)) return false;
			}
			// 彩色済の頂点の場合
			else {
				// s と t が同色だったら二部グラフではないのですぐに帰る．
				if (col[t] == col[s]) return false;
			}
		}

		// ここまで来たなら見た範囲は二部グラフである．
		return true;
	};

	// 0 を始点として再帰関数を呼び出す．
	col[0] = 0;
	return dfs(0);
}


int main() {
//	input_from_file("input.txt");
//	output_to_file("output.txt");

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

	vl c(n);
	cin >> c;

	auto g = read_Graph(n, m);

	vi col;
	auto bi = bipartite_graphQ(g, col);
	dump("bi?:", bi, "col:", col);

	vector<pli> cw(n);
	rep(i, n) cw[i] = { c[i], 1 };

	int i = 0; bool odd0 = false;

	while (1) {
		sort(all(cw), greater<pli>());

		int n = sz(cw);
		repir(j, n - 1, 0) {
			auto [cj, wj] = cw[j];
			if (cj != 0) break;

			if (wj) odd0 = true;

			cw.pop_back();
		}
		n = sz(cw);

		if (i >= n) break;

		auto [ci, wi] = cw[i];
		int b = msb(ci);

		rep(j, n) {
			if (j == i) continue;

			auto [cj, wj] = cw[j];
			if (!getb(cj, b)) continue;

			cw[j] = { cj ^ ci, wi ^ wj };
		}

		i++;
	}
	dump("odd0?", odd0); dumpel(cw);
	
	ll x = 0; int wgt = 0;
	for (auto [c, w] : cw) {
		x ^= c;
		wgt ^= w;
	}
	dump("x:", x);

	ll x2 = 0;
	for (auto [c, w] : cw) {
		if (w) chmax(x2, x ^ c);
	}
	if (odd0) x2 = x;
	dump("x2:", x2);

	rep(hoge, q) {
		int s, t;
		cin >> s >> t;
		s--; t--;

		if (bi && ((wgt % 2 == 0) == (col[s] == col[t]))) {
			cout << x2 << "\n";
		}
		else {
			cout << x << "\n";
		}
	}
}
accuracy: 1
time_ms: 280
memory_kb: 18024
final_rank: 11

code_snippet: #include<bits/stdc++.h>
#define ll long long
#define MOD 1000000007
#define inf 1e18

using namespace std;

ll max_xor(ll a[],ll n){
    ll ans=0;
    int max_bit=63;
    ll present[64]={0};
    for(int i=1;i<=n;i++){
        ll x=a[i];
        for(int j=max_bit;j>=0;j--){
            if(x&(1LL<<j)){
                if(present[j]){
                    x=x^present[j];
                }
                else{
                    present[j]=x;
                    //ans=ans^x;
                    break;
                }
            }
        }
    }
    for(int j=max_bit;j>=0;j--){
        if((ans&(1LL<<j))==0){
            ans=ans^present[j];
        }
    }
    return ans;
}

void solve(){
    ll n,m,q; cin>>n>>m>>q;
    ll c[n+1];
    for(int i=1;i<=n;i++){
        cin>>c[i];
    }
    vector<pair<int,int> > edges(m);
    for(int i=0;i<m;i++){
        cin>>edges[i].first>>edges[i].second;
    }
    vector<pair<int,int> > queries(q);
    for(int i=0;i<q;i++){
        cin>>queries[i].first>>queries[i].second;
    }
    ll ans=max_xor(c,n);
    for(int i=0;i<q;i++){
        if(n==2) cout<<(c[queries[i].first]^c[queries[i].second])<<endl;
        else cout<<ans<<"\n";
    }
}

int main(){
    ios_base::sync_with_stdio(false); cin.tie(NULL); cout.tie(NULL);
    ll t=1;

    while(t--){
        solve();
    }
}
accuracy: 0.6410256410256411
time_ms: 70
memory_kb: 6708
final_rank: 15

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

using namespace std;

using ll = long long;

vector<ll> kitei(vector<ll> line){
  int n = line.size();
  for(int i=0;i<n;++i){
    int itr = i;
    for(int j=i;j<n;++j){
      if(line[itr] < line[j]){
        itr = j;
      }
    }
    swap(line[itr],line[i]);
    for(int j=i+1;j<n;++j){
      line[j] = min(line[j], line[j] ^ line[i]);
    }
  }
  while(line.size() and line.back()==0)line.erase(line.end()-1);
  return line;
}

vector<ll> add_kitei(vector<ll> line,ll x){
  line.push_back(x);
  return kitei(line);
}

void func(){
  int n;
  int m;
  int q;
  cin >> n >> m >> q;
  vector<ll> xs;
  vector<ll> as(n);
  vector<vector<int>> edges(n);
  vector<bool> colors(n,false);
  for(auto &i:as)cin >> i;
  for(int i=0;i<m;++i){
    int a;
    int b;
    cin >> a >> b;
    --a;
    --b;
    edges[a].push_back(b);
    edges[b].push_back(a);
  }
  {
    vector<int> used(n,false);
    vector<ll> sums(n,0);
    auto rec = [&](auto rec,int p,ll sum,bool color) -> void{
      if(used[p]){
        xs = add_kitei(xs, sums[p] ^ sum);
        return;
      }
      used[p] = true;
      sums[p] = sum;
      colors[p] = color;
      for(auto e:edges[p]){
        rec(rec, e, sum ^ as[e],not color);
      }
    };
    rec(rec,0,as[0],true);
  }
  for(int i=1;i<n;++i){
    vector<ll> ys = add_kitei(xs, as[i] ^ as[0]);
    swap(xs,ys);
  }
  for(int i=0;i+1<n;++i){
    vector<ll> ys = add_kitei(xs, as[i+1] ^ as[i]);
    swap(xs, ys);
  }

  for(int i=0;i<q;++i){
    int a;
    int b;
    cin >> a >> b;
    --a;
    --b;
    ll ans = 0;
    if(colors[a] == colors[b]){
      ans = as[b];
    }
    for(auto i:xs){
      ans = max(ans, ans ^ i);
    }
    cout << ans << endl;
  }
}

int main(){
  func();
}
accuracy: 1
time_ms: 1380
memory_kb: 24236
final_rank: 14

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

using namespace std;

using ll = long long;

vector<ll> kitei(vector<ll> line){
  int n = line.size();
  for(int i=0;i<n;++i){
    int itr = i;
    for(int j=i;j<n;++j){
      if(line[itr] < line[j]){
        itr = j;
      }
    }
    swap(line[itr],line[i]);
    for(int j=i+1;j<n;++j){
      line[j] = min(line[j], line[j] ^ line[i]);
    }
  }
  while(line.size() and line.back()==0)line.erase(line.end()-1);
  return line;
}

vector<ll> add_kitei(vector<ll> line,ll x){
  line.push_back(x);
  return kitei(line);
}

void func(){
  int n;
  int m;
  int q;
  cin >> n >> m >> q;
  vector<ll> xs;
  vector<ll> as(n);
  vector<vector<int>> edges(n);
  for(auto &i:as)cin >> i;
  for(int i=0;i<m;++i){
    int a;
    int b;
    cin >> a >> b;
    --a;
    --b;
    edges[a].push_back(b);
    edges[b].push_back(a);
  }
  {
    vector<int> used(n,false);
    vector<ll> sums(n,0);
    auto rec = [&](auto rec,int p,ll sum) -> void{
      if(used[p]){
        xs = add_kitei(xs, sums[p] ^ sum);
        return;
      }
      used[p] = true;
      sums[p] = sum;
      for(auto e:edges[p]){
        rec(rec, e, sum ^ as[e]);
      }
    };
    rec(rec,0,as[0]);
  }
  for(int i=1;i<n;++i){
    vector<ll> ys = add_kitei(xs, as[i] ^ as[0]);
    swap(xs,ys);
  }
  for(int i=0;i+1<n;++i){
    vector<ll> ys = add_kitei(xs, as[i+1] ^ as[i]);
    swap(xs, ys);
  }

  ll ans = 0;
  for(auto i:xs){
    ans = max(ans, ans ^ i);
  }
  for(int i=0;i<q;++i){
    cout << ans << endl;
  }
}

int main(){
  func();
}
accuracy: 0.6410256410256411
time_ms: 1320
memory_kb: 24108
final_rank: 16

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

using namespace std;

using ll = long long;

vector<ll> kitei(vector<ll> line){
  int n = line.size();
  for(int i=0;i<n;++i){
    int itr = i;
    for(int j=i;j<n;++j){
      if(line[itr] < line[j]){
        itr = j;
      }
    }
    swap(line[itr],line[i]);
    for(int j=i+1;j<n;++j){
      line[j] = min(line[j], line[j] ^ line[i]);
    }
  }
  while(line.size() and line.back()==0)line.erase(line.end()-1);
  return line;
}

vector<ll> add_kitei(vector<ll> line,ll x){
  line.push_back(x);
  return kitei(line);
}

void func(){
  int n;
  int m;
  int q;
  cin >> n >> m >> q;
  vector<ll> xs;
  vector<ll> as(n);
  for(auto &i:as)cin >> i;
  for(int i=0;i<m;++i){
    int a;
    int b;
    cin >> a >> b;
  }
  for(int i=1;i<n;++i){
    vector<ll> ys = add_kitei(xs, as[i] ^ as[0]);
    swap(xs,ys);
  }
  for(int i=0;i+1<n;++i){
    vector<ll> ys = add_kitei(xs, as[i+1] ^ as[i]);
    swap(xs, ys);
  }
  for(int i=0;i<q;++i){
    int a;
    int b;
    cin >> a >> b;
    --a;
    --b;
    ll ans = as[a] ^ as[b];
    for(auto i:xs){
      ans = max(ans, ans ^ i);
    }
    cout << ans << endl;
  }
}

int main(){
  func();
}
accuracy: 0.3076923076923077
time_ms: 260
memory_kb: 3444
final_rank: 20

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

using namespace std;

using ll = long long;

vector<ll> kitei(vector<ll> line){
  int n = line.size();
  for(int i=0;i<n;++i){
    int itr = i;
    for(int j=i;j<n;++j){
      if(line[itr] < line[j]){
        itr = j;
      }
    }
    swap(line[itr],line[i]);
    for(int j=i+1;j<n;++j){
      line[j] = min(line[j], line[j] ^ line[i]);
    }
  }
  while(line.size() and line.back()==0)line.erase(line.end()-1);
  return line;
}

vector<ll> add_kitei(vector<ll> line,ll x){
  line.push_back(x);
  return kitei(line);
}

void func(){
  int n;
  int m;
  int q;
  cin >> n >> m >> q;
  vector<ll> xs;
  vector<ll> as(n);
  for(auto &i:as)cin >> i;
  for(int i=1;i<n;++i){
    vector<ll> ys = add_kitei(xs, as[i] ^ as[0]);
    swap(xs,ys);
  }
  for(int i=0;i+1<n;++i){
    vector<ll> ys = add_kitei(xs, as[i+1] ^ as[i]);
    swap(xs, ys);
  }
  ll ans = 0;
  for(auto i:xs){
    ans = max(ans, ans ^ i);
  }
  for(int i=0;i<q;++i){
    cout << ans << endl;
  }
}

int main(){
  func();
}
accuracy: 0.3076923076923077
time_ms: 220
memory_kb: 3476
final_rank: 19

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

using namespace std;

using ll = long long;

vector<ll> kitei(vector<ll> line){
  int n = line.size();
  for(int i=0;i<n;++i){
    int itr = i;
    for(int j=i;j<n;++j){
      if(line[itr] < line[j]){
        itr = j;
      }
    }
    swap(line[itr],line[i]);
    for(int j=i+1;j<n;++j){
      line[j] = min(line[j], line[j] ^ line[i]);
    }
  }
  while(line.size() and line.back()==0)line.erase(line.end()-1);
  return line;
}

vector<ll> add_kitei(vector<ll> line,ll x){
  line.push_back(x);
  return kitei(line);
}

void func(){
  int n;
  int m;
  int q;
  cin >> n >> m >> q;
  vector<ll> xs;
  vector<ll> as(n);
  for(auto &i:as)cin >> i;
  for(int i=1;i<n;++i){
    xs = add_kitei(xs, as[i] ^ as[0]);
  }
  ll ans = 0;
  for(auto i:xs){
    ans = max(ans, ans ^ i);
  }
  for(int i=0;i<q;++i){
    cout << ans << endl;
  }
}

int main(){
  func();
}
accuracy: 0.3076923076923077
time_ms: 120
memory_kb: 3604
final_rank: 17

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

int ri() {
	int n;
	scanf("%d", &n);
	return n;
}


template<int mod>
struct ModInt{
	int x;
	ModInt () : x(0) {}
	ModInt (int64_t x) : x(x >= 0 ? x % mod : (mod - -x % mod) % mod) {}
	ModInt &operator += (const ModInt &p){
		if ((x += p.x) >= mod) x -= mod;
		return *this;
	}
	ModInt &operator -= (const ModInt &p) {
		if ((x += mod - p.x) >= mod) x -= mod;
		return *this;
	}
	ModInt &operator *= (const ModInt &p) {
		x = (int64_t) x * p.x % mod;
		return *this;
	}
	ModInt &operator /= (const ModInt &p) {
		*this *= p.inverse();
		return *this;
	}
	ModInt &operator ^= (int64_t p) {
		ModInt res = 1;
		for (; p; p >>= 1) {
			if (p & 1) res *= *this;
			*this *= *this;
		}
		return *this = res;
	}
	ModInt operator - () const { return ModInt(-x); }
	ModInt operator + (const ModInt &p) const { return ModInt(*this) += p; }
	ModInt operator - (const ModInt &p) const { return ModInt(*this) -= p; }
	ModInt operator * (const ModInt &p) const { return ModInt(*this) *= p; }
	ModInt operator / (const ModInt &p) const { return ModInt(*this) /= p; }
	ModInt operator ^ (int64_t p) const { return ModInt(*this) ^= p; }
	bool operator == (const ModInt &p) const { return x == p.x; }
	bool operator != (const ModInt &p) const { return x != p.x; }
	explicit operator int() const { return x; }
	ModInt &operator = (const int p) { x = p; return *this;}
	ModInt inverse() const {
		int a = x, b = mod, u = 1, v = 0, t;
		while (b > 0) {
			t = a / b;
			a -= t * b;
			std::swap(a, b);
			u -= t * v;
			std::swap(u, v);
		}
		return ModInt(u);
	}
	friend std::ostream & operator << (std::ostream &stream, const ModInt<mod> &p) {
		return stream << p.x;
	}
	friend std::istream & operator >> (std::istream &stream, ModInt<mod> &a) {
		int64_t x;
		stream >> x;
		a = ModInt<mod>(x);
		return stream;
	}
};
typedef ModInt<998244353> mint;

template<int mod> struct MComb {
	using mint = ModInt<mod>;
	std::vector<mint> fact;
	std::vector<mint> inv;
	MComb (int n) { // O(n + log(mod))
		fact = std::vector<mint>(n + 1, 1);
		for (int i = 1; i <= n; i++) fact[i] = fact[i - 1] * mint(i);
		inv.resize(n + 1);
		inv[n] = fact[n] ^ (mod - 2);
		for (int i = n; i--; ) inv[i] = inv[i + 1] * mint(i + 1);
	}
	mint ncr(int n, int r) {
		return fact[n] * inv[r] * inv[n - r];
	}
	mint npr(int n, int r) {
		return fact[n] * inv[n - r];
	}
	mint nhr(int n, int r) {
		assert(n + r - 1 < (int) fact.size());
		return ncr(n + r - 1, r);
	}
};

std::vector<std::vector<int> > hen;
std::vector<int64_t> c;
std::vector<int64_t> acc;
std::vector<int> depth;
std::vector<bool> used;
std::vector<std::pair<int, int> > additionals;
std::vector<std::vector<int> > parent;

void dfs(int i, int prev) {
	used[i] = true;
	acc[i] ^= c[i];
	parent[0][i] = prev;
	for (auto j : hen[i]) {
		if (!used[j]) {
			depth[j] = depth[i] + 1;
			acc[j] = acc[i];
			dfs(j, i);
		} else if (j != prev) additionals.push_back({i, j});
	}
}
int lca(int a, int b) {
	if (depth[a] < depth[b]) std::swap(a, b);
	for (int k = 20; k--; ) if ((depth[a] - depth[b]) >> k & 1) a = parent[k][a];
	if (a == b) return a;
	for (int k = 20; k--; ) if (parent[k][a] != parent[k][b]) a = parent[k][a], b = parent[k][b];
	return parent[0][a];
}

int main() {
	int n = ri();
	int m = ri();
	int q = ri();
	c.resize(n);
	for (auto &i : c) std::cin >> i;
	hen.resize(n);
	for (int i = 0; i < m; i++) {
		int a = ri() - 1;
		int b = ri() - 1;
		hen[a].push_back(b);
		hen[b].push_back(a);
	}
	acc.resize(n);
	used.resize(n);
	depth.resize(n);
	parent.resize(20, std::vector<int>(n, -1));
	dfs(0, -1);
	for (int i = 1; i < 20; i++) for (int j = 0; j < n; j++) {
		if (parent[i - 1][j] == -1) parent[i][j] = -1;
		else parent[i][j] = parent[i - 1][parent[i - 1][j]];
	}
	std::vector<int64_t> bases;
	auto add = [&] (int64_t t) {
		for (auto j : bases) if ((j ^ t) < t) t ^= j;
		if (t) bases.push_back(t);
	};
	for (auto i : additionals) {
		int64_t cur = acc[i.first] ^ acc[i.second] ^ c[lca(i.first, i.second)];
		add(cur);
	}
	for (int i = 0; i + 1 < n; i++) add(c[i] ^ c[i + 1]);
	for (int i = 0; i < q; i++) {
		int a = ri() - 1;
		int b = ri() - 1;
		int64_t t0 = acc[a] ^ acc[b] ^ c[lca(a, b)];
		auto calc = [&] (int64_t t) {
			for (auto j : bases) if ((t ^ j) >= t) t ^= j;
			return t;
		};
		printf("%" PRId64 "\n", calc(t0));
	}
	
	
	return 0;
}
accuracy: 1
time_ms: 340
memory_kb: 32960
final_rank: 12

code_snippet: #include <iostream>
#include <unordered_map>
#include <unordered_set>
#include <set>
#include <vector>
#include <numeric>
#include <algorithm>
#include <queue>
#include <string>
#include <random>
#include <array>
#include <climits>
#include <map>
#include <cassert>
#include <stack>
#include <iomanip>
#include <cfloat>
#include <bitset>
#include <fstream>
#include <chrono>


int main() {
	int n, m, q; std::cin >> n >> m >> q;
	std::vector<long long int> vertices(n);
	for (auto& c : vertices) {
		std::cin >> c;
	}
	std::vector<std::pair<int, int>> edges(m), queries(q);
	for (auto& [a, b] : edges) {
		std::cin >> a >> b; --a; --b;
	}
	for (auto& [s, g] : queries) {
		std::cin >> s >> g; --s; --g;
	}
	std::vector<std::vector<int>> graph(n);
	for (const auto [a, b] : edges) {
		graph[a].push_back(b);
		graph[b].push_back(a);
	}
	std::vector<int> depth(n, -1);
	std::queue<int> queue;
	depth[0] = 0;
	queue.push(0);
	while (!queue.empty()) {
		const auto top = queue.front(); queue.pop();
		for (const auto next : graph[top]) {
			if (depth[next] >= 0) continue;
			depth[next] = depth[top] + 1;
			queue.push(next);
		}
	}
	const bool is_bipartite{ std::all_of(edges.begin(), edges.end(), [&](const auto& e) {return (depth[e.first] & 1) != (depth[e.second] & 1); }) };
	std::vector<long long int> vec(60);
	for (const auto c : vertices) {
		auto v = c ^ vertices[0];
		for (auto d = 59; d >= 0; --d) {
			if (((v >> d) & 1) != 0) {
				if (vec[d] != 0) {
					v ^= vec[d];
				}
				else {
					vec[d] = v;
					break;
				}
			}
		}
	}
	if (is_bipartite) {
		for (const auto [s, g] : queries) {
			const auto is_even = (depth[s] & 1) != (depth[g] & 1);
			long long int result{ 0 };
			if (!is_even) {
				result = vertices[0];
			}
			for (auto d = 59; d >= 0; --d) {
				if (result < (result ^ vec[d])) {
					result ^= vec[d];
				}
			}
			std::cout << result << '\n';
		}
	}
	else {
		for (const auto [s, g] : queries) {
			long long int odd{ vertices[0]}, even{0};
			for (auto d = 59; d >= 0; --d) {
				if (odd < (odd ^ vec[d])) {
					odd ^= vec[d];
				}
				if (even < (even ^ vec[d])) {
					even ^= vec[d];
				}
			}
			std::cout << std::max(even, odd) << '\n';
		}
	}
}
accuracy: 1
time_ms: 200
memory_kb: 15580
final_rank: 9

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

#define REP(i,n) for(int i=0;i<(n);i++)
#define RREP(i,n) for(int i=(n-1);i>=0;i--)
#define ALL(v) v.begin(),v.end()

using ll=long long;
template<typename T>
bool chmin(T &a,T b){
  return (a>b&&(a=b,true));
}
template<typename T>
bool chmax(T &a,T b){
  return (a<b&&(a=b,true));
}
//BEGIN CUT HERE
struct UnionFind{
  int num;
  vector<int> r,p;
  UnionFind(){}
  UnionFind(int n):num(n),r(n,1),p(n,0){iota(p.begin(),p.end(),0);}
  
  int find(int x){
    return (x==p[x]?x:p[x]=find(p[x]));
  }
  
  bool same(int x,int y){
    return find(x)==find(y);
  }
  
  bool unite(int x,int y){
    x=find(x);y=find(y);
    if(x==y)return false;
    if(r[x]<r[y]) swap(x,y);
    r[x]+=r[y];
    p[y]=x;
    num--;
    return true;
  }
  
  int size(int x){
    return r[find(x)];
  }
  
  int count() const{
    return num;
  }
};
//END CUT HERE

int main(){
  int n,m,q;cin>>n>>m>>q;
  vector<ll> v1,v2;
  ll tmp;
  REP(_,n){
    ll c;cin>>c;
    v1.push_back(c|(1LL<<61));
    if(!_)tmp=c;
    else v2.push_back(tmp^c);
  }
  UnionFind uf(n*2);
  REP(_,m){
    int a,b;cin>>a>>b;a--;b--;
    uf.unite(a,b+n);
    uf.unite(a+n,b);
  }
  
  ll oddmax=0,evenmax=0;
  vector<ll> base1,base2;
  for(ll p:v1){
    for(ll q:base1)chmin(p,p^q);
    if(p)base1.push_back(p);
  }
  sort(base1.rbegin(),base1.rend());
  for(ll p:base1)chmax(oddmax,oddmax^p);
  oddmax-=1LL<<61;
  for(ll p:v2){
    for(ll q:base2)chmin(p,p^q);
    if(p)base2.push_back(p);
  }
  sort(base2.rbegin(),base2.rend());
  for(ll p:base2)chmax(evenmax,evenmax^p);

  REP(_,q){
    int s,g;cin>>s>>g;s--;g--;
    if(uf.count()==1)cout<<max(oddmax,evenmax)<<endl;
    else
      if(uf.same(s,g))cout<<oddmax<<endl;
      else cout<<evenmax<<endl;
  }
}
accuracy: 1
time_ms: 260
memory_kb: 6312
final_rank: 3

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>
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;
}

struct UnionFind{
    vector<int> par,num;
    UnionFind(int n):par(n),num(n,1){
        iota(par.begin(),par.end(),0);  //include<numeric>
    }
    int find(int v){
        return (par[v]==v)?v:(par[v]=find(par[v]));
    }
    void unite(int u,int v){
        u=find(u),v=find(v);
        if(u==v)return;
        if(num[u]<num[v])swap(u,v);
        num[u]+=num[v];
        par[v]=u;
    }
    bool same(int u,int v){
        return find(u) == find(v);
    }
    int size(int v){
        return num[find(v)];
    }
};

int main(){
    cin.tie(nullptr);
    ios::sync_with_stdio(false);
    int n,m,q; cin >> n >> m >> q;
    vector<ll> c(n);
    for(int i=0;i<n;i++){
        cin >> c[i];
    }
    vector<vector<int>> g(n);
    for(int i=0;i<m;i++){
        int x,y; cin >> x >> y;
        x--; y--;
        g[x].push_back(y);
        g[y].push_back(x);
    }
    if(n == 2){
        while(q--){
            int s,t; cin >> s >> t;
            s--; t--;
            cout << (c[s]^c[t]) << "\n";
        }
        return 0;
    }
    // 二部グラフ判定
    vector<int> col(n,-1);
    col[0] = 0;
    bool ok = true;
    auto dfs=[&](auto self,int s)->void{
        for(int t:g[s]){
            if(col[t]!=-1){
                if((col[s]^1)!=col[t]){
                    ok = false;
                }
            }
            else{
                col[t] = (col[s]^1);
                self(self,t);
            }
        }
    };
    dfs(dfs, 0);
    vector<ll> basis;
    for(ll e:c){
        for(auto &b:basis){
            e = min(e, e^b);
        }
        if(e){
            basis.push_back(e);
        }
    }
    ll res = 0;
    for(auto &b:basis){
        res = max(res, res^b);
    }
    // 完全グラフ
    if(!ok){
        while(q--){
            int s,t; cin >> s >> t;
            s--; t--;
            cout << res << "\n";
        }
    }
    else{
        vector<pair<ll,int>> basis2;
        for(int i=0;i<n;i++){
            pair<ll,int> p = {c[i],col[i]+1};
            for(auto &b:basis2){
                if(p.first>(p.first^b.first)){
                    p.first^=b.first;
                    p.second^=b.second;
                }
                else if(p.first==(p.first^b.first)){
                    p.second = min(p.second,p.second^b.second);
                }
            }
            if(p.first>0 or p.second>0){
                basis2.push_back(p);
            }
        }
        vector<ll> ans(4,-1);
        ans[0] = 0;
        for(auto b:basis2){
            vector<ll> nans=ans;
            for(int i=0;i<4;i++){
                if(ans[i^b.second] == -1)continue;
                nans[i] = max(nans[i], ans[i^b.second]^b.first);
            }
            ans = nans;
        }
        while(q--){
            int s,t; cin >> s >> t;
            s--; t--;
            if(col[s] == col[t]){
                cout << max(ans[1],ans[2]) << "\n";
            }
            else{
                cout << max(ans[0],ans[3]) << "\n";
            }
        }
    }
}
accuracy: 1
time_ms: 100
memory_kb: 17856
final_rank: 7

code_snippet: #define LOCAL
#include <bits/stdc++.h>
using namespace std;
#pragma region Macros
typedef long long ll;
typedef __int128_t i128;
typedef unsigned int uint;
typedef unsigned long long ull;
#define ALL(x) (x).begin(), (x).end()

template <typename T> istream& operator>>(istream& is, vector<T>& v) {
    for (T& x : v) is >> x;
    return is;
}
template <typename T> ostream& operator<<(ostream& os, const vector<T>& v) {
    for (int i = 0; i < (int)v.size(); i++) {
        os << v[i] << (i + 1 == (int)v.size() ? "" : " ");
    }
    return os;
}
template <typename T, typename U> ostream& operator<<(ostream& os, const pair<T, U>& p) {
    os << '(' << p.first << ',' << p.second << ')';
    return os;
}
template <typename T, typename U> ostream& operator<<(ostream& os, const map<T, U>& m) {
    os << '{';
    for (auto itr = m.begin(); itr != m.end();) {
        os << '(' << itr->first << ',' << itr->second << ')';
        if (++itr != m.end()) os << ',';
    }
    os << '}';
    return os;
}
template <typename T, typename U> ostream& operator<<(ostream& os, const unordered_map<T, U>& m) {
    os << '{';
    for (auto itr = m.begin(); itr != m.end();) {
        os << '(' << itr->first << ',' << itr->second << ')';
        if (++itr != m.end()) os << ',';
    }
    os << '}';
    return os;
}
template <typename T> ostream& operator<<(ostream& os, const set<T>& s) {
    os << '{';
    for (auto itr = s.begin(); itr != s.end();) {
        os << *itr;
        if (++itr != s.end()) os << ',';
    }
    os << '}';
    return os;
}
template <typename T> ostream& operator<<(ostream& os, const multiset<T>& s) {
    os << '{';
    for (auto itr = s.begin(); itr != s.end();) {
        os << *itr;
        if (++itr != s.end()) os << ',';
    }
    os << '}';
    return os;
}
template <typename T> ostream& operator<<(ostream& os, const unordered_set<T>& s) {
    os << '{';
    for (auto itr = s.begin(); itr != s.end();) {
        os << *itr;
        if (++itr != s.end()) os << ',';
    }
    os << '}';
    return os;
}
template <typename T> ostream& operator<<(ostream& os, const deque<T>& v) {
    for (int i = 0; i < (int)v.size(); i++) {
        os << v[i] << (i + 1 == (int)v.size() ? "" : " ");
    }
    return os;
}

template <int i, typename T> void print_tuple(ostream&, const T&) {}
template <int i, typename T, typename H, class... Args> void print_tuple(ostream& os, const T& t) {
    if (i) os << ',';
    os << get<i>(t);
    print_tuple<i + 1, T, Args...>(os, t);
}
template <typename... Args> ostream& operator<<(ostream& os, const tuple<Args...>& t) {
    os << '{';
    print_tuple<0, tuple<Args...>, Args...>(os, t);
    return os << '}';
}

void debug_out() { cerr << '\n'; }
template <class Head, class... Tail> void debug_out(Head&& head, Tail&&... tail) {
    cerr << head;
    if (sizeof...(Tail) > 0) cerr << ", ";
    debug_out(move(tail)...);
}
#ifdef LOCAL
#define debug(...)                                                                   \
    cerr << " ";                                                                     \
    cerr << #__VA_ARGS__ << " :[" << __LINE__ << ":" << __FUNCTION__ << "]" << '\n'; \
    cerr << " ";                                                                     \
    debug_out(__VA_ARGS__)
#else
#define debug(...) 42
#endif

template <typename T> T gcd(T x, T y) { return y != 0 ? gcd(y, x % y) : x; }
template <typename T> T lcm(T x, T y) { return x / gcd(x, y) * y; }

int topbit(signed t) { return t == 0 ? -1 : 31 - __builtin_clz(t); }
int topbit(long long t) { return t == 0 ? -1 : 63 - __builtin_clzll(t); }
int botbit(signed a) { return a == 0 ? 32 : __builtin_ctz(a); }
int botbit(long long a) { return a == 0 ? 64 : __builtin_ctzll(a); }
int popcount(signed t) { return __builtin_popcount(t); }
int popcount(long long t) { return __builtin_popcountll(t); }
bool ispow2(int i) { return i && (i & -i) == i; }

template <class T> T ceil(T x, T y) {
    assert(y >= 1);
    return (x > 0 ? (x + y - 1) / y : x / y);
}
template <class T> T floor(T x, T y) {
    assert(y >= 1);
    return (x > 0 ? x / y : (x - y + 1) / y);
}

template <class T1, class T2> inline bool chmin(T1& a, T2 b) {
    if (a > b) {
        a = b;
        return true;
    }
    return false;
}
template <class T1, class T2> inline bool chmax(T1& a, T2 b) {
    if (a < b) {
        a = b;
        return true;
    }
    return false;
}
#pragma endregion

#include <algorithm>
#include <cassert>
#include <vector>

struct UnionFind {
    UnionFind(int n) : n(n), num(n), data(n, -1) {}

    int find(int x) {
        assert(0 <= x && x < n);
        return data[x] < 0 ? x : data[x] = find(data[x]);
    }

    bool merge(int x, int y) {
        assert(0 <= x && x < n);
        assert(0 <= y && y < n);
        if ((x = find(x)) == (y = find(y))) return false;
        if (-data[x] < -data[y]) std::swap(x, y);
        data[x] += data[y];
        data[y] = x;
        num--;
        return true;
    }

    bool same(int x, int y) {
        assert(0 <= x && x < n);
        assert(0 <= y && y < n);
        return find(x) == find(y);
    }

    int size(int x) {
        assert(0 <= x && x < n);
        return -data[find(x)];
    }

    int count() const { return num; }

    std::vector<std::vector<int>> groups() {
        std::vector<std::vector<int>> res(n);
        for (int i = 0; i < n; i++) res[find(i)].emplace_back(i);
        res.erase(std::remove_if(res.begin(), res.end(), [&](const std::vector<int>& v) { return v.empty(); }));
        return res;
    }

    int operator[](int x) { return find(x); }

private:
    int n, num;
    // root node : -1 * component size
    // otherwise : parent
    std::vector<int> data;
};

/**
 * @brief Union Find (Disjoint Set Union)
 * @docs docs/datastructure/UnionFind.md
 */

const int INF = 1e9;
const long long IINF = 1e18;
const int dx[4] = {1, 0, -1, 0}, dy[4] = {0, 1, 0, -1};
const char dir[4] = {'D', 'R', 'U', 'L'};
const long long MOD = 1000000007;
// const long long MOD = 998244353;

const int MAX = 60;

int main() {
    cin.tie(0);
    ios::sync_with_stdio(false);
    int N, M, Q;
    cin >> N >> M >> Q;
    vector<ll> c(N);
    for (auto& x : c) cin >> x;
    UnionFind UF(2 * N);
    for (; M--;) {
        int a, b;
        cin >> a >> b;
        a--, b--;
        UF.merge(a, b + N);
        UF.merge(a + N, b);
    }
    bool bipar = true;
    for (int i = 0; i < N; i++) {
        if (UF.same(i, i + N)) {
            bipar = false;
        }
    }

    vector<ll> bases;
    for (int i = 0; i < N; i++) {
        c[i] |= 1LL << MAX;
        for (auto& base : bases) c[i] = min(c[i], c[i] ^ base);
        if (c[i] != 0) bases.emplace_back(c[i]);
    }
    ll odd = bases[0], even = 0;
    for (size_t i = 1; i < bases.size(); i++) {
        odd = max(odd, odd ^ bases[i]);
        even = max(even, even ^ bases[i]);
    }
    odd ^= 1LL << MAX;

    auto solve = [&](int S, int G) {
        if (bipar) return UF.same(S, G) ? odd : even;
        return max(odd, even);
    };

    for (; Q--;) {
        int S, G;
        cin >> S >> G;
        cout << solve(--S, --G) << '\n';
    }
    return 0;
}
accuracy: 1
time_ms: 60
memory_kb: 4660
final_rank: 1

code_snippet: #pragma region Macros
#include <bits/stdc++.h>
using namespace std;
template <class T> inline bool chmax(T &a, T b) {
    if(a < b) {
        a = b;
        return 1;
    }
    return 0;
}
template <class T> inline bool chmin(T &a, T b) {
    if(a > b) {
        a = b;
        return 1;
    }
    return 0;
}
#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

struct Setup {
    Setup() {
        cin.tie(0);
        ios::sync_with_stdio(false);
        cout << fixed << setprecision(15);
    }
} __Setup;

using ll = long long;
#define ALL(v) (v).begin(), (v).end()
#define RALL(v) (v).rbegin(), (v).rend()
#define FOR(i, a, b) for(int i = (a); i < int(b); i++)
#define REP(i, n) FOR(i, 0, n)
const int INF = 1 << 30;
const ll LLINF = 1LL << 60;
constexpr int MOD = 1000000007;
const int dx[4] = {1, 0, -1, 0};
const int dy[4] = {0, 1, 0, -1};

void Case(int i) { cout << "Case #" << i << ": "; }
int popcount(int x) { return __builtin_popcount(x); }
ll popcount(ll x) { return __builtin_popcountll(x); }
#pragma endregion Macros

int main() {
    int N, M, Q;
    cin >> N >> M >> Q;
    vector<ll> c(N);
    REP(i, N) cin >> c[i];
    vector<vector<int>> G(N);
    REP(i, M) {
        int a, b;
        cin >> a >> b;
        a--; b--;
        G[a].push_back(b);
        G[b].push_back(a);
    }

    vector<int> color(N, -1);
    bool is_nibu = true;
    auto dfs = [&](auto&& self, int u, int p, int c) -> void {
        color[u] = c;
        for(int v : G[u]) {
            if(color[v] != -1 and color[v] == c) is_nibu = false;
            if(color[v] == -1) {
                self(self, v, u, 1-c);
            }
        }
    };
    dfs(dfs, 0, -1, 0);
    
    if(!is_nibu) {
        ll mx = 0;
        vector<ll> bases;
        REP(i, N) {
            ll b = c[i];
            for(const auto& t : bases) chmin(b, b ^ t);
            if(b > 0) bases.push_back(b);
        }
        for(const auto& t : bases) chmax(mx, mx ^ t);
        REP(_, Q) {
            int s, g;
            cin >> s >> g;
            cout << mx << "\n";
        }
    } else {
        // odd
        vector<ll> odds(N), evens(N);
        REP(i, N) {
            odds[i] = c[i] + (1LL << 61);
            evens[i] = c[i] ^ c[(i+1)%N];
        }
        vector<ll> odd_bases, even_bases;
        REP(i, N) {
            ll b = odds[i];
            for(const auto& t : odd_bases) chmin(b, b ^ t);
            if(b > 0) odd_bases.push_back(b);
            b = evens[i];
            for(const auto& t : even_bases) chmin(b, b ^ t);
            if(b > 0) even_bases.push_back(b);
        }
        array<ll, 2> mxs = {0, 0};
        for(const auto& e : even_bases) chmax(mxs[0], mxs[0] ^ e);
        for(const auto& e : odd_bases) chmax(mxs[1], mxs[1] ^ e);
        mxs[1] -= (1LL << 61);
        REP(_, Q) {
            int s, g;
            cin >> s >> g;
            s--; g--;
            if(color[s] != color[g]) cout << mxs[0] << "\n";
            else cout << mxs[1] << "\n";
        }
    }
}
accuracy: 1
time_ms: 110
memory_kb: 18312
final_rank: 10

code_snippet: #include <iostream>
#include <iomanip>
#include <cstdio>
#include <cmath>
#include <ctime>
#include <cstdlib>
#include <cassert>
#include <vector>
#include <list>
#include <stack>
#include <queue>
#include <deque>
#include <map>
#include <set>
#include <bitset>
#include <string>
#include <algorithm>
#include <utility>
#include <complex>
#include <unordered_set>
#include <unordered_map>
#define rep(x, s, t) for(ll x = (s); (x) <= (t); (x)++)
#define per(x, s, t) for(ll x = (s); (x) >= (t); (x)--)
#define reps(x, s) for(ll x = 0; (x) < (ll)(s).size(); (x)++)
#define chmin(x, y) (x) = min((x), (y))
#define chmax(x, y) (x) = max((x), (y))
#define sz(x) ((ll)(x).size())
#define all(x) (x).begin(),(x).end()
#define outl(...) dump_func(__VA_ARGS__)
#define outf(x) cout << fixed << setprecision(16) << (x) << endl
#define inf 2e18
#define eps 1e-9
const double PI = 3.1415926535897932384626433;

using namespace std;

typedef long long llint;
typedef long long ll;
typedef pair<ll, ll> P;

struct edge{
	ll to, cost;
	edge(){}
	edge(ll a, ll b){ to = a, cost = b;}
};
const int dx[] = {1, 0, -1, 0}, dy[] = {0, -1, 0, 1};

const int mod = 1000000007;
//const int mod = 998244353;

struct mint{
	int x;
	mint(ll y = 0){if(y < 0 || y >= mod) y = (y%mod+mod)%mod; x = y;}
	mint(const mint &ope) {x = ope.x;}

	mint operator-(){return mint(-x);}
	mint operator+(const mint &ope){return mint(x) += ope;}
	mint operator-(const mint &ope){return mint(x) -= ope;}
	mint operator*(const mint &ope){return mint(x) *= ope;}
	mint operator/(const mint &ope){return mint(x) /= ope;}
	mint& operator+=(const mint &ope){
		x += ope.x;
		if(x >= mod) x -= mod;
		return *this;
	}
	mint& operator-=(const mint &ope){
		x += mod - ope.x;
		if(x >= mod) x -= mod;
		return *this;
	}
	mint& operator*=(const mint &ope){
		ll tmp = x;
		tmp *= ope.x, tmp %= mod;
		x = tmp;
		return *this;
	}
	mint& operator/=(const mint &ope){
		ll n = mod-2; mint mul = ope;
		while(n){
			if(n & 1) *this *= mul;
			mul *= mul;
			n >>= 1;
		}
		return *this;
	}
	mint inverse(){return mint(1) / *this;}
	bool operator ==(const mint &ope){return x == ope.x;}
	bool operator !=(const mint &ope){return x != ope.x;}
	bool operator <(const mint &ope){return x < ope.x;}
};
mint modpow(mint a, ll n){
	if(n == 0) return mint(1);
	if(n % 2) return a * modpow(a, n-1);
	else return modpow(a*a, n/2);
}
istream& operator >>(istream &is, mint &ope){
	ll t; is >> t, ope.x = t;
	return is;
}
ostream& operator <<(ostream &os, mint &ope){return os << ope.x;}
ostream& operator <<(ostream &os, const mint &ope){return os << ope.x;}

vector<mint> fact, fact_inv;
void make_fact(int n){
	fact.resize(n+1), fact_inv.resize(n+1);
	fact[0] = mint(1); rep(i, 1, n) fact[i] = fact[i-1] * mint(i);
	fact_inv[n] = fact[n].inverse(); per(i, n-1, 0) fact_inv[i] = fact_inv[i+1] * mint(i+1);
}
mint comb(int n, int k){ if(n < 0 || k < 0 || n < k) return mint(0); return fact[n] * fact_inv[k] * fact_inv[n-k];}
mint perm(int n, int k){ return comb(n, k) * fact[k]; }

vector<int> prime, pvec;
void make_prime(int n){
	prime.resize(n+1);
	rep(i, 2, n){
		if(prime[i]) continue;
		for(int j = i; j <= n; j+=i) prime[j] = i;
	}
	rep(i, 2, n) if(prime[i] == i) pvec.push_back(i);
}

bool exceed(ll x, ll y, ll m){return x >= m / y + 1;}
void mark(){ cout << "*" << endl; }
void yes(){ cout << "YES" << endl; }
void no(){ cout << "NO" << endl; }
ll floor(ll a, ll b){ if(b < 0) a *= -1, b *= -1; if(a >= 0) return a/b; else return -((-a+b-1)/b); }
ll ceil(ll a, ll b){ if(b < 0) a *= -1, b *= -1; if(a >= 0) return (a+b-1)/b; else return -((-a)/b); }
ll modulo(ll a, ll b){ b = abs(b); return a - floor(a, b) * b; }
ll sgn(ll x){ if(x > 0) return 1; if(x < 0) return -1; return 0;}
ll gcd(ll a, ll b){if(b == 0) return a; return gcd(b, a%b);}
ll lcm(ll a, ll b){return a/gcd(a, b)*b;}
ll digitnum(ll x, ll b = 10){ll ret = 0; for(; x; x /= b) ret++; return ret;}
ll digitsum(ll x, ll b = 10){ll ret = 0; for(; x; x /= b) ret += x % b; return ret;}
string lltos(ll x){string ret; for(;x;x/=10) ret += x % 10 + '0'; reverse(ret.begin(), ret.end()); return ret;}
ll stoll(string &s){ll ret = 0; for(auto c : s) ret *= 10, ret += c - '0'; return ret;}
template<typename T>
void uniq(T &vec){ sort(vec.begin(), vec.end()); vec.erase(unique(vec.begin(), vec.end()), vec.end());}

template<class S, class T> pair<S, T>& operator+=(pair<S,T> &s, const pair<S,T> &t){
	s.first += t.first, s.second += t.second;
	return s;
}
template<class S, class T> pair<S, T>& operator-=(pair<S,T> &s, const pair<S,T> &t){
	s.first -= t.first, s.second -= t.second;
	return s;
}
template<class S, class T> pair<S, T> operator+(const pair<S,T> &s, const pair<S,T> &t){
	return pair<S,T>(s.first+t.first, s.second+t.second);
}
template<class S, class T> pair<S, T> operator-(const pair<S,T> &s, const pair<S,T> &t){
	return pair<S,T>(s.first-t.first, s.second-t.second);
}
template<typename T>
ostream& operator << (ostream& os, vector<T>& vec) {
	reps(i, vec) os << vec[i] << (i + 1 == vec.size() ? "" : " "); return os;
}
template<typename T>
ostream& operator << (ostream& os, const vector<T>& vec) {
	reps(i, vec) os << vec[i] << (i + 1 == vec.size() ? "" : " "); return os;
}
template<typename T>
ostream& operator << (ostream& os, deque<T>& deq) {
	reps(i,  deq) os << deq[i] << (i + 1 == deq.size() ? "" : " "); return os;
}
template<typename T, typename U>
ostream& operator << (ostream& os, pair<T, U>& pair_var) {
	os << "(" << pair_var.first << ", " << pair_var.second << ")";
	return os;
}
template<typename T, typename U>
ostream& operator << (ostream& os, const pair<T, U>& pair_var) {
	os << "(" << pair_var.first << ", " << pair_var.second << ")";
	return os;
}
template<typename T, typename U>
ostream& operator << (ostream& os, map<T, U>& map_var) {
	for(typename map<T, U>::iterator itr = map_var.begin(); itr != map_var.end(); itr++) {
		os << "(" << itr->first << ", " << itr->second << ")";
		itr++; if(itr != map_var.end()) os << ","; itr--;
	}
	return os;
}
template<typename T>
ostream& operator << (ostream& os, set<T>& set_var) {
	for(typename set<T>::iterator itr = set_var.begin(); itr != set_var.end(); itr++) {
		os << *itr; ++itr; if(itr != set_var.end()) os << " "; itr--;
	}
	return os;
}
template<typename T>
ostream& operator << (ostream& os, multiset<T>& set_var) {
	for(typename multiset<T>::iterator itr = set_var.begin(); itr != set_var.end(); itr++) {
		os << *itr; ++itr; if(itr != set_var.end()) os << " "; itr--;
	}
	return os;
}
template<typename T>
void outa(T a[], ll s, ll t){rep(i, s, t){ cout << a[i]; if(i < t) cout << " ";}cout << endl;}
void dump_func(){cout << endl;}
template <class Head, class... Tail>
void dump_func(Head &&head, Tail &&... tail) {
	cout << head;
	if(sizeof...(Tail) > 0) cout << " ";
	dump_func(std::move(tail)...);
}

struct LCA{
	int n, logn;
	vector<vector<int> > prev;
	vector<int> depth;
	vector<int> used;

	LCA(){}
	void predfs(vector<ll> G[], int v, int p, int d)
	{
		used[v] = 1;
		depth[v] = d, prev[v][0] = p;
		for(auto u : G[v]){
			if(u == p) continue;
			if(used[u]) continue;
			predfs(G, u, v, d+1);
		}
	}
	void init(vector<ll> G[], int n, int root = 1)  //_1-indexBﾂ
	{
		this->n = n;
		for(int i = 0; ; i++){
			if(n <= (1<<i)){
				logn = i;
				break;
			}
		}
		prev.resize(n+1);
		for(int i = 0; i < prev.size(); i++) prev[i].resize(logn);
		depth.resize(n+1);

		used.resize(n+1);

		prev[0][0] = 0;
		predfs(G, root, 0, 0);
		for(int i = 1; i < logn; i++){
			for(int j = 0; j <= n; j++){
				prev[j][i] = prev[prev[j][i-1]][i-1];
			}
		}
	}
	int getLCA(int u, int v){
		int x = u, y = v;
		if(depth[y] > depth[x]) swap(x, y);

		for(int i = logn-1; i >= 0; i--){
			if(depth[x] - (1<<i) >= depth[y]) x = prev[x][i];
		}
		if(x == y) return x;
		for(int i = logn-1; i >= 0; i--){
			if(prev[x][i] != prev[y][i]){
				x = prev[x][i];
				y = prev[y][i];
			}
		}
		x = prev[x][0];
		return x;
	}
};




struct GaussianElimination{
	vector<ll> vec;
	int bitlen;
	int dim;
	
	GaussianElimination(int b = 60){
		init(b);
	}
	void init(int b = 60){
		dim = 0, bitlen = b;
		vec.clear();
	}
	void add(ll x) //ベクトルを追加
	{
		vec.push_back(x);
		int n = vec.size();
		
		int r = 0, p = -1;
		for(int i = bitlen-1; i >= 0 && r < n-1; i--){ //上位ビットから見ていく
			if((vec[r]&(1LL<<i)) == 0){
				if((vec[n-1]&(1LL<<i)) == 0 || p != -1) goto end;
				if(p == -1) p = r;
			}
			else if(vec[n-1]&(1LL<<i)) vec[n-1] ^= vec[r];
			r++;
			end:;
		}
		if(p != -1){
			ll tmp = vec[n-1];
			for(int i = n-1; i >= p+1; i--) vec[i] = vec[i-1];
			vec[p] = tmp;
		}
		if(vec[dim]) dim++;
	}
	
	bool check(ll x) //ベクトルが部分空間に含まれるか？
	{
		int n = vec.size();
		
		int r = 0;
		for(int i = bitlen-1; i >= 0 && r < n; i--){
			if((x & (1LL<<i)) == 0){
				if(vec[r] & (1LL<<i)) r++;
				continue;
			}
 			if((vec[r]&(1LL<<i)) == 0) return false;
			x ^= vec[r];
			r++;
		}
		return x == 0;
	}
	ll getMax(ll x)
	{
		int p = bitlen-1;
		for(int r = 0; r < sz(vec); r++){
			while(p >= 0 && (vec[r] & (1LL<<p)) == 0) p--;
			if(p < 0) break;
			if((x & (1LL<<p)) == 0) x ^= vec[r];
		}
		return x;
	}
};



ll n, m, Q;
ll c[100005], w[100005];
vector<ll> G[100005];
LCA lca;
GaussianElimination ge;

void dfs(int v, int p, ll d)
{
	w[v] = d;
	for(auto u : G[v]){
		if(u == p) continue;
		if(w[u] != -1) ge.add(w[u]^w[v]^c[lca.getLCA(u, v)]);
		else dfs(u, v, d^c[u]);
	}
}

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

	cin >> n >> m >> Q;
	rep(i, 1, n) cin >> c[i];
	ll u, v;
	rep(i, 1, m){
		cin >> u >> v;
		G[u].push_back(v);
		G[v].push_back(u);
	}
	lca.init(G, n);

	rep(i, 1, n) w[i] = -1;
	dfs(1, -1, 0);
	rep(i, 1, n) ge.add(c[1]^c[i]);

	//outa(w, 1, n);

	//outl(ge.vec);

	rep(q, 1, Q){
		cin >> u >> v;
		ll ans = w[u] ^ w[v] ^ c[lca.getLCA(u, v)];
		//outl(ans);
		outl(ge.getMax(ans));
	}

	return 0;
}
accuracy: 1
time_ms: 480
memory_kb: 42388
final_rank: 13

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

struct UnionFind {
    vector<int> p,e;
    UnionFind(int n) { p.resize(n, -1); e.resize(n, 0); }

    int unite(int a, int b) {
        int x = root(a), y = root(b); e[x]++;
        if(x == y) return x;
        if(-p[x] < -p[y]) swap(x, y);
        p[x] += p[y];
        p[y] = x;
        e[x] += e[y];
        return x;
    }

    bool same(int a, int b) { return root(a) == root(b); }

    int root(int a) {
        if(p[a] < 0) return a;
        return p[a] = root(p[a]);
    }

    int size(int a) { return -p[root(a)]; }
    int edge_size(int a) { return e[root(a)]; }
};

int main(){
    cin.tie(0);
    ios::sync_with_stdio(0);
    
    int N,M,Q; cin >> N >> M >> Q;
    UnionFind uf(N + N);
    vector<ll> C(N);
    rep(i,N) cin >> C[i];
    rep(i,M) {
        int u,v; cin >> u >> v; u--; v--;
        uf.unite(u, v + N);
        uf.unite(v, u + N);
    }

    bool is_bp = true;
    rep(i,N) if(uf.same(i, i + N)) is_bp = false;

    vector<ll> A = C;
    rep(i,N) A[i] ^= C[0];
    vector<ll> B;
    rep(b,70) {
        auto i = max_element(A.begin(), A.end()) - A.begin();
        if(A[i] == 0) break;
        B.push_back(A[i]);
        rep(j,N) if(j != i) A[j] = min(A[j], A[j] ^ A[i]);
        A[i] = 0;
    }

    A = B;
    sort(A.rbegin(), A.rend());
    ll even = 0, odd = C[0];
    for(ll a : A){
        even = max(even, even ^ a);
        odd  = max(odd , odd  ^ a);
    }

    while(Q --> 0) {
        int s,g; cin >> s >> g; s--; g--;
        if(is_bp)
            cout << (uf.same(s, g) ? odd : even) << '\n';
        else
            cout << max(even, odd) << '\n';
    }
}
accuracy: 1
time_ms: 60
memory_kb: 6232
final_rank: 2

code_snippet: #define _USE_MATH_DEFINES
#include <bits/stdc++.h>
using namespace std;
#define FOR(i,m,n) for(int i=(m);i<(n);++i)
#define REP(i,n) FOR(i,0,n)
#define ALL(v) (v).begin(),(v).end()
using ll = long long;
constexpr int INF = 0x3f3f3f3f;
constexpr long long LINF = 0x3f3f3f3f3f3f3f3fLL;
constexpr double EPS = 1e-8;
constexpr int MOD = 1000000007;
// constexpr int MOD = 998244353;
constexpr int DY[]{1, 0, -1, 0}, DX[]{0, -1, 0, 1};
constexpr int DY8[]{1, 1, 0, -1, -1, -1, 0, 1}, DX8[]{0, -1, -1, -1, 0, 1, 1, 1};
template <typename T, typename U> inline bool chmax(T &a, U b) { return a < b ? (a = b, true) : false; }
template <typename T, typename U> inline bool chmin(T &a, U b) { return a > b ? (a = b, true) : false; }
struct IOSetup {
  IOSetup() {
    std::cin.tie(nullptr);
    std::ios_base::sync_with_stdio(false);
    std::cout << fixed << setprecision(20);
  }
} iosetup;

bool is_bipartite(const std::vector<std::vector<int>> &graph, std::vector<int> &color) {
  const int n = graph.size();
  color.assign(n, -1);
  std::function<bool(int, int)> dfs = [&graph, &color, &dfs](const int ver, const int c) -> bool {
    color[ver] = c;
    for (const int e : graph[ver]) {
      if (color[e] == c || (color[e] == -1 && !dfs(e, c ^ 1))) return false;
    }
    return true;
  };
  for (int i = 0; i < n; ++i) {
    if (color[i] == -1 && !dfs(i, 0)) return false;
  }
  return true;
}

template <int D>
struct Basis {
  std::vector<std::bitset<D>> v;
  std::vector<int> msb;

  bool add(std::bitset<D> val) {
    int n = v.size();
    if (n == D) return false;
    for (int i = 0; i < n; ++i) {
      if (val[msb[i]]) val ^= v[i];
    }
    if (val.none()) return false;
    int m = D - 1;
    while (!val[m]) --m;
    if (v.empty()) {
      v.emplace_back(val);
      msb.emplace_back(m);
      return true;
    }
    int idx = n - std::distance(msb.rbegin(), std::upper_bound(msb.rbegin(), msb.rend(), m));
    v.emplace(v.begin() + idx, val);
    msb.emplace(msb.begin() + idx, m);
    for (int i = idx + 1; i <= n; ++i) {
      if (v[idx][msb[i]]) v[idx] ^= v[i];
    }
    for (int i = idx - 1; i >= 0; --i) {
      if (v[i][m]) v[i] ^= v[idx];
    }
    return true;
  }

  int rank() const { return v.size(); }

  inline bool operator<(const Basis &x) const {
    int n = v.size();
    if (n != x.v.size()) return n < x.v.size();
    if (n == D) return false;
    for (int i = 0; i < n; ++i) {
      if (msb[i] != x.msb[i]) return msb[i] < x.msb[i];
    }
    for (int i = 0; i < n; ++i) {
      if (v[i] != x.v[i]) {
        for (int j = msb[i] - 1; ; --j) {
          if (v[i][j] != x.v[i][j]) return v[i][j] < x.v[i][j];
        }
      }
    }
    return false;
  }
};

template <int D>
ll max(const Basis<D> &basis, ll initialized = 0) {
  ll ans = initialized;
  REP(i, basis.rank()) chmax(ans, ans ^ basis.v[i].to_ullong());
  return ans;
}

// https://twitter.com/noshi91/status/1316770805808721920
// https://twitter.com/noshi91/status/1442031151216926727
// https://twitter.com/nok0_kyopro/status/1442022824059674633
int main() {
  constexpr int D = 60;
  int n, m, q; cin >> n >> m >> q;
  vector<ll> c(n); REP(i, n) cin >> c[i];
  vector<vector<int>> graph(n);
  while (m--) {
    int a, b; cin >> a >> b; --a; --b;
    graph[a].emplace_back(b);
    graph[b].emplace_back(a);
  }
  vector<int> color;
  if (is_bipartite(graph, color)) {
    ll ans[2]{};
    Basis<D + 1> basis;
    REP(i, n) basis.add(c[i] | (1LL << D));
    ans[0] = max(basis) ^ (1LL << D);
    ans[1] = max(basis, 1LL << D) ^ (1LL << D);
    while (q--) {
      int s, g; cin >> s >> g; --s; --g;
      cout << ans[color[s] ^ color[g]] << '\n';
    }
  } else {
    Basis<D> basis;
    REP(i, n) basis.add(c[i]);
    ll ans = max(basis);
    while (q--) cout << ans << '\n';
  }
  return 0;
}
accuracy: 1
time_ms: 100
memory_kb: 16592
final_rank: 6

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

using namespace std;

// using mint = long double;
// using mint = atcoder::modint998244353;
// using mint = atcoder::modint1000000007;

typedef long long ll;
typedef pair<ll, ll> P;
typedef pair<ll, P> T;
typedef pair<ll, vector<ll>> Pd;

const ll INF = 3e18;
const ll fact_table = 8000050;

/*
priority_queue<ll> pql;
priority_queue<P> pqp;
// big priority queue
// priority_queue<ll, vector<ll>, greater<ll>> pqls;
priority_queue<P, vector<P>, greater<P>> pqps;
// small priority queue
// top pop
*/

ll dx[8] = {1, 0, -1, 0, 1, 1, -1, -1};
ll dy[8] = {0, 1, 0, -1, -1, 1, 1, -1};

//↓,→,↑,←

#define p(x) cout << x << "\n";
#define el cout << "\n";
#define pe(x) cout << x << " ";
#define ps(x) cout << fixed << setprecision(25) << x << endl;
#define pu(x) cout << (x);
#define pb push_back
#define eb emplace_back
#define lb lower_bound
#define ub upper_bound
#define rep(i, n) for (ll i = 0; i < (n); i++)
#define rep2(i, a, b) for (ll i = a; i <= (b); i++)
#define rep3(i, a, b) for (ll i = a; i >= (b); i--)
#define all(c) begin(c), end(c)
#define sorti(v) sort(all(v))
#define sortd(v)                                                               \
    sort(all(v));                                                              \
    reverse(all(v));
#define SUM(v) accumulate(all(v), 0LL)
#define MIN(v) *min_element(all(v))
#define MAX(v) *max_element(all(v))

typedef vector<ll> vec;
typedef vector<vector<ll>> mat;

// vec v(n) -> 長さnのベクトルを宣言
// mat dp(h, vec(w)) -> h * w の行列を宣言

// const ll mod = 1000000007ll;
const ll mod = 998244353ll;

ll mypow(ll a, ll b, ll m = mod) {
    ll x = 1;
    while (b) {
        while (!(b & 1)) {
            (a *= a) %= m;
            b >>= 1;
        }
        (x *= a) %= m;
        b--;
    }
    return x;
}
vec rv(ll read) {
    vec res(read);
    for (int i = 0; i < read; i++) {
        cin >> res[i];
    }
    return res;
}

vec fact, rfact;

void c3_init() {
    fact.resize(fact_table + 5);
    rfact.resize(fact_table + 5);
    fact[0] = rfact[0] = 1;
    for (ll i = 1; i <= fact_table; i++) {
        fact[i] = (fact[i - 1] * i) % mod;
    }
    rfact[fact_table] = mypow(fact[fact_table], mod - 2, mod);
    for (ll i = fact_table; i >= 1; i--) {
        rfact[i - 1] = rfact[i] * i;
        rfact[i - 1] %= mod;
    }
    return;
}

ll c3(ll n, ll r) {
    if (n < r) return 0ll;
    return fact[n] * rfact[r] % mod * rfact[n - r] % mod;
}

bool icpc = false;
bool multicase = false;

// 配列の長さ足りてますか？
ll n, m, q;
ll a, b;
ll ans0, ans1;

vec c;

ll calcxor(vector<ll> &v, int odd) {
    vector<ll> bs; // base
    int i, n = v.size();
    for (i = 0; i < n; i++) {
        ll sum = v[i] + (1LL << 60);
        for (ll x : bs)
            sum = min(sum, sum ^ x);
        if (sum != 0) bs.push_back(sum);
    }
    ll ans = 0;
    if (odd == 1) ans = bs[0];
    for (i = 1; i < bs.size(); i++)
        ans = max(ans, ans ^ bs[i]);
    return ans;
}

void calc(bool bipar, bool same) {
    if (n == 2) {
        p(max(c[0] ^ c[1], 0ll));
        return;
    }

    if (bipar) {
        if (same) {
            p(ans1);
        } else {
            p(ans0);
        }
    } else {
        p(max(ans0, ans1));
    }
    return;
}

ll parent[500005], sizes[500005];
void init(ll n) {
    for (ll i = 0; i <= n; i++) {
        parent[i] = i;
    }
}
ll find(ll x) {
    if (parent[x] == x) {
        return x;
    } else {
        return parent[x] = find(parent[x]);
    }
}
void unite(ll x, ll y) {
    x = find(x);
    y = find(y);
    if (x == y) return;
    if (sizes[x] < sizes[y]) swap(x, y);
    parent[y] = x;
    sizes[x] += sizes[y];
}
bool same(ll x, ll y) {
    return find(x) == find(y);
}
ll size(ll x) {
    return sizes[find(x)];
}

bool solve() {
    cin >> n >> m >> q;
    c.resize(n);
    rep(i, n) {
        cin >> c[i];
    }
    init(n * 2 + 10);
    rep(i, m) {
        cin >> a >> b;
        a--;
        b--;
        unite(a * 2, b * 2 + 1);
        unite(a * 2 + 1, b * 2);
    }

    bool bipar = true;
    rep(i, n) {
        if (same(i * 2, i * 2 + 1)) bipar = false;
    }

    ans0 = calcxor(c, 0);
    ans1 = calcxor(c, 1) - (1ll << 60);

    rep(i, q) {
        int s, t;
        cin >> s >> t;
        s--;
        t--;
        calc(bipar, same(2 * s, 2 * t));
    }
    return true;
}

/*







*/

int main() {

    // ios::sync_with_stdio(false);
    // cin.tie(nullptr);

    if (icpc) {
        while (solve())
            ;
        return 0;
    }
    ll q, testcase = 1;
    if (multicase) {
        cin >> q;
    } else {
        q = 1;
    }
    while (q--) {
        // cout << "Case #" << testcase << ": ";
        solve();
        testcase++;
    }

    // solve();
    return 0;
}
accuracy: 1
time_ms: 240
memory_kb: 9592
final_rank: 4

code_snippet: #define _USE_MATH_DEFINES
#include <bits/stdc++.h>
using namespace std;
#define FOR(i,m,n) for(int i=(m);i<(n);++i)
#define REP(i,n) FOR(i,0,n)
#define ALL(v) (v).begin(),(v).end()
using ll = long long;
constexpr int INF = 0x3f3f3f3f;
constexpr long long LINF = 0x3f3f3f3f3f3f3f3fLL;
constexpr double EPS = 1e-8;
constexpr int MOD = 1000000007;
// constexpr int MOD = 998244353;
constexpr int DY[]{1, 0, -1, 0}, DX[]{0, -1, 0, 1};
constexpr int DY8[]{1, 1, 0, -1, -1, -1, 0, 1}, DX8[]{0, -1, -1, -1, 0, 1, 1, 1};
template <typename T, typename U> inline bool chmax(T &a, U b) { return a < b ? (a = b, true) : false; }
template <typename T, typename U> inline bool chmin(T &a, U b) { return a > b ? (a = b, true) : false; }
struct IOSetup {
  IOSetup() {
    std::cin.tie(nullptr);
    std::ios_base::sync_with_stdio(false);
    std::cout << fixed << setprecision(20);
  }
} iosetup;

bool is_bipartite(const std::vector<std::vector<int>> &graph, std::vector<int> &color) {
  const int n = graph.size();
  color.assign(n, -1);
  std::function<bool(int, int)> dfs = [&graph, &color, &dfs](const int ver, const int c) -> bool {
    color[ver] = c;
    for (const int e : graph[ver]) {
      if (color[e] == c || (color[e] == -1 && !dfs(e, c ^ 1))) return false;
    }
    return true;
  };
  for (int i = 0; i < n; ++i) {
    if (color[i] == -1 && !dfs(i, 0)) return false;
  }
  return true;
}

template <int D>
struct Basis {
  std::vector<std::bitset<D>> v;
  std::vector<int> msb;

  bool add(std::bitset<D> val) {
    int n = v.size();
    if (n == D) return false;
    for (int i = 0; i < n; ++i) {
      if (val[msb[i]]) val ^= v[i];
    }
    if (val.none()) return false;
    int m = D - 1;
    while (!val[m]) --m;
    if (v.empty()) {
      v.emplace_back(val);
      msb.emplace_back(m);
      return true;
    }
    int idx = n - std::distance(msb.rbegin(), std::upper_bound(msb.rbegin(), msb.rend(), m));
    v.emplace(v.begin() + idx, val);
    msb.emplace(msb.begin() + idx, m);
    for (int i = idx + 1; i <= n; ++i) {
      if (v[idx][msb[i]]) v[idx] ^= v[i];
    }
    for (int i = idx - 1; i >= 0; --i) {
      if (v[i][m]) v[i] ^= v[idx];
    }
    return true;
  }

  int rank() const { return v.size(); }

  inline bool operator<(const Basis &x) const {
    int n = v.size();
    if (n != x.v.size()) return n < x.v.size();
    if (n == D) return false;
    for (int i = 0; i < n; ++i) {
      if (msb[i] != x.msb[i]) return msb[i] < x.msb[i];
    }
    for (int i = 0; i < n; ++i) {
      if (v[i] != x.v[i]) {
        for (int j = msb[i] - 1; ; --j) {
          if (v[i][j] != x.v[i][j]) return v[i][j] < x.v[i][j];
        }
      }
    }
    return false;
  }
};

template <int D>
ll max(const Basis<D> &basis) {
  ll ans = 0;
  REP(i, basis.rank()) {
    if (ans >> basis.msb[i] & 1) continue;
    ans |= basis.v[i].to_ullong();
  }
  return ans;
}

// https://twitter.com/noshi91/status/1316770805808721920
// https://twitter.com/nok0_kyopro/status/1442022824059674633
int main() {
  constexpr int D = 60;
  int n, m, q; cin >> n >> m >> q;
  vector<ll> c(n); REP(i, n) cin >> c[i];
  vector<vector<int>> graph(n);
  while (m--) {
    int a, b; cin >> a >> b; --a; --b;
    graph[a].emplace_back(b);
    graph[b].emplace_back(a);
  }
  vector<int> color;
  if (is_bipartite(graph, color)) {
    ll ans[2]{};
    {
      Basis<D + 1> basis;
      REP(i, n) basis.add(c[i] | (1LL << D));
      ans[0] = max(basis) ^ (1LL << D);
    }
    {
      Basis<D> basis;
      REP(i, n) basis.add(c[i] ^ c[(i + 1) % n]);
      ans[1] = max(basis);
    }
    while (q--) {
      int s, g; cin >> s >> g; --s; --g;
      cout << ans[color[s] ^ color[g]] << '\n';
    }
  } else {
    Basis<D> basis;
    REP(i, n) basis.add(c[i]);
    ll ans = 0;
    REP(i, basis.rank()) {
      if (ans >> basis.msb[i] & 1) continue;
      ans |= basis.v[i].to_ullong();
    }
    while (q--) cout << ans << '\n';
  }
  return 0;
}
accuracy: 0.3076923076923077
time_ms: 40
memory_kb: 8616
final_rank: 18

code_snippet: #include <bits/stdc++.h>
using namespace std;
typedef long long int ll;
int main(void){
    int N,M,Q;
    cin>>N>>M>>Q;
    vector<ll> C(N);
    for(int i=0;i<N;i++){
        cin>>C[i];
    }
    vector<vector<int>> G(N);
    for(int i=0;i<M;i++){
        int a,b;
        cin>>a>>b;
        a--;b--;
        G[a].push_back(b);
        G[b].push_back(a);
    }
    vector<int> dist(N,-1);
    vector<ll> cost(N,-1);
    queue<int> q;
    q.push(0);
    vector<ll> base;
    dist[0]=0;
    cost[0]=C[0];
    while(!q.empty()){
        int r=q.front();q.pop();
        for(int p:G[r]){
            if(dist[p]==-1){
                dist[p]=dist[r]^1;
                cost[p]=cost[r]^C[p];
                q.push(p);
            }
        }
    }
    bool flag=true;
    for(int i=0;i<N;i++){
        for(int j:G[i]){
            if (dist[i]==dist[j]){
                flag=false;
                break;
            }
        }
    }
    if (flag){
        for(int a=0;a<N;a++){
            for(int b:G[a]){
                ll x=C[a]^C[b];
                for(ll y:base){
                    x=min(x,y^x);
                }
                if (x!=0){
                    base.push_back(x);
                }
            }
        }
    }
    else{
        for(int a=0;a<N;a++){
            ll x=C[a];
            for(ll y:base){
                x=min(x,y^x);
            }
            if (x!=0){
                base.push_back(x);
            }
        }
    }
    
    sort(base.begin(),base.end(),greater<ll>());
    while(Q--){
        int s,g;
        cin>>s>>g;
        s--;g--;
        ll x=cost[s]^cost[g]^C[0];
        ll ans=x;
        for(ll y:base){
            ans=max(ans,ans^y);
        }
        cout<<ans<<endl;
    }
}
accuracy: 1
time_ms: 280
memory_kb: 13116
final_rank: 8