题目描述
一家餐厅有 n 道菜,编号 1...n ,大家对第 i 道菜的评价值为 ai(1<=i<=n)。有 m 位顾客,第 i 位顾客的期望值为 bi,而他的偏好值为 xi 。因此,第 i 位顾客认为第 j 道菜的美味度为 bi XOR (aj+xi),XOR 表示异或运算。
第 i 位顾客希望从这些菜中挑出他认为最美味的菜,即美味值最大的菜,但由于价格等因素,他只能从第 li 道到第 ri 道中选择。请你帮助他们找出最美味的菜。
输入输出格式
输入格式:
第1行,两个整数,n,m,表示菜品数和顾客数。第2行,n个整数,a1,a2,...,an,表示每道菜的评价值。第3至m+2行,每行4个整数,b,x,l,r,表示该位顾客的期望值,偏好值,和可以选择菜品区间。1<=n<=2*10^5,0<=ai,bi,xi<10^5,1<=li<=ri<=n(1<=i<=m);1<=m<=10^5
输出格式:
输出 m 行,每行 1 个整数,ymax ,表示该位顾客选择的最美味的菜的美味值。
题意:n个数,m个询问,每个询问要求输出l-r区间内(ai+x) xor b的最大值;
①一个数异或多个数异或最大值,还是可以考虑;
②但是有偏好值,让可持久话字典树变成字典树套主席树,构造到第j位,已经确定好的j位以上的答案(ai+x)是ans,每次在ans^(~b&(1<<j)) 到 ans^(~b&(1<<j)) + (1<<j)-1区间里查询是否有值。
1 #include2 #include 3 using namespace std; 4 const int N = 200010,S = 20,M = 100000; 5 int n,m,sz,a[N],rt[N],ls[N*S],rs[N*S],sum[N*S],bin[S]; 6 char gc(){ 7 static char *p1,*p2,s[1000000]; 8 if(p1==p2) p2=(p1=s)+fread(s,1,1000000,stdin); 9 return(p1==p2)?EOF:*p1++;10 }11 int rd(){12 int x = 0,f = 1; char c = gc();13 while(c<'0'||c>'9') { if(c=='-') f = -1; c = gc();}14 while(c>='0'&&c<='9') x=x*10+c-'0',c = gc();15 return x * f;16 }17 void ins(int &k,int last,int l,int r,int x){18 k = ++sz; 19 sum[k] = sum[last] + 1,ls[k] = ls[last],rs[k] = rs[last];20 if(l==r) return ;21 int mid = (l+r)>>1;22 if(x<=mid) ins(ls[k],ls[last],l,mid,x);23 else ins(rs[k],rs[last],mid+1,r,x);24 }25 bool query(int k1,int k2,int l,int r,int ql,int qr){26 if(l==ql&&qr==r){27 return bool(sum[k2]-sum[k1]);28 }29 else {30 int mid = (l+r)>>1;31 if(qr<=mid) return query(ls[k1],ls[k2],l,mid,ql,qr);32 else if(ql>mid) return query(rs[k1],rs[k2],mid+1,r,ql,qr);33 else return query(ls[k1],ls[k2],l,mid,ql,mid)|query(rs[k1],rs[k2],mid+1,r,mid+1,qr);34 }35 }36 int main()37 { freopen("bzoj4571.in","r",stdin);38 freopen("bzoj4571.out","w",stdout);39 n = rd(); m = rd();40 for(int i = 1;i <= n;i++) ins(rt[i],rt[i-1],0,M,a[i] = rd());41 for(int i = bin[0] = 1;i <= 17;i++) bin[i] = bin[i-1]<<1;42 for(int i = 1,l,r,b,x;i <= m;i++){43 b = rd(); x = rd(); l = rd(); r = rd();44 int ans = 0;45 for(int k = 17;k>=0;k--){46 if(!((b>>k)&1)) ans |= bin[k];47 int L = max(0,ans - x),R = min((ans|(bin[k]-1)) - x,M); 48 if(L > M || R < 0 || !query(rt[r],rt[l-1],0,M,L,R)) ans ^= bin[k];49 }50 printf("%d\n",ans^b);51 }52 return 0;53 }//by tkys_Austin;