zoukankan      html  css  js  c++  java
  • [莫队算法]异或序列

    题目描述

    已知一个长度为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。

    思路:维护区间内每个数x出现频率(cnt[x]),以及区间内每个数x对答案的贡献(cnt[x^k]--因为x^(x^k)=k),这两个信息可以在O(1)内由区间[L,R]转移到相邻区间;

    AC代码:

    #include <iostream>
    #include<cstdio>
    #include<cmath>
    #include<algorithm>
    using namespace std;
    
    int n,m,k;
    int a[100010];
    int cnt[100010];
    int ans[100010];
    int block;
    int ret;
    
    struct Query{
      int l,r,id;
    }query[100010];
    
    bool cmp(Query a,Query b){
      if(a.l/block==b.l/block) return a.r<b.r;
      else return a.l/block<b.l/block;
    }
    
    void add(int pos){
      cnt[a[pos]]++;ret+=cnt[a[pos]^k];
    }
    
    void sub(int pos){
      ret-=cnt[a[pos]^k];cnt[a[pos]]--;
    }
    
    int main()
    {
        scanf("%d%d%d",&n,&m,&k);
        for(int i=1;i<=n;i++) scanf("%d",&a[i]),a[i]^=a[i-1];
        for(int i=1;i<=m;i++) scanf("%d%d",&query[i].l,&query[i].r),query[i].l--,query[i].id=i;//注意query[i].l要自减1
        block=(int)sqrt(n);
        sort(query+1,query+1+m,cmp);
        int L=1,R=0;
        for(int i=1;i<=m;i++){
            while(R<query[i].r) {R++;add(R);}
            while(R>query[i].r) {sub(R);R--;}
            while(L<query[i].l) {sub(L);L++;}
            while(L>query[i].l) {L--;add(L);}
            ans[query[i].id]=ret;
        }
        for(int i=1;i<=m;i++) printf("%d
    ",ans[i]);
        return 0;
    }
    转载请注明出处:https://www.cnblogs.com/lllxq/
  • 相关阅读:
    模块
    Queue(队列)
    Stack(栈)
    Vector(容器)
    位图像素的颜色
    大数处理之三(除法)
    大数处理之二(幂运算)
    浮点数(double)的优势
    大数处理之一(加法和乘法)
    Depth-First Search
  • 原文地址:https://www.cnblogs.com/lllxq/p/9439282.html
Copyright © 2011-2022 走看看