传送门:点击打开链接
题意:给你一棵树,然后Q个问题,每个问题询问有存在多少个f(u,v)等于s其中u<=v,f(u,v)表示节点u到节点v所有边的权值异或和
思路:这道题我觉得出的非常好,运用了位异或的一些妙用。f(u,v)=f(1,u)^f(1,v),因为假设u,v的lca是p,那么1~p这些节点都是公用的,这部分被异或了两次,就抵消了
然后对于Q次问题,假设某一次问题是s,则有s=f(u,v)=f(1,u)^f(1,v)。那么有f(1,v)=s^f(1,u),也就是说,如果我们DFS到节点u,算出了f(1,v),那么对于某一个s,我们就需要算出f(1,v)等于多少,然后再通过cnt数组知道f(1,v)有多少个,把这个值累加到s这个查询的答案中去,就这样DFS遍历完整个树,答案就离线处理完了。复杂度O(Q*N)
trick:当出现下面这种数据的时候
1
10
1 2 0
2 3 0
3 4 0
4 5 0
5 6 0
6 7 0
7 8 0
8 9 0
1
0
可以看出来,答案会等于n(n-1)/2,因为n最大是1e5,所以结果可能会爆int,要用long long保存
#include<map>
#include<set