题意:给定一个序列,对于每个询问,给出x,b,l,r,从区间l,r选一个数,使得(ai+b)xor x最大,对于每个询问输出最大值。

如果没有加法的话,这就是裸的可持久化trie,但是有加法后就很恶心了,怎么办?

一般来说异或总是每位独立,然后就进行贪心。这道题我们单独考虑每一位能否为1,贪心去搞。

具体来说,如果x当前一位上是1,那么我们能使这位为1的数的取值区间在a,a|((i<<1)-1)中(其中a是已经确定了的高位,i为当前位),我们只要看是否存在有这么一个数,就能知道能否使得这个位置为1了。0的情况类似,不多加赘述。

别忘了最后a要异或x输出,被坑了一发。

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define N 200005
 4 #define M 1000005
 5 int inline read(){
 6     int x=0,f=1; char a=getchar();
 7     while(a<'0' || a>'9') {if(a=='-') f=-1; a=getchar();}
 8     while(a>='0' && a<='9') x=x*10+a-'0',a=getchar();
 9     return x*f;
10 }
11 int n,m;
12 namespace Chairman_Tree{
13     struct ct{
14         int son[2],sz;
15     }tr[10000005];
16     int size,root[N];
17     void insert(int x,int& y,int l,int r,int v){
18         y=++size; tr[y].sz=tr[x].sz+1;
19         memcpy(tr[y].son,tr[x].son,sizeof(tr[x].son));
20         if(l==r) return;
21         int mid=(l+r)>>1;
22         if(v<=mid) insert(tr[x].son[0],tr[y].son[0],l,mid,v);
23         else insert(tr[x].son[1],tr[y].son[1],mid+1,r,v);
24     }
25     bool query(int x,int y,int l,int r,int L,int R){
26         if(l==L && r==R) return tr[y].sz>tr[x].sz;
27         int mid=(l+r)>>1;
28         if(mid>=R) return query(tr[x].son[0],tr[y].son[0],l,mid,L,R);
29         else if(mid<L) return query(tr[x].son[1],tr[y].son[1],mid+1,r,L,R);
30         else return query(tr[x].son[0],tr[y].son[0],l,mid,L,mid) || query(tr[x].son[1],tr[y].son[1],mid+1,r,mid+1,R);
31     }
32 }
33 #define CT Chairman_Tree
34 int main(){
35     n=read(); m=read();
36     for(int i=1;i<=n;i++) CT::insert(CT::root[i-1],CT::root[i],0,M,read());
37     while(m--){
38         int b=read(),x=read(),L=read(),R=read(),l,r,a=0;
39         for(int i=17;i>=0;i--)
40             if(b&(1<<i)){
41                 l=max(0,a-x); r=(a|((1<<i)-1))-x;
42                 if(!r || !CT::query(CT::root[L-1],CT::root[R],0,M,l,r)) a|=(1<<i);
43             }else{
44                 a|=(1<<i);
45                 l=max(0,a-x); r=(a|((1<<i)-1))-x;
46                 if(!r || !CT::query(CT::root[L-1],CT::root[R],0,M,l,r)) a^=(1<<i); 
47             }
48         printf("%d\n",a^b);
49     }
50     return 0;
51 }