题目
“~妖梦,我又饿了!”
魂魄妖梦身为西行寺家的专属庭师第二代兼大小姐的西行寺幽幽子的护卫,却承担了为幽幽子准备食物的任务。幽幽子是个非常贪吃的亡灵,所以妖梦经常为食物的问题所困。
现在,妖梦有n盘食物排成一排,第i盘食物有一个属性a[i]。亡灵的体质比较特殊,所以妖梦认为食物的属性很重要。妖梦会进行q次询问,每次给出两个整数r,k,她想知道有多少个区间[i,r](1≤i≤r),区间内所有食物属性值的异或大于等于k。
分析
首先按(r)值从小到大排序。
由于要求异或,首先考虑位数运算。
开一棵Trie,
随便搞搞就可以了。
具体细节就不说了。
#include <cmath>
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <queue>
const long long maxlongint=2147483647;
const long long mo=1000000007;
const long long N=100005;
using namespace std;
struct ddx
{
long long l,r,v;
}tree[5000000];
struct ddx1
{
long long x,y,bef;
}re[N*5];
long long a[N],n,m,tot,ans[N],mi[33];
bool cmp(ddx1 x,ddx1 y)
{
return x.x<y.x;
}
int main()
{
freopen("food.in","r",stdin);
freopen("food.out","w",stdout);
scanf("%lld",&n);
mi[0]=1;
for(long long i=1;i<=31;i++)
{
mi[i]=mi[i-1]*2;
}
for(long long i=1;i<=n;i++)
{
scanf("%lld",&a[i]);
a[i]=a[i-1]^a[i];
}
scanf("%lld",&m);
for(long long i=1;i<=m;i++)
{
scanf("%lld%lld",&re[i].x,&re[i].y);
re[i].bef=i;
}
sort(re+1,re+m+1,cmp);
long long tt=0;
tot=1;
for(long long i=1;i<=m;i++)
{
while(tt<re[i].x)
{
long long k=a[tt],pos=1;
for(long long j=31;j>=0;j--)
{
tree[pos].v++;
if(k>=mi[j])
{
k-=mi[j];
if(!tree[pos].r)
{
tree[pos].r=++tot;
pos=tot;
}
else
{
pos=tree[pos].r;
}
}
else
{
if(!tree[pos].l)
{
tree[pos].l=++tot;
pos=tot;
}
else
{
pos=tree[pos].l;
}
}
if(!j) tree[pos].v++;
}
tt++;
}
long long pos=1,k=re[i].y,l=a[re[i].x];
for(long long j=31;j>=0;j--)
{
if(k>=mi[j])
{
k-=mi[j];
if(l>=mi[j])
{
l-=mi[j];
if(!tree[pos].l)
{
break;
}
else
{
pos=tree[pos].l;
}
}
else
{
if(!tree[pos].r)
{
break;
}
else
{
pos=tree[pos].r;
}
}
}
else
{
if(l>=mi[j])
{
l-=mi[j];
ans[re[i].bef]+=tree[tree[pos].l].v;
pos=tree[pos].r;
}
else
{
ans[re[i].bef]+=tree[tree[pos].r].v;
pos=tree[pos].l;
}
}
if(!j) ans[re[i].bef]+=tree[pos].v;
}
}
for(long long i=1;i<=m;i++)
printf("%lld
",ans[i]);
}