题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4571
区间找异或值最大,还带加法,可以用主席树;
可以按位考虑,然后通过加上之前已经有的答案、减去题目给的那个 x ,得到满足这一位最大的值的范围,查找一下有没有即可;
注意如果写 b&(1<<j) ,这个不仅是 0 或 1!所以用个 bool 类型存下来。
代码如下:
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #define mid ((l+r)>>1) using namespace std; int const xn=2e5+5,mx=(1<<18)-1,xm=xn*20; int n,m,cnt,sum[xm],ls[xm],rs[xm],rt[xn]; int rd() { int ret=0,f=1; char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=0; ch=getchar();} while(ch>='0'&&ch<='9')ret=(ret<<3)+(ret<<1)+ch-'0',ch=getchar(); return f?ret:-ret; } void insert(int &x,int y,int l,int r,int v) { x=++cnt; sum[x]=sum[y]+1; ls[x]=ls[y]; rs[x]=rs[y]; if(l==r)return; if(v<=mid)insert(ls[x],ls[y],l,mid,v); else insert(rs[x],rs[y],mid+1,r,v); } int query(int x,int y,int l,int r,int L,int R) { if(l>=L&&r<=R)return sum[y]-sum[x]; int ret=0; if(mid>=L)ret+=query(ls[x],ls[y],l,mid,L,R); if(mid<R)ret+=query(rs[x],rs[y],mid+1,r,L,R); return ret; } int main() { n=rd(); m=rd(); for(int i=1,x;i<=n;i++) { x=rd(); insert(rt[i],rt[i-1],0,mx,x); } for(int i=1,b,x,l,r,ans;i<=m;i++) { b=rd(); x=rd(); l=rd(); r=rd(); ans=0; for(int j=17;j>=0;j--) { int L,R; bool k=(b&(1<<j));//bool!! if(k)//这一位应填0 L=max(ans-x,0),R=min(ans-x+(1<<j)-1,mx); else L=max(ans-x+(1<<j),0),R=min(ans-x+(1<<(j+1))-1,mx); if(L<=R&&query(rt[l-1],rt[r],0,mx,L,R))ans+=(1<<j)*(k^1); else ans+=(1<<j)*k; } printf("%d ",ans^b); } return 0; }