P4592 [TJOI2018] 异或

Sol

直接建立两颗可持久化线段树,一个维护以 dfn 为下标的数,这个是为了做子树异或,一个做根到当前点的,这个是为了做链上异或。

Code

#include <bits/stdc++.h>
#define x first
#define y second
#define pb push_back
#define pf push_front
#define desktop "C:\\Users\\incra\\Desktop\\"
#define IOS ios :: sync_with_stdio (false),cin.tie (0),cout.tie (0)
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
typedef pair <int,int> PII;
const int dx[] = {1,0,-1,0},dy[] = {0,-1,0,1};
template <typename T1,typename T2> bool tomax (T1 &x,T2 y) {
	if (y > x) return x = y,true;
	return false;
}
template <typename T1,typename T2> bool tomin (T1 &x,T2 y) {
	if (y < x) return x = y,true;
	return false;
}
LL power (LL a,LL b,LL p) {
	LL ans = 1;
	while (b) {
		if (b & 1) ans = ans * a % p;
		a = a * a % p;
		b >>= 1;
	}
	return ans;
}
int fastio = (IOS,0);
#define endl '\n'
#define puts(s) cout << (s) << endl
const int N = 100010,MAX_LOG = 20,M = 2 * 32 * N;
int n,q;
int a[N];
vector <int> g[N];
int rt1[N],rt2[N];
int tr[M][2],s[M],idx;
int dfn[N],last[N],timestamp;
int f[N][MAX_LOG];
int dep[N];
int clone (int u) {
	idx++;
	tr[idx][0] = tr[u][0];
	tr[idx][1] = tr[u][1];
	s[idx] = s[u];
	return idx;
}
void insert (int &u,int x,int i) {
	u = clone (u);
	s[u]++;
	if (~i) insert (tr[u][x >> i & 1],x,i - 1);
}
void DFS (int u,int fa) {
	dfn[u] = ++timestamp;
	dep[u] = dep[fa] + 1;
	insert (rt1[dfn[u]] = rt1[dfn[u] - 1],a[u],30);
	insert (rt2[u] = rt2[fa],a[u],30);
	for (int v : g[u]) {
		if (v == fa) continue;
		f[v][0] = u;
		for (int i = 1;i < MAX_LOG;i++) f[v][i] = f[f[v][i - 1]][i - 1];
		DFS (v,u);
	}
	last[u] = timestamp;
}
int get_LCA (int a,int b) {
	if (dep[a] < dep[b]) swap (a,b);
	for (int i = MAX_LOG - 1;i >= 0;i--) {
		if (dep[f[a][i]] >= dep[b]) a = f[a][i];
	}
	if (a == b) return a;
	for (int i = MAX_LOG - 1;i >= 0;i--) {
		if (f[a][i] == f[b][i]) continue;
		a = f[a][i],b = f[b][i];
	}
	return f[a][0];
}
int query (int u,int v,int x,int i) {
	if (i == -1) return 0;
	int t = x >> i & 1;
	if (s[tr[u][!t]] - s[tr[v][!t]]) return query (tr[u][!t],tr[v][!t],x,i - 1) + (1 << i);
	return query (tr[u][t],tr[v][t],x,i - 1);
}
void mian () {
	cin >> n >> q;
	for (int i = 1;i <= n;i++) cin >> a[i];
	for (int i = 1;i < n;i++) {
		int a,b;
		cin >> a >> b;
		g[a].pb (b),g[b].pb (a);
	}
	DFS (1,0);
	while (q--) {
		int op;
		cin >> op;
		if (op == 1) {
			int a,b;
			cin >> a >> b;
			cout << query (rt1[last[a]],rt1[dfn[a] - 1],b,30) << endl;
		}
		else {
			int a,b,c;
			cin >> a >> b >> c;
			int p = f[get_LCA (a,b)][0];
			cout << max (query (rt2[a],rt2[p],c,30),query (rt2[b],rt2[p],c,30)) << endl;
		}
	}
}
int main () {
	int T = 1;
	// cin >> T;
	while (T--) mian ();
	return 0;
}
posted @ 2025-05-02 10:03  incra  阅读(9)  评论(0)    收藏  举报