[jzoj4598]【NOIP2016模拟7.9】准备食物

来源:互联网 发布:二代身份证照片软件 编辑:程序博客网 时间:2024/04/28 01:27

Description

“~妖梦,我又饿了!”
魂魄妖梦身为西行寺家的专属庭师第二代兼大小姐的西行寺幽幽子的护卫,却承担了为幽幽子准备食物的任务。幽幽子是个非常贪吃的亡灵,所以妖梦经常为食物的问题所困。
现在,妖梦有n盘食物排成一排,第i盘食物有一个属性a[i]。亡灵的体质比较特殊,所以妖梦认为食物的属性很重要。妖梦会进行q次询问,每次给出两个整数r,k,她想知道有多少个区间[i,r](1≤i≤r),区间内所有食物属性值的异或大于等于k。

100%:1≤n,q≤100000 r≤n 0≤k,a[i]≤1,000,000,000

Solution

离线处理问题

在 Trie 上处理

注意到 [i,r]=[1,r][1,i)

在 Trie 上存属性的异或值的前缀和

根据异或的性质去做即可

Code

#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>#define fo(i,x,y) for (int pq = (y),i = (x);i <= pq;++ i)#define fd(i,x,y) for (int pq = (y),i = (x);i >= pq;-- i)#define oo 2139062143using namespace std;typedef double db;typedef long long ll;int lowbit(int x) {return((x)&(-x));}int min(int x,int y){return (x>y)?(y):(x);}int max(int x,int y){return (x>y)?(x):(y);}const int N=100100;struct qy{    int r,k,pos;}p[N];int n,q;int a[N],ans[N];bool gt(int x,int y)//x binary NO.y{    return(x&(1<<(y-1)));}bool cmpr(qy x,qy y){    return(x.r<y.r);}int sz[N*30],chd[N*30][2],col[N*30];int tot=1;void insert(int now,int v,int p){    ++sz[now];    if(!p) return;    int tmp=gt(v,p);    if(!chd[now][tmp]) chd[now][tmp]=++tot,col[tot]=tmp;    insert(chd[now][tmp],v,p-1);}int query(int now,int v,int p,int xr){    if(!sz[now])         return 0;    if(p==1)         return ((col[now]^gt(xr,p))>=gt(v,p))?sz[now]:0;    if((col[now]^gt(xr,p))>gt(v,p))         return(sz[now]);    if((col[now]^gt(xr,p))==gt(v,p))         return(query(chd[now][0],v,p-1,xr)+query(chd[now][1],v,p-1,xr));     if((col[now]^gt(xr,p))<gt(v,p))        return 0;}int main(){    freopen("food.in","r",stdin);    freopen("food.out","w",stdout);    scanf("%d",&n);    fo(i,1,n) scanf("%d", &a[i]),a[i]^=a[i-1];    scanf("%d",&q);    fo(i,1,q)     {        scanf("%d%d",&p[i].r,&p[i].k);        p[i].pos=i;    }    sort(p+1,p+1+q,cmpr);    p[0].r=1;    insert(1,0,30);    fo(i,1,q)    {        fo(j,p[i-1].r,p[i].r-1)             insert(1,a[j],30);        ans[p[i].pos]=query(chd[1][0],p[i].k,30,a[p[i].r])+query(chd[1][1],p[i].k,30,a[p[i].r]);    }    fo(i,1,q) printf("%d\n",ans[i]);    return 0;}