随便说点
今天代码源大放水就出了个lcalcalca+前缀和板子题,可惜lcalcalca板子记错了,wawawa了好久。
题意
有一棵树,上面有很多个节点,每个节点都有一个对应的权值,现在有qqq次询问,问任意两点之间简单路径的权值亦或和。
题解
其实很简单,先dfsdfsdfs求前缀和,然后将询问的两点的前缀和亦或因为根节点到公共祖先的权值会被亦或两次而抵消所以我们只要再找一个公共祖先就行了。lcalcalca找到两点公共祖先,亦或上公共祖先的权值直接ACACAC。(直接ACACAC的前提是你没记错lcalcalca的板子)
const int N=2e5+10;
vector<vector<int>> g;
int f[N][30],d[N],a[N],w[N],n,m;
void dfs(int fa,int x){
w[x]=a[x]^w[fa];
f[x][0]=fa;d[x]=d[fa]+1;
for(int i=1;i<=25;i++) f[x][i]=f[f[x][i-1]][i-1];
for(auto v:g[x]){if(v==fa) continue;dfs(x,v);}
return ;
}
int lca(int x,int y){
for(int i=25;i>=0;i--) if(d[f[x][i]]>=d[y]) x=f[x][i];
for(int i=25;i>=0;i--) if(d[f[y][i]]>=d[x]) y=f[y][i];
if(x==y) return x;
for(int i=25;i>=0;i--) if(f[x][i]!=f[y][i]) x=f[x][i],y=f[y][i];
return f[x][0];
}
void MAIN(){
cin>>n>>m;
g.resize(n+1);
for(int i=1;i<=n;i++) cin>>a[i];
for(int i=1,u,v;i<n&&cin>>u>>v;i++) g[u].push_back(v),g[v].push_back(u);
dfs(0,1);
int x,y;
while(cin>>x>>y){
int anc=lca(x,y);
cout<<(w[x]^w[y]^a[anc])<<endl;
}
return ;
}