【Luogu】P4462异或序列(莫队)

  题目链接

  观察什么时候x到y之间那一段可以被统计

  xorsum[x-1]^xorsum[y]=k

  xorsum[x-1]=xorsum[y]^k||xorsum[y]=xorsum[x-1]^k

  莫队维护。

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cctype>
#include<cstdlib>
#include<cmath>
#define maxn 200200
using namespace std;
inline long long read(){
    long long num=0,f=1;
    char ch=getchar();
    while(!isdigit(ch)){
        if(ch=='-')    f=-1;
        ch=getchar();
    }
    while(isdigit(ch)){
        num=num*10+ch-'0';
        ch=getchar();
    }
    return num*f;
}

int blo[maxn];
int xum[maxn];
int sum[maxn];
long long ans[maxn];

struct Que{
    int x,y,id;
    bool operator <(const Que a)const{
        if(blo[x]!=blo[a.x])    return blo[x]<blo[a.x];
        return y<a.y;
    }
}q[maxn];

int main(){
    int n=read(),m=read(),e=read();
    int sqt=sqrt(n);
    for(int i=1;i<=n;++i)    blo[i]=(i-1)/sqt+1;
    for(int i=1;i<=n;++i)    xum[i]=xum[i-1]^read();
    for(int i=1;i<=m;++i)    q[i]=(Que){read(),read(),i};
    sort(q+1,q+m+1);
    int lef=1,rig=0;long long now=0;
    for(int i=1;i<=m;++i){
        while(lef<q[i].x-1){
            sum[xum[lef]]--;
            now-=sum[xum[lef]^e];
            lef++;
        }
        while(lef>q[i].x-1){
            lef--;
            now+=sum[xum[lef]^e];
            sum[xum[lef]]++;
        }
        while(rig<q[i].y){
            rig++;
            now+=sum[xum[rig]^e];
            sum[xum[rig]]++;
        }
        while(rig>q[i].y){
            sum[xum[rig]]--;
            now-=sum[xum[rig]^e];
            rig--;
        }
        ans[q[i].id]=now;
    }
    for(int i=1;i<=m;++i)    printf("%lld\n",ans[i]);
    return 0;
}

 

posted @ 2018-04-19 21:19  Konoset  阅读(139)  评论(0编辑  收藏  举报