题目描述:
给出 N 个数 M个询问 每次询问给出 L R X 三个参量 询问从L-R中的数字与X最大的异或值是多少
题目分析:
异或最大值问题应该是用 01 字典树来做 然后关于区间直接像主席树那样搞个可持久化就OK了
AC代码:
#include <cstdio>
#include <iostream>
#include <algorithm>
const int maxn
=210000,maxm
=210000*30;
int _div
[40],root
[maxn
],sz
;
int n
,m
,q
;
struct tree
{
int son
[maxm
][2],sum
[maxm
];
void insert(int num
,int &now
,int pre
)
{
now
=++sz
;
son
[now
][0]=son
[pre
][0];
son
[now
][1]=son
[pre
][1];
sum
[now
]=sum
[pre
]+1;
if(!num
) return;
insert(num
-1,son
[now
][_div
[num
-1]],son
[pre
][_div
[num
-1]]);
}
int ask(int num
,int now
,int pre
)
{
if(!num
) return 0;
if(sum
[son
[now
][_div
[num
-1]]]>sum
[son
[pre
][_div
[num
-1]]]) return ask(num
-1,son
[now
][_div
[num
-1]],son
[pre
][_div
[num
-1]])+(1<<(num
-1));
else return ask(num
-1,son
[now
][!_div
[num
-1]],son
[pre
][!_div
[num
-1]]);
}
}st
;
int main()
{
scanf("%d%d",&n
,&m
);
for(int i
=1,x
;i
<=n
;i
++)
{
scanf("%d",&x
);
for(int j
=0;j
<30;j
++,x
/=2) _div
[j
]=x
%2;
st
.insert(30,root
[i
],root
[i
-1]);
}
for(int i
=1,l
,r
,x
;i
<=m
;i
++)
{
scanf("%d%d%d",&x
,&l
,&r
);
for(int j
=0;j
<30;j
++,x
/=2) _div
[j
]=1-x
%2;
printf("%d\n",st
.ask(30,root
[r
+1],root
[l
]));
}
return 0;
}