1 条题解
-
0
自动搬运
来自洛谷,原作者为

Miko35
阿玮你又在打电动喔,去看会书好不好搬运于
2025-08-24 22:30:28,当前版本为作者最后更新于2021-04-07 11:49:54,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
验题人来水一水题解。
异或,比大小,很容易想到 Trie 树。但是这题插入的是二元组,很难用普通的 01trie 进行维护。
既然是二元组,有一个初步的想法是,将 Trie 开成四叉的,其中令 表示:节点 内的二元组 中, 二进制下一位为 , 二进制下一位为 的二元组集合。也就是说,插入的向量的第 位是 取第 位形成的二元组。
比如从高到低插入插入二元组 :

这样就可以像 01trie 一样实现异或比大小,也就是:将 的节点计入答案,然后分别递归 的点。
显然这样不是很对,因为每一层要递归两个节点,一次操作总共涉及的节点数到了 级别。
观察可知,一个点能被递归下去,当且仅当在这一位 ,而这个可以写成 ,左边只跟 有关。这样插入时只需要保留两个儿子:下一位 和 的,查询时只需要根据 的取值决定往哪边走即可。
依然要在每个节点处记录下一位 的二元组个数,这样才可以在递归时统计答案。
良心题,代码真心不长。
#include<bits/stdc++.h> #define g(a) ((a)>>d&1) long long x,y; int m,o,c,S[1<<23][2][2],r,h[1<<23][2]; void s(int& r,int d){ if(~d)S[r?r:r=++c][g(x)][g(y)]+=3-o*2,s(h[r][g(x^y)],d-1); } int q(int r,int d){ return r&&~d?S[r][!g(x)][g(y)]+q(h[r][g(x^y)],d-1):0; } int main(){ std::cin>>m; while(m--)std::cin>>o>>x>>y,o^3?s(r,60):void(printf("%d\n",q(r,60))); }
- 1
信息
- ID
- 5242
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 5
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者