zoukankan      html  css  js  c++  java
  • 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] igoplus A geq BC[k]AB(式中igoplus⨁为异或运算)。

    输入描述

        输入第一行为一个整数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
    ",ans[i]);
        }
        return 0;
    }
    

      

     
  • 相关阅读:
    DIV 设置垂直居中
    JavaScript--什么是函数
    JavaScript--引用JS外部文件
    JavaScript--如何插入JS
    CSS-类和ID选择器的区别
    CSS-ID选择器
    CSS类选择器
    CSS样式介绍
    HTML--使用mailto在网页中链接Email地址
    HTML--form表单中的label标签
  • 原文地址:https://www.cnblogs.com/zhangchengc919/p/6864062.html
Copyright © 2011-2022 走看看