如果没有加法,这就是一道水水的可持久化trie,有了加法,我们就要用可持久化权值线段树,然后按位贪心,查询变成一个区间内是否存在数字。
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#define ll long long
#define inf 1e9
#define eps 1e-8
#define md
#define N 4000010
using namespace std;
const int mxn=262143;
int ch[N][2],sz[N];
int root[200010];
int cnt=0;
void insert(int &i,int pre,int l,int r,int d)
{
i=++cnt; ch[i][0]=ch[pre][0]; ch[i][1]=ch[pre][1]; sz[i]=sz[pre]+1;
if (l==r) return;
int mid=(l+r)>>1;
if (d<=mid) insert(ch[i][0],ch[pre][0],l,mid,d);
else insert(ch[i][1],ch[pre][1],mid+1,r,d);
}
bool query(int L,int R,int l,int r,int ql,int qr)
{
if (ql<=l&&r<=qr) return sz[R]-sz[L]>0;
int mid=(l+r)>>1;
if (qr<=mid) return query(ch[L][0],ch[R][0],l,mid,ql,qr);
if (mid+1<=ql) return query(ch[L][1],ch[R][1],mid+1,r,ql,qr);
return query(ch[L][0],ch[R][0],l,mid,ql,qr)||query(ch[L][1],ch[R][1],mid+1,r,ql,qr);
}
int main()
{
int n,m;
scanf("%d%d",&n,&m);
for (int i=1;i<=n;i++)
{
int x;
scanf("%d",&x);
insert(root[i],root[i-1],0,mxn,x);
}
for (int i=1;i<=m;i++)
{
int b,x,l,r;
scanf("%d%d%d%d",&b,&x,&l,&r); l--;
int ans=0;
for (int d=17;d>=0;d--)
{
if (b&(1<<d))
{
int L=max(ans-x,0),R=(ans|((1<<d)-1))-x;
if (R<0||!query(root[l],root[r],0,mxn,L,R)) ans^=1<<d;
}
else
{
ans^=1<<d;
int L=max(ans-x,0),R=(ans|((1<<d)-1))-x;
if (R<0||!query(root[l],root[r],0,mxn,L,R)) ans^=1<<d;
}
}
printf("%d\n",b^ans);
}
return 0;
}