zoukankan      html  css  js  c++  java
  • 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
    ",ans[i]);
        }
        return 0;
    }
  • 相关阅读:
    二维数组重复合并 并计算
    处理formdata传递的json数据
    thinkphp lock 锁 的使用和例子
    docker 更新后 和wsl2直接集成
    ubuntu apt 换阿里镜像源
    使用phpstorm将本地代码实时自动同步到远程服务器
    notepad++ markdown主题
    【Git】pull遇到错误:error: Your local changes to the following files would be overwritten by merge:
    hyperf 安装扩展 protobuf
    bt[宝塔]安装redis
  • 原文地址:https://www.cnblogs.com/dyzll/p/6868460.html
Copyright © 2011-2022 走看看