异或序列

题目:

https://www.luogu.com.cn/problem/P4462

利用的异或的前缀和性质,

有多少个区间[l,r]满足异或起来为k
异或满足前缀和

有多少个sumr^sum(l-1) =k

sum(l-1) =k^sumr

要将l换成l-1

#include<bits/stdc++.h>
#include<stdio.h>
using namespace std;
const int maxn=1e5+7;
int n,m,k,block,belong[maxn],sum[maxn],arr[maxn],has[maxn],ans[maxn];
inline int gcd(int a, int b)
{ int r; while (b > 0) { r = a % b; a = b; b = r; }return a; }
struct Q
{
    int l,r,id;
    bool operator <(const Q &b)
    {
        if(belong[l]!=belong[b.l])
            return l<b.l;
        else
            return r<b.r;
    }
}query[maxn];
int L,R;
int ret=0;
int fa=0;
int s=0;

inline void add(int x)
{
  ret+=has[x^k];
  ++has[x];

}
inline void del(int x)
{   --has[x];
  ret-=has[x^k];
}
//´Ó[L,R]×ªÒÆµ½[l,r]
/*
void GetNew(int l,int r,int L,int R)
{
    while(R<r) add(arr[++R]);
    while(L>l) add(arr[--L]);
    while(R>r) del(arr[R--]);
    while(L<l) del(arr[L++]);
}
*/
int main()
{
    scanf("%d%d%d",&n,&m,&k);
     block=sqrt(n);

  for(int i=1;i<=n;++i)
  {  scanf("%d",&arr[i]);
arr[i]^=arr[i-1];
       belong[i]=(i-1)/block+1;
  }
 int ans[maxn];
  for(int i=1;i<=m;++i)
  {
    int l,r;
    scanf("%d%d",&l,&r);

    query[i]={l-1,r,i};
  }
  sort(query+1,query+m+1);
 L=1;
  for(int i=1;i<=m;++i)
  {  int l=query[i].l;
     int r=query[i].r;
     int id=query[i].id;
      //auto[l,r,id]=query[i];
      while(R<r) add(arr[++R]);
      while(L>l) add(arr[--L]);
      while(R>r) del(arr[R--]);
      while(L<l) del(arr[L++]);
      //printf("ret=%d\n",ret);
      ans[id]=ret;
  }
  for(int i=1;i<=m;++i)
  {   printf("%d\n",ans[i]);
  }
}

 

posted @ 2021-08-12 10:15  废柴废柴少女  阅读(40)  评论(0)    收藏  举报