P2420 解题报告 BY LPC
首先我们得明确,异或运算的逆运算就是本身。于是乎,我们得到
x^y^y==x
我们定义树根为1,sum[i][j]为从节点i到节点j的路径(因为是树,所以路径唯一)上所有边权的异或值。那么对于询问x,y,其答案就应该为
sum[lca(x,y)][x]^sum[lca(x,y)][y]
将上式异或上两个sum[1][lca(x,y)],值不变,得到
sum[lca(x,y)]^sum[lca(x,y)][y]^sum[1][lca(x,y)]^sum[1][lca(x,y)]
因为异或有结合律,所以答案可以变为
(sum[lca(x,y)]^sum[1][lca(x,y)])^(sum[lca(x,y)][y]^sum[1][lca(x,y)])
很显然,若j是i的直系子孙,k是j的直系子孙,则
sum[i][j]^sum[j][k]==sum[i][k]
因为lca(x,y)一定是树根1的子孙,x,y一定是lca(x,y)的子孙,所以答案变成
sum[1][x]^sum[1][y]
所以只需要任选一个节点为根,令sum[根节点][根节点]为0,O(n)从根开始跑一遍DFS,处理出对于每一个节点i的sum[根节点][i],对于每一个询问O(1)作答即可。
AC代码(我选的根是1号节点):
#pragma GCC optimize(3)
#include<bits/stdc++.h>
using namespace std;
typedef long long ak;
#define im INT_MAX
#define F(i,j,k) for(int i=j;i<=k;i++)
#define G(i,j,k) for(int i=j;i>=k;i--)
vec