输出 m 行,每行 1 个整数,ymax ,表示该位顾客选择的最美味的菜的美味值。
按位异或+主席树~
异或各位互不影响,所以我们按照每一位来计算,从高往低,如果能让ans的该位==1就加上。这里需要我们在位置[l,r]中找到是否有数属于[L,R],我们用主席树来实现这个查找过程。
要注意的是计算数的范围[L,R]时区间可能为负,要判掉。
#include<cstdio> #include<iostream> using namespace std; int n,m,x,c[4000001],root[200001],ls[4000001],rs[4000001],ans,cnt,b,l,r,ll,rr; int read() { int x=0,f=1;char ch=getchar(); while(ch<'0' || ch>'9') {if(ch=='-') f=-1;ch=getchar();} while(ch>='0' && ch<='9') {x=x*10+ch-'0';ch=getchar();} return x*f; } void add(int l,int r,int las,int &now,int v) { now=++cnt;c[now]=c[las]+1; if(l==r) return; int mid=l+r>>1; ls[now]=ls[las];rs[now]=rs[las]; if(mid>=v) add(l,mid,ls[las],ls[now],v); else add(mid+1,r,rs[las],rs[now],v); } bool cal(int l,int r,int las,int now,int u,int v) { if(l>=u && r<=v) return c[now]-c[las]; int kkz=0,mid=l+r>>1; if(u<=mid) kkz+=cal(l,mid,ls[las],ls[now],u,v); if(v>mid) kkz+=cal(mid+1,r,rs[las],rs[now],u,v); return kkz; } int main() { n=read();m=read(); for(int i=1;i<=n;i++) x=read(),add(0,100000,root[i-1],root[i],x); while(m--) { b=read();x=read();l=read();r=read();ans=0; for(int i=18;~i;i--) { if((b>>i)&1) { ll=min(100000,max(ans-x,0)); rr=min(100000,ans+(1<<i)-x-1); if(rr<0 || !cal(0,100000,root[l-1],root[r],ll,rr)) ans^=(1<<i); } else { ll=min(100000,max(ans-x+(1<<i),0)); rr=min(100000,ans+(1<<i+1)-x-1); if(rr>=0 && cal(0,100000,root[l-1],root[r],ll,rr)) ans^=(1<<i); } } printf("%d\n",ans^b); } return 0; }