1. 程式人生 > >洛谷 2420 讓我們異或吧

洛谷 2420 讓我們異或吧

【題解】

  樹鏈剖分+線段樹的模板題。每個點的點權是它父親到它的邊的邊權,這樣我們就完成了把邊權變為點權的操作,之後直接樹剖即可。

  注意回答詢問的時候要把lca(x,y)去掉,因為x到y的鏈上並不包含lca(x,y)到它的父親的邊。

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 #define LL long long
 5 #define rg register
 6 #define N 100010
 7 #define ls (u<<1)
 8
#define rs (u<<1|1) 9 #define mid ((a[u].l+a[u].r)>>1) 10 using namespace std; 11 int n,m,cnt,tot,last[N],siz[N],dep[N],hvy[N],top[N],val[N],pos[N],dfn[N],fa[N]; 12 struct edge{int to,pre,w;}e[N<<1]; 13 struct tree{int l,r,xr;}a[N<<2]; 14 inline int read(){ 15 int k=0,f=1
; char c=getchar(); 16 while(c<'0'||c>'9')c=='-'&&(f=-1),c=getchar(); 17 while('0'<=c&&c<='9')k=k*10+c-'0',c=getchar(); 18 return k*f; 19 } 20 void dfs(int x){ 21 siz[x]=1; 22 for(rg int i=last[x],to;i;i=e[i].pre)if((to=e[i].to)!=fa[x]){ 23 fa[to]=x; dep[to]=dep[x]+1
; val[to]=e[i].w; dfs(to); 24 siz[x]+=siz[to]; if(siz[to]>siz[hvy[x]]) hvy[x]=to; 25 } 26 } 27 void dfs2(int x,int tp){ 28 top[x]=tp; dfn[x]=++cnt; pos[cnt]=x; 29 if(hvy[x]) dfs2(hvy[x],tp); 30 for(rg int i=last[x],to;i;i=e[i].pre) 31 if((to=e[i].to)!=fa[x]&&to!=hvy[x]) dfs2(to,to); 32 } 33 void build(int u,int l,int r){ 34 a[u].l=l; a[u].r=r; 35 if(l<r) build(ls,l,mid),build(rs,mid+1,r),a[u].xr=a[ls].xr^a[rs].xr; 36 else a[u].xr=val[pos[l]]; 37 } 38 int query(int u,int l,int r){ 39 if(l<=a[u].l&&a[u].r<=r) return a[u].xr; 40 int ret=0; 41 if(l<=mid) ret^=query(ls,l,r); 42 if(r>mid) ret^=query(rs,l,r); 43 return ret; 44 } 45 int main(){ 46 n=read(); 47 for(rg int i=1;i<n;i++){ 48 int u=read(),v=read(),w=read(); 49 e[++tot]=(edge){v,last[u],w}; last[u]=tot; 50 e[++tot]=(edge){u,last[v],w}; last[v]=tot; 51 } 52 dfs(1); dfs2(1,1); build(1,1,n); 53 m=read(); 54 while(m--){ 55 int x=read(),y=read(),ans=0; 56 while(top[x]!=top[y]){ 57 if(dep[top[x]]<dep[top[y]]) swap(x,y); 58 ans^=query(1,dfn[top[x]],dfn[x]); x=fa[top[x]]; 59 } 60 if(dep[x]<dep[y]) swap(x,y); 61 ans^=query(1,dfn[y],dfn[x]); 62 printf("%d\n",ans^val[y]); 63 } 64 return 0; 65 }