XOR Queries(莫队+trie)

题目链接:

XOR Queries

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

输入描述

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

    对于每组测试数据:

    第一行为两个整数nn,mm(1 \leq n, m \leq 500001n,m50000)。

    第二行为nn个整数表示数组CC(0 \leq C[i] \leq 10^{9}0C[i]109​​)。

    接下来mm行中,第ii行有四个整数L_{i}Li​​,R_{i}Ri​​,A_{i}Ai​​,B_{i}Bi​​(1 \leq L_{i} \leq R_{i} \leq n1Li​​Ri​​n, 0 \leq A_{i}, B_{i} \leq 10^{9}0Ai​​,Bi​​109​​)。

输出描述

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

样例输入

1
5 2
1 2 3 4 5
1 3 1 1
2 5 2 3

样例输出

2
2

题意:给出一个数列,然后m个询问,每一询问是问这个区间里面有多少个a[k]^A>=B;
思路:显然是一个莫队,trie树里面存的是当前区间里面的数,所以需要trie的insert和del操作,
然后就是询问这个区间里面有多少个异或大于等于B就贪心就好了,注意最后相等的情况,需要写个query就好;
AC代码:
#include <bits/stdc++.h>
using namespace std;
const int maxn=5e4+10;
int n,m,a[maxn],ans[maxn];
struct node
{
    int l,r,a,b,id,sq;
}po[maxn];
int cmp(node x,node y)
{
    if(x.sq==y.sq)return x.r<y.r;
    return x.l<y.l;
}
int ch[31*maxn][2],val[31*maxn];
int sz;
inline void init()
{
    sz=1;
    memset(ch[0],0,sizeof(ch[0]));
}
inline void insert(int x)
{
    int u=0,len=30;
    for(int i=len;i>=0;i--)
    {
        int c=((x>>i)&1);
        if(!ch[u][c])
        {
            memset(ch[sz],0,sizeof(ch[sz]));
            val[sz]=0;
            ch[u][c]=sz++;
        }
        u=ch[u][c];
        val[u]++;
    }
}
inline void Delete(int x)
{
    int u=0,len=30;
    for(int i=len;i>=0;i--)
    {
        int c=((x>>i)&1);
        u=ch[u][c];
        val[u]--;
    }
}
inline int query(int A,int B)
{
    int u=0,len=30,sum=0,flag;
    for(int i=len;i>=0;i--)
    {
        int c=((A>>i)&1),d=((B>>i)&1);
        int ha=u;
        if(ch[u][1]&&(c^1)>d)
        {
            int tep=ch[u][1];
            sum=sum+val[tep];
        }
        if(ch[u][0]&&(c^0)>d)
        {
            int tep=ch[u][0];
            sum=sum+val[tep];
        }
        flag=0;
        if(ch[u][1]&&(c^1)==d)u=ch[u][1],flag=1;
        if(ch[u][0]&&(c^0)==d)u=ch[u][0],flag=1;
        if(ha==u)break;
    }
    if(flag)sum=sum+val[u];
    return sum;
}
int main()
{
    //freopen("in.txt","r",stdin);
    int T;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d%d",&n,&m);
        init();
        int sq=sqrt(n*1.0);
        for(int i=1;i<=n;i++)scanf("%d",&a[i]);
        for(int i=1;i<=m;i++)
        {
            scanf("%d%d%d%d",&po[i].l,&po[i].r,&po[i].a,&po[i].b);
            po[i].id=i;po[i].sq=po[i].l/sq;
        }
        sort(po+1,po+m+1,cmp);
        int l=1,r=0;
        for(int i=1;i<=m;i++)
        {
            while(r<po[i].r)r++,insert(a[r]);
            while(r>po[i].r)Delete(a[r]),r--;
            while(l<po[i].l)Delete(a[l]),l++;
            while(l>po[i].l)l--,insert(a[l]);
            ans[po[i].id]=query(po[i].a,po[i].b);
        }
        for(int i=1;i<=m;i++)printf("%d\n",ans[i]);
    }
    return 0;
}

  

 
posted @ 2017-05-16 22:26  LittlePointer  阅读(440)  评论(0编辑  收藏  举报