[Cqoi2018]异或序列

Description

已知一个长度为 n 的整数数列 a[1],a[2],…,a[n] ,给定查询参数 l、r ,问在 [l,r] 区间内,有多少连续子
序列满足异或和等于 k 。
也就是说,对于所有的 x,y (l≤x≤y≤r),能够满足a[x]^a[x+1]^…^a[y]=k的x,y有多少组。
 

Input

输入文件第一行,为3个整数n,m,k。
第二行为空格分开的n个整数,即ai,a2,….an。
接下来m行,每行两个整数lj,rj,表示一次查询。
1≤n,m≤105,O≤k,ai≤105,1≤lj≤rj≤n

Output

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

Sample Input

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

Sample Output

4
2
1
2
1

HINT

 

Source

 
预处理前缀和。
若i-j,异或和为K。
则 sum[i-1]^sum[j]=k。
则用莫队处理,加入sum[i-1] ,每次(O1)处理,ans+=cnt[sum[i-1]^k].
#include <bits/stdc++.h>
#define maxn 100005
using namespace std;
struct quer
{
    int l,r,pos;
}query[maxn];
int block;
bool cmp(quer a,quer b)
{
    if(a.l/block!=b.l/block) return (a.l/block)<(b.l/block);
    return a.r<b.r;
}
int now=0,k;
int ans[maxn];
int sum[maxn];
int cnt[maxn];
void add(int x)
{   cnt[x]++;
    now+=cnt[x^k];
}
void dele(int x)
{   cnt[x]--;
    now-=cnt[x^k];
}
int main()
{
    int n,m,i;
    int a[maxn];
    cin>>n>>m>>k;
    for(i=1;i<=n;i++)
    {
        scanf("%d",&a[i]);
    }
    block=sqrt(n);
    for(i=1;i<=n;i++)
    {
        sum[i]=sum[i-1]^a[i];
    }
    for(i=1;i<=m;i++)
    {
        scanf("%d%d",&query[i].l,&query[i].r);
        query[i].pos=i;
        query[i].l--;
    }
    sort(query+1,query+1+m,cmp);
    int l=1,r=0;
    for(i=1;i<=m;i++)
    {
      while(l<query[i].l)
      {
          dele(sum[l]);
          l++;
      }
      while(l>query[i].l)
      {
          l--;
          add(sum[l]);
      }
      while(r<query[i].r)
      {   r++;
          add(sum[r]);
      }
      while(r>query[i].r)
      {
          dele(sum[r]);
          r--;
      }
      ans[query[i].pos]=now;
    }
    for(i=1;i<=m;i++)
    {
        printf("%d\n",ans[i]);
    }
    return 0;
}

  

posted @ 2018-08-07 20:24  行远山  阅读(240)  评论(0编辑  收藏  举报