建立主席树,然后从高位到低位贪心就好了。
#include<iostream>
#include<cstdio>
using namespace std;
const int MAXN=100000;
const int N=200005;
const int M=5000005;
int n,m,size;
int root[N];
int ls[M],rs[M],sum[M];
inline int read()
{
int a=0,f=1; char c=getchar();
while (c<'0'||c>'9') {if (c=='-') f=-1; c=getchar();}
while (c>='0'&&c<='9') {a=a*10+c-'0'; c=getchar();}
return a*f;
}
void update(int l,int r,int x,int &y,int val)
{
y=++size;
ls[y]=ls[x]; rs[y]=rs[x]; sum[y]=sum[x]+1;
if (l==r) return;
int mid=l+r>>1;
if (val<=mid) update(l,mid,ls[x],ls[y],val);
else update(mid+1,r,rs[x],rs[y],val);
}
bool find(int l,int r,int x,int y,int X,int Y)
{
if (sum[y]-sum[x]==0) return false;
if (X==l&&r==Y) return true;
int mid=l+r>>1;
if (Y<=mid) return find(l,mid,ls[x],ls[y],X,Y);
else if (X>mid) return find(mid+1,r,rs[x],rs[y],X,Y);
else return find(l,mid,ls[x],ls[y],X,mid)|find(mid+1,r,rs[x],rs[y],mid+1,Y);
}
int main()
{
n=read(); m=read();
for (int i=1;i<=n;i++)
update(0,MAXN,root[i-1],root[i],read());
for (int i=1;i<=m;i++)
{
int L=0,R=(1<<19)-1;
int b=read(),x=read(),l=read(),r=read();
for (int i=18;~i;i--)
{
int mid=L+R>>1;
if ((b>>i)&1)
if (find(0,MAXN,root[l-1],root[r],L-x,mid-x)) R=mid; else L=mid+1;
else
if (find(0,MAXN,root[l-1],root[r],mid+1-x,R-x)) L=mid+1; else R=mid;
}
printf("%d\n",b^L);
}
return 0;
}