题目链接:戳我
如果没有偏移的话,就是模板了,但是加上了偏移,肯定不能直接上01trie了。
看到异或,我们想到要按位处理。
因为只有a和原先的区间中间的数有关,因为是区间,所以先把它放到主席树里面。然后之后查询的话,每输入一个b和x,我们可以按位贪心的和b异或。
具体是什么意思呢,就是如果当前b的第i位为1的话,我们就要看看这个区间里面有没有存在的。
然后答案累加上该位的贡献,然后继续在这个基础上进行上面的贪心操作即可。
但是有个问题
代码如下:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#define MAXN 200010
using namespace std;
int n,m,tot,ans;
int a[MAXN+10],rt[MAXN+10];
struct Node{int ls,rs,sum;}t[MAXN*32];
inline void update(int &x,int f,int l,int r,int k)
{
x=++tot;
t[x]=t[f];t[x].sum++;
if(l==r) return;
int mid=(l+r)>>1;
if(k<=mid) update(t[x].ls,t[f].ls,l,mid,k);
else update(t[x].rs,t[f].rs,mid+1,r,k);
}
inline int query(int x,int f,int l,int r,int ll,int rr)
{
int cur=t[x].sum-t[f].sum,cur_ans=0;
if(ll<=l&&r<=rr) return cur;
int mid=(l+r)>>1;
if(ll<=mid) cur_ans+=query(t[x].ls,t[f].ls,l,mid,ll,rr);
if(mid<rr) cur_ans+=query(t[x].rs,t[f].rs,mid+1,r,ll,rr);
return cur_ans;
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("ce.in","r",stdin);
#endif
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
update(rt[i],rt[i-1],1,MAXN,a[i]);
}
// for(int i=1;i<=n;i++) printf("a[%d]=%d
",i,a[i]); puts("");
// for(int i=1;i<=n;i++) printf("rt[%d]=%d
",i,rt[i]);
for(int i=1;i<=m;i++)
{
int b,x,l,r,k,ll,rr,ans=0;
scanf("%d%d%d%d",&b,&x,&l,&r);
for(int j=17;j>=0;j--)
{
if(b&(1<<j))
{
ll=ans,rr=ans+(1<<j)-1;
k=0;
}
else
{
ll=ans+(1<<j),rr=ans+(1<<(j+1))-1;
k=1;
}
if(!query(rt[r],rt[l-1],1,MAXN,max(1,ll-x),min(MAXN,rr-x))) k^=1;
ans|=(k<<j);
}
printf("%d
",ans^b);
}
return 0;
}