Description
A 国共有 n 座城市,这些城市由 n-1 条道路相连,使得任意两座城市可以互达,且路径唯一。每座城市都有一个
幸运数字,以纪念碑的形式矗立在这座城市的正中心,作为城市的象征。一些旅行者希望游览 A 国。旅行者计划
乘飞机降落在 x 号城市,沿着 x 号城市到 y 号城市之间那条唯一的路径游览,最终从 y 城市起飞离开 A 国。
在经过每一座城市时,游览者就会有机会与这座城市的幸运数字拍照,从而将这份幸运保存到自己身上。然而,幸
运是不能简单叠加的,这一点游览者也十分清楚。他们迷信着幸运数字是以异或的方式保留在自己身上的。例如,
游览者拍了 3 张照片,幸运值分别是 5,7,11,那么最终保留在自己身上的幸运值就是 9(5 xor 7 xor 11)。
有些聪明的游览者发现,只要选择性地进行拍照,便能获得更大的幸运值。例如在上述三个幸运值中,只选择 5
和 11 ,可以保留的幸运值为 14 。现在,一些游览者找到了聪明的你,希望你帮他们计算出在他们的行程安排中
可以保留的最大幸运值是多少。
N<=20000,Q<=200000,Gi<=2^60
Solution
异或最大值,考虑用线性基做。
直接倍增,rec[x][i]表示x向上2^i个组成的线性基,倍增的时候合并线性基就可以了
合并线性基就是把一个线性基中的元素插入另一个里面
Code
#include <stdio.h>
#include <string.h>
#include <algorithm>
#define rep(i,st,ed) for (int i=st;i<=ed;++i)
#define drp(i,st,ed) for (int i=st;i>=ed;--i)
#define fill(x,t) memset(x,t,sizeof(x))
typedef long long LL;
const int N=20005;
struct edge {int y,next;} e[N*2];
struct Bin {
LL r[61];
bool ins(LL x) {
drp(i,60,0) if (x&(1LL<<i)) {
if (r[i]) x^=r[i];
else {r[i]=x; return true;}
}
return x==0;
}
LL get_max() {
LL ret=0;
drp(i,60,0) if ((ret^r[i])>ret) {
ret^=r[i];
}
return ret;
}
void merge(Bin b) {
rep(i,0,60) if (b.r[i]) {
ins(b.r[i]);
}
}
void init() {
fill(r,0);
}
} rec[N][15];
int dep[N],fa[N][15];
int ls[N],edCnt;
LL v[N];
void add_edge(int x,int y) {
e[++edCnt]=(edge) {y,ls[x]}; ls[x]=edCnt;
e[++edCnt]=(edge) {x,ls[y]}; ls[y]=edCnt;
}
void dfs(int now) {
rep(i,1,14) {
fa[now][i]=fa[fa[now][i-1]][i-1];
rec[now][i]=rec[now][i-1];
rec[now][i].merge(rec[fa[now][i-1]][i-1]);
}
for (int i=ls[now];i;i=e[i].next) {
if (e[i].y==fa[now][0]) continue;
fa[e[i].y][0]=now; dep[e[i].y]=dep[now]+1;
rec[e[i].y][0].ins(v[now]);
dfs(e[i].y);
}
}
int get_lca(int x,int y) {
if (dep[x]<dep[y]) std:: swap(x,y);
drp(i,14,0) if (dep[fa[x][i]]>=dep[y]) x=fa[x][i];
if (x==y) return x;
drp(i,14,0) if (fa[x][i]!=fa[y][i]) x=fa[x][i],y=fa[y][i];
return fa[x][0];
}
int main(void) {
int n,q; scanf("%d%d",&n,&q); Bin S;
rep(i,1,n) scanf("%lld",&v[i]);
rep(i,2,n) {
int x,y; scanf("%d%d",&x,&y);
add_edge(x,y);
}
for (dfs(dep[1]=1);q--;) {
int x,y; scanf("%d%d",&x,&y);
int lca=get_lca(x,y);
S.init(); S.ins(v[x]); S.ins(v[y]);
drp(i,14,0) if (dep[fa[x][i]]>=dep[lca]) {
S.merge(rec[x][i]); x=fa[x][i];
}
drp(i,14,0) if (dep[fa[y][i]]>=dep[lca]) {
S.merge(rec[y][i]); y=fa[y][i];
}
printf("%lld\n", S.get_max());
}
return 0;
}