[SCOI2016]幸运数字

\(\text{Solution}\)

很显然的暴力就是把路径上的数抽出来弄个线性基求答案
再优化一下就是用倍增的方式把数抽出来
倍增时涉及两个线性基合并,然后就是 \(O(3600q\log n)\)
竟没想到它可以过

\(\text{Code}\)

#include <cstdio>
#include <iostream>
#define RE register
#define IN inline
using namespace std;
typedef long long LL;

const int N = 20005;
int n, q, fa[N][16], h[N], tot, dep[N];
LL a[N];
struct edge{int to, nxt;}e[N << 1];
IN void add(int x, int y){e[++tot] = edge{y, h[x]}, h[x] = tot;}

struct node{
	LL p[61];
	IN node(){for(RE int i = 0; i < 61; i++) p[i] = 0;}
}f[N][16];
IN void Insert(node &a, LL x)
{
	for(RE int i = 60; i >= 0; i--)
		if ((x >> i) & 1)
		{
			if (!a.p[i]){a.p[i] = x; return;}
			x ^= a.p[i];
		}
}
IN void Merge(node &a, node b)
{
	for(RE int i = 60; i >= 0; i--)
		if (b.p[i]) Insert(a, b.p[i]);
}

void dfs(int x, int dad)
{
	for(RE int i = 1; i <= 15; i++)
	if (fa[x][i - 1]) fa[x][i] = fa[fa[x][i - 1]][i - 1],
		Merge(f[x][i], f[x][i - 1]), Merge(f[x][i], f[fa[x][i - 1]][i - 1]);
	else break;
	for(RE int i = h[x]; i; i = e[i].nxt)
	{
		int v = e[i].to;
		if (v == dad) continue;
		Insert(f[v][0], a[v]), fa[v][0] = x, dep[v] = dep[x] + 1;
		dfs(v, x);
	}
}
IN node Query(int u, int v)
{
	node tmp;
	if (dep[u] < dep[v]) swap(u, v);
	int deep = dep[u] - dep[v];
	for(RE int i = 15; i >= 0; i--)
		if ((deep >> i) & 1) Merge(tmp, f[u][i]), u = fa[u][i];
	if (u == v){Insert(tmp, a[u]); return tmp;}
	for(RE int i = 15; i >= 0; i--)
	if (fa[u][i] ^ fa[v][i])
		Merge(tmp, f[u][i]), Merge(tmp, f[v][i]), u = fa[u][i], v = fa[v][i];
	Insert(tmp, a[u]), Insert(tmp, a[v]), Insert(tmp, a[fa[u][0]]);
	return tmp;
}

IN void read(int &x)
{
	x = 0; char ch = getchar();
	for(; !isdigit(ch); ch = getchar());
	for(; isdigit(ch); x = (x<<3)+(x<<1)+(ch^48), ch = getchar());
}
IN void readLL(LL &x)
{
	x = 0; char ch = getchar();
	for(; !isdigit(ch); ch = getchar());
	for(; isdigit(ch); x = (x<<3)+(x<<1)+(ch^48), ch = getchar());
}

int main()
{
	read(n), read(q);
	for(RE int i = 1; i <= n; i++) readLL(a[i]);
	for(RE int i = 1, u, v; i < n; i++) read(u), read(v), add(u, v), add(v, u);
	dfs(1, 0); node tmp; LL ans;
	for(RE int u, v; q; --q)
	{
		read(u), read(v), tmp = Query(u, v), ans = 0;
		for(RE int i = 60; i >= 0; i--) ans = max(ans, ans ^ tmp.p[i]);
		printf("%lld\n", ans);
	}
}
posted @ 2022-01-03 11:59  leiyuanze  阅读(57)  评论(0)    收藏  举报