XOR Queries

XOR Queries

时间限制: 1000ms   内存限制: 256M

    给出一个长度为n的数组C,回答m个形式为(L,R,A,B)的询问,含义为存在多少个不同的数组下标k[L,R]满足C[k]AB(式中为异或运算)。

输入第一行为一个整数T,表示一共有T组测试数据。

对于每组测试数据:

第一行为两个整数nm1n,m50000)。

第二行为n个整数表示数组C0C[i]109)。

接下来m行中,第i行有四个整数LiRiAiBi1LiRin0Ai,Bi109)。

对于每次询问:输出一个整数表示满足条件的数组下标数目。

 复制
1
5 2
1 2 3 4 5
1 3 1 1
2 5 2 3
2
2
分析:区间问题很容易想到莫队;
   然后有了区间内所有数,怎么查x^a>=b;
   考虑异或,建01字典树插入删除查询即可;
代码:
#include <bits/stdc++.h>
using namespace std;
const int maxn=5e4+10;
int n,m,k,t,a[maxn],bel[maxn],tot,cnt,ans[maxn],ch[maxn*31][2],sz[maxn*31],num;
long long ret;
struct node
{
    int l,r,id,block,c,d;
    bool operator<(const node&p)const
    {
        return block==p.block?r<p.r:block<p.block;
    }
}qu[maxn];
void insert(int x)
{
    int pos=0;
    for(int i=30;i>=0;i--)
    {
        int y=(x>>i&1);
        if(ch[pos][y]==0)
        {
            ch[pos][y]=++num;
            ch[num][0]=ch[num][1]=0;
            sz[ch[pos][y]]=0;
        }
        sz[ch[pos][y]]++;
        pos=ch[pos][y];
    }
}
void del(int x)
{
    int pos=0;
    for(int i=30;i>=0;i--)
    {
        int y=(x>>i&1);
        sz[ch[pos][y]]--;
        pos=ch[pos][y];
    }
}
int query(int x,int y)
{
    int ret=0,pos=0;
    for(int i=30;i>=0;i--)
    {
        int z=(x>>i&1),w=(y>>i&1);
        if(w==1)
        {
            pos=ch[pos][z^1];
            if(i==0)ret+=sz[pos];
        }
        else ret+=sz[ch[pos][z^1]],pos=ch[pos][z];
        if(pos==0)break;
    }
    return ret;
}
int main()
{
    int i,j;
    scanf("%d",&t);
    while(t--)
    {
        cnt=0;
        num=0;
        sz[0]=0;
        tot=0;
        ch[0][0]=ch[0][1]=0;
        scanf("%d%d",&n,&m);
        int sz=(int)sqrt(n);
        for(i=1;i<=n;i++)
        {
            bel[i]=tot;
            if(++cnt==sz)tot++,cnt=0;
        }
        for(i=1;i<=n;i++)scanf("%d",&a[i]);
        for(i=1;i<=m;i++)scanf("%d%d%d%d",&qu[i].l,&qu[i].r,&qu[i].c,&qu[i].d),qu[i].id=i,qu[i].block=bel[qu[i].l];
        sort(qu+1,qu+m+1);
        int l=1,r=0;
        for(i=1;i<=m;i++)
        {
            while(r < qu[i].r)
            {
                insert(a[++r]);
            }
            while(l > qu[i].l)
            {
                insert(a[--l]);
            }
            while(r > qu[i].r)
            {
                del(a[r--]);
            }
            while(l < qu[i].l)
            {
                del(a[l++]);
            }
            ans[qu[i].id]=query(qu[i].c,qu[i].d);
        }
        for(i=1;i<=m;i++)printf("%d\n",ans[i]);
    }
    return 0;
}
posted @ 2017-05-17 17:04  mxzf0213  阅读(452)  评论(0编辑  收藏  举报