题目描述:
给出 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;
}