给定长度为 \(n\) 序列 \(a[i]\) ,每次询问区间 \([l,r]\) ,并给定 \(b,x\) 中的一个数 \(p=a[i]\) ,使得最大化 \(b \bigoplus p^x\)
主席树+按位贪心。
我们可以直接贪每一位长什么样子,然后再主席树上区间查询即可。
#include<iostream> #include<cstdio> #include<algorithm> #include<cmath> #include<cstring> #define R register int using namespace std; namespace Luitaryi { inline int g() { R x=0,f=1; register char s; while(!isdigit(s=getchar())) f=s=='-'?-1:f; do x=x*10+(s^48); while(isdigit(s=getchar())); return x*f; } const int N=200010,B=17; int n,m,L,tot,a[N]; int sum[N*20],ls[N*20],rs[N*20],rt[N]; inline void ins(int& tr,int t,int l,int r,int p) { tr=++tot; sum[tr]=sum[t]+1,ls[tr]=ls[t],rs[tr]=rs[t]; if(l==r) return ; R md=l+r>>1; p<=md?ins(ls[tr],ls[t],l,md,p):ins(rs[tr],rs[t],md+1,r,p); } inline bool query(int tr,int t,int l,int r,int LL,int RR) { if(r<LL||l>RR||sum[tr]-sum[t]<=0) return 0; if(l==r) return sum[tr]-sum[t]; R md=l+r>>1; return (LL<=md&&ls[tr]&&query(ls[tr],ls[t],l,md,LL,RR)) ||(RR>md&&rs[tr]&&query(rs[tr],rs[t],md+1,r,LL,RR)); } inline void main() { n=g(),m=g(); for(R i=1;i<=n;++i) a[i]=g(),L=max(L,a[i]); for(R i=1;i<=n;++i) ins(rt[i],rt[i-1],0,L,a[i]); for(R i=1,b,x,l,r,ans;i<=m;++i) { ans=0; b=g(),x=g(),l=g(),r=g(); for(R t=B;~t;--t) { if((b>>t&1)&&!query(rt[r],rt[l-1],0,L,ans-x,ans+(1<<t)-1-x)) ans+=1<<t; if(!(b>>t&1)&&query(rt[r],rt[l-1],0,L,ans+(1<<t)-x,ans+(1<<t+1)-1-x)) ans+=1<<t; } printf("%d\n",b^ans); } } } signed main() {Luitaryi::main(); return 0;}
2019.11.23