XORTREE(统计树上奇数位路径异或)
题:https://ac.nowcoder.com/acm/problem/200191
题意:给定一棵树,操作一:把u变为x,操作二统计u~v的最短路径中的各子路径的节点的异或和的异或和。1<=n,q<=1e5
分析:考虑一个节点要么被异或到,要么不被异或到,只与被路径选中次数的奇偶有关。
假设节点从u到v遍历,走过的路径长为x,总路径长为len,那么当前节点被选到的次数就为:x*(len-x)+x+(len-x)=x*(len-x)+len;
我们发现,当路径长len为奇数的时候,结果肯定为奇数,也就意味着这次询问是询问u~v的节点的异或和;
当路径长len为偶数的时候,结果是偶奇偶奇。。。地交替,也就意味着这次询问是询问u~v的节点的偶数位的异或和。
那么可以根据深度的奇偶来判断路径即可,用长链剖分+BIT解决区间异或

#include<bits/stdc++.h> using namespace std; #define pb push_back int read() { int x=0; char c=getchar(); while(c<'0'||c>'9') c=getchar(); while(c>='0'&&c<='9') x=(x<<1)+(x<<3)+c-'0',c=getchar(); return x; } const int M=2e5+4; int fa[M],sz[M],deep[M],ans[M],dfn[M],tp[M],son[M],a[M],las[M]; int cnt,n,q; vector<int>g[M]; struct BIT{ int tr[3][M]; void init(){ memset(tr,0,sizeof(tr)); } void update(int id,int i,int x){ while(i<=n) tr[id][i]^=x,i+=i&(-i); } int sum(int id,int i){ int res=0; while(i){ res^=tr[id][i]; i-=i&(-i); } return res; } }t1; void dfs1(int u,int f){ fa[u]=f,sz[u]=1,deep[u]=deep[f]+1; for(auto v:g[u]){ if(v!=f){ dfs1(v,u); sz[u]+=sz[v]; if(sz[son[u]]<sz[v]) son[u]=v; } } } void dfs2(int u,int top){ tp[u]=top; dfn[u]=++cnt; if(son[u]) dfs2(son[u],top); for(auto v:g[u]){ if(v!=fa[u]&&v!=son[u]) dfs2(v,v); } } int solve(int u,int v){ int res=0; ///路径长为奇数就,奇数位选,否则,全部选 int id=( (deep[u]%2==deep[v]%2) ? (1-deep[u]%2) : 2); while(tp[u]!=tp[v]){ if(deep[tp[u]]<deep[tp[v]]) swap(u,v); res^=(t1.sum(id,dfn[u])^t1.sum(id,dfn[tp[u]]-1)); u=fa[tp[u]]; } if(deep[u]<deep[v]) swap(u,v); res^=(t1.sum(id,dfn[u])^t1.sum(id,dfn[v]-1)); return res; } int main(){ t1.init(); n=read(),q=read(); for(int i=1;i<=n;i++) a[i]=read(); for(int u,v,i=1;i<n;i++){ u=read(),v=read(); g[u].pb(v),g[v].pb(u); } dfs1(1,0),dfs2(1,1); for(int i=1;i<=n;i++){ t1.update(deep[i]%2,dfn[i],a[i]); t1.update(2,dfn[i],a[i]); las[dfn[i]]=a[i]; } while(q--){ int op=read(),u=read(),v=read(); if(op==1){ t1.update(deep[u]%2,dfn[u],las[dfn[u]]^v); t1.update(2,dfn[u],las[dfn[u]]^v); las[dfn[u]]=v; } else{ printf("%d\n",solve(u,v)); } } return 0; }