• 异或序列


    异或序列

    时间限制: 1 Sec  内存限制: 128 MB

    题目描述

    已知一个长度为n的整数数列a1,a2,…,an,给定查询参数l、r,问在al,al+1,…,ar区间内,有多少子序列满足异或和等于k。也就是说,对于所有的x,y(l≤x≤y≤r),满足ax⊕ax+1⊕⋯⊕ay=k的x,y有多少组。

    输入

    输入第一行为3个整数n,m,k。第二行为空格分开的n个整数,即a1,a2,…,an。接下来m行,每行两个整数lj,rj,代表一次查询。

    输出

    输出共m行,对应每个查询的计算结果。

    样例输入

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

    样例输出

    4
    2
    1
    2
    1
    

    提示

    对于30%的数据,1≤n,m≤1000。
    对于100%的数据,1≤n,m≤105,0≤k,ai≤105,1≤lj≤rj≤n。

    来源/分类

    重庆OI2018 


    莫队:转移考虑维护sum数组,sum[i]表示当前区间内有多少个数和k异或为i。即x^k=i;
    这样sum[i]就是有多少个数和i异或为k。
    #include<bits/stdc++.h>
    #define N 100500
    using namespace std;
    int a[N+5];
    int sum[N*10+5]= {0};
    int l,r,n,k,base;
    
    int l_l_move()
    {
        if(l<=0)return 0;
        l--;
        int now=sum[a[l]];
        sum[a[l]^k]++;
        return now;
    }
    
    int r_r_move()
    {
        if(r>=n)return 0;
        r++;
        int now=sum[a[r]];
        sum[a[r]^k]++;
        return now;
    }
    
    int l_r_move()
    {
        if(l>=n)return 0;
        sum[a[l]^k]--;
        int now=sum[a[l]];
        l++;
        return now;
    }
    
    int r_l_move()
    {
        if(r<=0)return 0;
        sum[a[r]^k]--;
        int now=sum[a[r]];
    
    
        r--;
        return now;
    }
    
    typedef struct
    {
        int l,r,index,ans;
    } ss;
    int cmp(ss a,ss b)
    {
        if(a.l/base!=b.l/base)return (a.l/base)<(b.l/base);
        return a.r<b.r;
    }
    ss Array[N];
    long long Ans[N];
    
    int main()
    {
        int m;
        scanf("%d %d %d",&n,&m,&k);
        base=sqrt(n);
        for(int i=1; i<=n; i++)scanf("%d",&a[i]);
        for(int i=2; i<=n; i++)a[i]=a[i-1]^a[i];
    
        for(int i=1; i<=m; i++)
    
            scanf("%d %d",&Array[i].l,&Array[i].r),Array[i].index=i;
    
        sort(Array+1,Array+1+m,cmp);
    
        long long ans=0;
        l=r=Array[1].l;
        sum[a[l]^k]++;
    
        for(int i=1; i<=m; i++)
        {
            Array[i].l--;
            while(l<Array[i].l)ans-=l_r_move();
            while(l>Array[i].l)ans+=l_l_move();
            while(r>Array[i].r)ans-=r_l_move();
            while(r<Array[i].r)ans+=r_r_move();
    
            Ans[Array[i].index]=ans;
    
        }
    
        for(int i=1; i<=m; i++)
            printf("%lld
    ",Ans[i]);
    
        return 0;
    }
    View Code
  • 相关阅读:
    Lucene.Net
    关于数据库优化问题总结
    网页幻灯片效果
    ASP.NET邮件发送
    【收藏】悟透JavaScript(李战)
    JS之显示、隐藏控件方法
    初学自定义验证码
    js之判断浏览器类型及版本号
    js清空上传控件的值
    vs2008学习之路
  • 原文地址:https://www.cnblogs.com/tian-luo/p/9439605.html
Copyright © 2020-2023  润新知