题目链接
题意
求树上路径最大点权异或和
自然想到(维护树上路径)+ (维护最大异或和)
那么有三种方法可以选择
1.树剖+线性基
2.倍增+线性基
3.点分治+线性基
至于线性基的合并
一共就是long级的
暴力合并就好啦
这是一份在loj T掉在洛谷AC的可怜代码
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <vector>
using namespace std;
const int N = 2e4 + 2;
const int LIM = 60;
inline int read()
{
int x=0;bool t=false;char ch=getchar();
while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
if(ch=='-')t=true,ch=getchar();
while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
return t?-x:x;
}
struct Edge{
int v, next;
}edge[N << 1];
int esize, head[N];
inline void addedge(int x, int y){
edge[++esize] = (Edge){y, head[x]};
head[x] = esize;
}
struct XXJ{
long long w[LIM + 2];
XXJ(){
memset(w, 0, sizeof(w));
}
void ins(long long x){
for(int i = LIM; ~i; --i){
if(!(x >> i)) continue;
else if(!w[i]){w[i] = x; break;}
x ^= w[i];
}
}
void print(){
long long res = 0;
for(int i = LIM; ~i; --i)
if((res ^ w[i]) > res) res ^= w[i];
printf("%lld
", res);
}
}px[N][18];
long long w[N];
int p[N][18], dep[N];
int n, m;
XXJ merge(XXJ x, XXJ y){
for(int i = LIM; i >= 0; --i){
if(y.w[i]) x.ins(y.w[i]);
}
return x;
}
XXJ LCA(int x, int y){
XXJ res;
res.ins(w[x]); res.ins(w[y]);
if(dep[x] < dep[y]) swap(x, y);
for(int i = 15; i >= 0; --i)
if(dep[x] - (1 << i) >= dep[y]){
res = merge(res, px[x][i]);
x = p[x][i];
}
if(x == y) return res;
for(int i = 15; i >= 0; --i){
if(p[x][i] != p[y][i]){
res = merge(res, px[x][i]);
res = merge(res, px[y][i]);
x = p[x][i], y = p[y][i];
}
}
res = merge(res, px[x][0]);
return res;
}
void dfs(int x, int ff){
dep[x] = dep[ff] + 1;
p[x][0] = ff;
px[x][0].ins(w[ff]);
for(int i = head[x], vv; ~i; i = edge[i].next){
vv = edge[i].v; if(vv == ff) continue;
dfs(vv, x);
}
}
void calc(){
for(int i = 1; i <= 15; ++i){
for(int j = 1; j <= n; ++j){
p[j][i] = p[p[j][i - 1]][i - 1];
px[j][i] = merge(px[j][i - 1], px[p[j][i - 1]][i - 1]);
}
}
}
int main() {
memset(head, -1, sizeof(head));
scanf("%d%d", &n, &m);
for(int i = 1; i <= n; ++i){
scanf("%lld", &w[i]);
}
for(int i = 1, x, y; i < n; ++i){
scanf("%d%d", &x, &y);
addedge(x, y); addedge(y, x);
}
dfs(1, 0);
calc();
for(int i = 1, x, y; i <= m; ++i){
x = read(), y = read();
XXJ res = LCA(x, y);
res.print();
}
return 0;
}