Description
“~妖梦,我又饿了!”
魂魄妖梦身为西行寺家的专属庭师第二代兼大小姐的西行寺幽幽子的护卫,却承担了为幽幽子准备食物的任务。幽幽子是个非常贪吃的亡灵,所以妖梦经常为食物的问题所困。
现在,妖梦有n盘食物排成一排,第i盘食物有一个属性a[i]。亡灵的体质比较特殊,所以妖梦认为食物的属性很重要。妖梦会进行q次询问,每次给出两个整数r,k,她想知道有多少个区间[i,r](1≤i≤r),区间内所有食物属性值的异或大于等于k。
Solution
用字典树来做,按二进制位的高位开始做,
查询就直接查,
修改的时候需要做一个指针,不可以直接改,否则可能超时,
复杂度:
O(2∗30n)
Code
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define fod(i,a,b) for(int i=a;i>=b;i--)
#define aqr a[q].g[g[c][1]]
#define aql a[q].g[g[c][0]]
using namespace std;
const int N=100500,M=30;
int read(int &n)
{
char ch=' ';int q=0,w=1;
for(;(ch!='-')&&((ch<'0')||(ch>'9'));ch=getchar());
if(ch=='-')w=-1,ch=getchar();
for(;ch>='0'&&ch<='9';ch=getchar())q=q*10+ch-48;n=q*w;return n;
}
int m,m1,n,ans,a0=1;
int er[M+2],s[N],b[N];
struct qqww
{int g[2],s;}a[50*N];
int g[M+2][2];
struct wwqq
{int r,k,i;}bs[N];
bool PX(wwqq q,wwqq w){return q.r<w.r||(q.r==w.r&&q.k<w.k);}
void turn(int w)
{
fo(i,1,M)if(er[i]&w)swap(g[i][0],g[i][1]);
}
void add(int q,int w,int c)
{
a[q].s++;
if(c>M)return;
if(w&er[c])
{
if(!aqr)aqr=++a0;
add(aqr,w,c+1);
}else
{
if(!aql)aql=++a0;
add(aql,w,c+1);
}
}
int find(int q,int w,int c)
{
if(c>M+1)return 0;
if(!q)return 0;
if(w&er[c])return find(aqr,w,c+1);
else return (c<M?find(aql,w,c+1)+a[aqr].s:a[q].s);
}
int main()
{
freopen("food.in","r",stdin);
freopen("food.out","w",stdout);
er[1]=1<<(M-1);fo(i,2,M+1)er[i]=er[i-1]>>1;
read(n);
fo(i,1,n)read(b[i]);
read(m1);
fo(i,1,m1)read(bs[i].r),read(bs[i].k),bs[i].i=i;
fo(i,0,M+1)g[i][1]=1;
sort(bs+1,bs+1+m1,PX);
fo(I,1,m1)
{
fo(i,bs[I-1].r+1,bs[I].r)
{
turn(b[i]);
add(1,b[i],1);
}
s[bs[I].i]=find(1,bs[I].k,1);
}
fo(i,1,m1)printf("%d\n",s[i]);
return 0;
}