背景:
只有一天的假期
.
.
.
...
...
题意:
给出
n
n
n个数
a
i
a_i
ai,多组询问,每一次给出
x
,
b
,
l
,
r
x,b,l,r
x,b,l,r,求
b
xor
(
a
i
+
x
)
b\text{ xor }(a_i+x)
b xor (ai+x)的最大值,其中
i
∈
[
l
,
r
]
i∈[l,r]
i∈[l,r]。
思路:
你考虑当
x
=
0
x=0
x=0时就是
01Trie
\text{01Trie}
01Trie了。
但是这一题的
x
x
x有点坑啊。
本质上还是贪心,因为每一位之间不会影响,你要使高位尽可能为
1
1
1即可。
开启懒人模式(https://www.cnblogs.com/Yangrui-Blog/p/9683222.html):
我是真的没想到啊(
tcl
\text{tcl}
tcl)。
代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
#define INF int(1e5)
using namespace std;
int ls[8000010],rs[8000010],root[200010],tot[8000010];
int n,m,len=0,ans;
void change(int last,int &now,int x,int l,int r)
{
if(!now) now=++len;
tot[now]=tot[last]+1;
if(l==r) return;
int mid=(l+r)/2;
if(x<=mid)
{
rs[now]=rs[last];
change(ls[last],ls[now],x,l,mid);
}
else
{
ls[now]=ls[last];
change(rs[last],rs[now],x,mid+1,r);
}
}
int solve(int x,int y,int l,int r,int target_l,int target_r)
{
if(target_l<=l&&r<=target_r) return tot[y]-tot[x];
int mid=(l+r)/2,sum=0;
if(target_l<=mid) sum+=solve(ls[x],ls[y],l,mid,target_l,target_r);
if(mid<target_r) sum+=solve(rs[x],rs[y],mid+1,r,target_l,target_r);
return sum;
}
bool check(int x,int y,int target_l,int target_r)
{
target_l=max(target_l,0),target_r=min(target_r,INF);
if(target_l>target_r) return false;
return solve(root[x-1],root[y],0,INF,target_l,target_r);
}
int main()
{
int b,x,l,r;
scanf("%d %d",&n,&m);
for(int i=1;i<=n;i++)
{
scanf("%d",&x);
change(root[i-1],root[i],x,0,INF);
}
for(int i=1;i<=m;i++)
{
ans=0;
scanf("%d %d %d %d",&b,&x,&l,&r);
for(int j=17;j>=0;j--)
{
int now=ans+((1^((b>>j)&1))<<j);
if(check(l,r,now-x,now+(1<<j)-x-1)) ans=now; else ans+=(((b>>j)&1)<<j);
}
printf("%d\n",ans^b);
}
}