【JZOJ4598】准备食物

Description

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

Solution

一开始,乱搞了一通,得出一个异或不等式,然后异或是不满足一般的不等式性质的,搞得我打完了主席树,打好了拍之后,出了个数组之后发现错了。
后来比赛还剩下40分钟的时候打完了第三题有看了一眼第二题:不是裸的字典树吗……
打了个可持久化trie成功搞了过去。
主要思路:[i,r]表示a[i] xor a[i+1] xor …… xor a[r],所以[i,r]=[1,i-1] xor [1,r],然后把数值[1,r]对trie进行xor操作,保证异或完的数≥k的方案数,在trie上如果k的二进制位是1,那么就只能异或成1,如果是0,加上异或成1的答案,在往异或成0的搜。

Code

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#define fo(i,a,b) for(i=a;i<=b;i++)
#define rep(i,a) for(i=first[a];i;i=next[i])
#define fod(i,a,b) for(i=a;i>=b;i--)
typedef long long ll;
using namespace std;
const int maxn=100007;
int i,j,k,l,n,m,num,p,da,root[maxn],ans;
int a[maxn],sum[maxn],er[maxn];
struct node{
    int sum,son[2];
}t[maxn*32];
void build(int x,int y,int z){
    int i;
    fod(i,31,1){
        int q=((z&er[i])>0);
        t[x].sum=t[y].sum+1;
        t[x].son[q^1]=t[y].son[q^1];t[x].son[q]=++num;
        x=num;y=t[y].son[q];
    }
    t[x].sum=t[y].sum+1;
}  
void find(int x,int y,int z){
    int i;
    fod(i,31,1){
        int q=((y&er[i])>0),p=((z&er[i])>0);
        if(p){
            x=t[x].son[q^1];
        }
        else{
            ans+=t[t[x].son[1^q]].sum;
            x=t[x].son[q];
        }
    }
    ans+=t[x].sum;
}
int main(){
    freopen("food.in","r",stdin);
    freopen("food.out","w",stdout);
    scanf("%d",&n);
    fo(i,1,50)er[i]=1<<(i-1);
    fo(i,1,n)scanf("%d",&a[i]),sum[i]=sum[i-1]^a[i];
    build(root[0]=++num,0,0);
    fo(i,1,n)build(root[i]=++num,root[i-1],sum[i]);
    for(scanf("%d",&m);m;m--){
        scanf("%d%d",&k,&l);
        ans=0;
        find(root[k-1],sum[k],l);
        printf("%d\n",ans);
    }

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值