题解 P2420 【让我们异或吧】——适合幼儿园及以上理解水平

本文详细介绍了P2420题目的解题思路,重点讲解了利用异或运算是自身逆运算的性质,通过定义树根和路径异或值来求解问题。通过将路径异或值转化为节点间异或值,再利用异或的结合律简化计算,最终实现O(n)预处理与O(1)查询的时间复杂度。AC代码已给出。
摘要由CSDN通过智能技术生成

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
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值