标签:eps gis 出现 min span \n 异或 namespace bit
异或最大值应该是要用\(trie\)树,从高位往低位贪心,虽然这里询问区间的数都要加上\(x\),但是仍然可以利用这个思想
从高往低位考虑,我们要找一个加上\(x\)后当前二进制位\(j\)不等于\(b\)的当前位的数,假设\(b\)当前位为0,我们就要现在找个数加上\(x\)后当前位\(j\)为1,记之前选出的数为\(ans\),那么我们就要找一个在\([ans+(1<<j)-x,ans+(1<<j)-(1<<j)-1-x]\)区间内的数;如果\(b\)当前位为1,那么取值范围为\([ans-x,ans-(1<<j)-1-x]\).如果有这个数,那么\(ans\)当前位\(j\)就可以等于\(b\)当前位\(xor\ 1\),否则就反过来
这个操作可以用主席树查询某区间的数出现次数的操作实现
#include<bits/stdc++.h>
#define LL long long
#define il inline
#define re register
#define db double
#define eps (1e-7)
using namespace std;
const int N=500000+10;
const LL inf=1ll<<45;
il LL rd()
{
re LL x=0,w=1;re char ch=0;
while(ch<'0'||ch>'9') {if(ch=='-') w=-1;ch=getchar();}
while(ch>='0'&&ch<='9') {x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
return x*w;
}
#define mid ((l+r)>>1)
int s[N*20],ch[N*20][2],rt[N],tt;
int n,m,kk,L,R,a[N];
il void inst(int p)
{
rt[p]=++tt;
int o1=rt[p],o2=rt[p-1],l=0,r=n;
s[o1]=s[o2]+1;
do
{
if(a[p]<=mid)
{
ch[o1][0]=++tt,ch[o1][1]=ch[o2][1];
o1=ch[o1][0],o2=ch[o2][0],r=mid;
}
else
{
ch[o1][0]=ch[o2][0],ch[o1][1]=++tt;
o1=ch[o1][1],o2=ch[o2][1],l=mid+1;
}
s[o1]=s[o2]+1;
}
while(l<r);
}
int quer(int o1,int o2,int l,int r,int ll,int rr)
{
if(ll<=l&&r<=rr) return s[o1]-s[o2];
int an=0;
if(ll<=mid) an+=quer(ch[o1][0],ch[o2][0],l,mid,ll,rr);
if(rr>mid) an+=quer(ch[o1][1],ch[o2][1],mid+1,r,ll,rr);
return an;
}
bool ok(int l,int r,int ll,int rr)
{
ll=max(ll,0),rr=min(rr,n);
return ll<=rr?quer(rt[r],rt[l-1],0,n,ll,rr):0;
}
int q;
int main()
{
///no O2
m=rd(),q=rd();
for(int i=1;i<=m;i++) n=max(n,a[i]=rd());
for(int i=1;i<=m;i++) inst(i);
while(q--)
{
int b=rd(),x=rd(),ll=rd(),rr=rd(),ans=0;
for(int i=17;i>=0;i--)
{
int nw=ans|(((b>>i&1)^1)<<i);
if(ok(ll,rr,nw-x,nw+(1<<i)-1-x)) ans=nw;
else ans|=(b>>i&1)<<i;
}
printf("%d\n",ans^b);
}
return 0;
}
标签:eps gis 出现 min span \n 异或 namespace bit
原文地址:https://www.cnblogs.com/smyjr/p/9739276.html