题意:给定一个序列,对于每个询问,给出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 }